View Javadoc

1   /*
2    *  XNap - A P2P framework and client.
3    *
4    *  See the file AUTHORS for copyright information.
5    *
6    *  This program is free software; you can redistribute it and/or modify
7    *  it under the terms of the GNU General Public License as published by
8    *  the Free Software Foundation.
9    *
10   *  This program is distributed in the hope that it will be useful,
11   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   *  GNU General Public License for more details.
14   *
15   *  You should have received a copy of the GNU General Public License
16   *  along with this program; if not, write to the Free Software
17   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18   */
19  
20  package org.xnap.plugin.opennap.net;
21  
22  import java.io.File;
23  import java.util.Hashtable;
24  import java.util.*;
25  
26  import org.apache.log4j.Logger;
27  import org.xnap.*;
28  import org.xnap.gui.StatusBar;
29  import org.xnap.plugin.opennap.net.msg.MessageHandler;
30  import org.xnap.plugin.opennap.net.msg.client.*;
31  import org.xnap.plugin.opennap.net.msg.client.UploadAckMessage;
32  import org.xnap.plugin.opennap.net.msg.server.DirectBrowseRequestMessage;
33  import org.xnap.plugin.opennap.net.msg.server.UploadRequestMessage;
34  import org.xnap.plugin.opennap.user.OpenNapUser;
35  import org.xnap.plugin.opennap.util.OpenNapFileHelper;
36  import org.xnap.transfer.*;
37  import org.xnap.transfer.UploadManager;
38  import org.xnap.util.Preferences;
39  
40  public class OpenNapTransferManager {
41  
42      //--- Constant(s) ---
43  
44      //--- Data field(s) ---
45  
46      private static Logger logger
47  		= Logger.getLogger(OpenNapTransferManager.class);
48  
49  	/***
50  	 * Stores a list of {@link OpenNapDownloadContainer} objects.
51  	 */
52  	private List downloads = new LinkedList();
53  	private Hashtable uploadByRequest = new Hashtable();
54  	private OpenNapResumeRepository repository = new OpenNapResumeRepository();
55  
56      //--- Constructor(s) ---
57  
58      public OpenNapTransferManager()
59      {
60      }
61  
62      //--- Method(s) ---
63  
64  	private synchronized void add(OpenNapDownloadContainer d)
65  	{
66  		DownloadManager.getInstance().add(d);
67  		downloads.add(d);
68  	}
69  
70  	public synchronized void clear()
71  	{
72  		for (Iterator i = downloads.iterator(); i.hasNext();) {
73  			OpenNapDownloadContainer d = (OpenNapDownloadContainer)i.next();
74  			d.stop();
75  
76  			DownloadManager.getInstance().remove(d);
77  			i.remove(); 
78  		}
79  	}
80  
81  	public synchronized void done(OpenNapUpload u)
82  	{
83  		uploadByRequest.remove(u.getHash());
84  	}
85  
86  	/***
87  	 * Creates a new {@link OpenNapDownloadContainer} object for
88  	 * results if no download for results is already running.  
89  	 *
90  	 * @return the created or running download */
91  	public synchronized OpenNapDownloadContainer download
92  		(OpenNapSearchResult results[]) 
93  	{
94  		for (Iterator it = downloads.iterator(); it.hasNext();) {
95  			OpenNapDownloadContainer d 
96  				= (OpenNapDownloadContainer)it.next();
97  			if (d.add(results[0], true)) {
98  				for (int i = 1; i < results.length; i++) {
99  					d.add(results[i], true);
100 				}
101 				StatusBar.setText(XNap.tr("Results added to already running download"));
102 				return d;
103 			}
104 		}
105 
106 		OpenNapDownloadContainer d = new OpenNapDownloadContainer(results);
107 		add(d);
108 		return d;
109 	}
110 
111 	public OpenNapResumeRepository getResumeRepository()
112 	{
113 		return repository;
114 	}
115 
116 	public synchronized void received(DirectBrowseRequestMessage msg)
117 	{
118 		OpenNapUser user = msg.getServer().getUser(msg.nick);
119 		user.setHost(msg.ip);
120 		user.setPort(msg.port);
121 
122 		OpenNapDirectBrowseUpload u = new OpenNapDirectBrowseUpload(user);
123 
124 		// no queueing, start it right away
125 		u.start();
126 	}
127 
128     public synchronized void received(UploadRequestMessage msg) 
129     {
130 		String hash = msg.nick + ":" + msg.filename;
131 		OpenNapUpload u
132 			= (OpenNapUpload)uploadByRequest.get(hash);
133 		if (u == null) {
134 			OpenNapUser user = msg.getServer().getUser(msg.nick);
135 			File file = OpenNapFileHelper.getSharedFile(msg.filename);
136 			if (user.isUploadDenied() || file == null) {
137 				// invalid request
138 				MessageHandler.send
139 					(msg.getServer(), 
140 					 new AcceptFailedMessage(msg.nick, msg.filename));
141 				return;
142 			}
143 
144 			// create new upload object
145 			u = new OpenNapUpload(msg.getServer(), user, file, msg.filename);
146 			u.setHash(hash);
147 			uploadByRequest.put(hash, u);
148 			u.start();
149 
150 			UploadManager.getInstance().add(u);
151 			int pos = u.getQueuePosition();
152 			if (pos > 0) {
153 				QueueLimitMessage m 
154 					= new QueueLimitMessage(msg.nick, msg.filename, pos);
155 				MessageHandler.send(msg.getServer(), m);
156 			}
157 		}
158 		else {
159 			int pos = u.getQueuePosition();
160 			if (pos == 0) {
161 				// some clients need two confirmations before they start
162 				// downloading
163 				MessageHandler.send
164 					(msg.getServer(), 
165 					 new UploadAckMessage(msg.nick, msg.filename));
166 			}
167 			else {
168 				QueueLimitMessage m 
169 					= new QueueLimitMessage(msg.nick, msg.filename, pos);
170 				MessageHandler.send(msg.getServer(), m);
171 				// notify upload that it has been requested
172 				u.requested();
173 			}
174 		}
175 	}
176 
177 	public synchronized void remove(OpenNapDownloadContainer download)
178 	{
179 		downloads.remove(download);
180 	}
181 
182 	/***
183 	 * Restores the resumes.
184 	 */
185 	public synchronized void restore()
186 	{
187 		repository.restore
188 			(new File(Preferences.getInstance().getIncompleteDir()));
189 
190 		for (Iterator it = repository.iterator(); it.hasNext(); ) {
191 			OpenNapDownloadContainerData data 
192 				= (OpenNapDownloadContainerData)it.next();
193 			OpenNapDownloadContainer d = new OpenNapDownloadContainer(data);
194 			add(d);
195 		}
196 	}
197 
198 	public void save()
199 	{
200 		repository.save
201 			(new File(Preferences.getInstance().getIncompleteDir()));
202 	}
203 
204 	public synchronized void startAllDownloads()
205 	{
206 		for (Iterator i = downloads.iterator(); i.hasNext();) {
207 			OpenNapDownloadContainer d = (OpenNapDownloadContainer)i.next();
208 			d.startTransfer();
209 		}
210 	}
211 
212 	// TOFIX
213 //  		if (OpenNapPreferences.getInstance().getWhoisQueryOnTransfer()) {
214 //  			server.getUser(nick).update(true);
215 //  		}
216 
217 //  		File file = OpenNapFileHelper.getRepositoryFile(filename);
218 //  		Upload u = new Upload(nick, file, server, filename);
219 	
220 //  		if (file == null || !server.getUser(nick).isAllowedToDownload()) {
221 //  			logger.warn("rejecting leecher / invalid request: " + nick + " "
222 //  		    			+ filename);
223 //  			u.reject();
224 //  			return;
225 
226 //  		  	if (file == null) {
227 //  				logger.warn("invalid request: " + nick + " " + filename);
228 //  				u.reject();
229 //  				return;
230 //  		  	}
231 	
232 //  		  	if (!server.getUser(nick).isAllowedToDownload()) {
233 //  				logger.warn("rejecting leecher" + nick + " " + filename);
234 //  				u.reject();
235 //  				return;
236 //  		  	}
237 	
238 //  		  	UploadQueue uq = UploadQueue.getInstance();
239 //  		  	logger.debug("upload: " + nick + " " + filename);
240 
241 //  		  	boolean added = uq.add(u);
242 //  		  	if (added) {
243 //  				give the download queue a chance to start the download 
244 //  					right away to avoid sending local queued responses
245 //  					try {
246 //  						Thread.currentThread().sleep(20);
247 //  					}
248 //  					catch (InterruptedException e) {
249 //  					}
250 //  		  	}
251 
252 //  		  	int pos = uq.getLocalQueuePos(u);
253 //  		  	if (pos == -1 && !added) {
254 //  		  	    if (uq.isRunning(u)) {
255 //  					some clients need two confirmations before they start
256 //  						downloading
257 //  						MessageHandler.send
258 //  						(server, new UploadAckMessage(nick, filename));
259 //  		  	    }
260 //  		  	    else {
261 //  					logger.warn("upload queue rejected " + filename);
262 //  					u.reject();
263 //  		  	    }
264 //  		  	}
265 //  		  	else if (pos != -1) {
266 //  				pos == 0 means busy, so we always send pos > 0
267 //  					QueueLimitMessage m = new QueueLimitMessage(nick, filename,
268 //  																pos + 1);
269 //  		  	    MessageHandler.send(server, m);
270 //  		  	}
271 //  		}
272 
273 }