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.gift.net;
21  
22  import java.awt.event.ActionEvent;
23  import java.io.File;
24  import java.util.Enumeration;
25  import java.util.Hashtable;
26  import java.util.LinkedList;
27  
28  import javax.swing.Action;
29  import javax.swing.Icon;
30  
31  import org.xnap.XNap;
32  import org.xnap.gui.util.IconHelper;
33  import org.xnap.peer.Peer;
34  import org.xnap.plugin.Plugin;
35  import org.xnap.plugin.gift.GiFTPlugin;
36  import org.xnap.plugin.gift.action.AbstractClearSourcesAction;
37  import org.xnap.transfer.AbstractDownload;
38  import org.xnap.transfer.Segment;
39  import org.xnap.transfer.action.AbstractDeleteAction;
40  import org.xnap.transfer.action.AbstractFindMoreSourcesAction;
41  import org.xnap.transfer.action.AbstractTransferAction;
42  
43  
44  
45  /***
46   * GiFTDownloadContainer
47   *
48   * @author <a href="mailto:taval@users.sf.net">Tammo van Lessen</a>
49   * @version CVS $Id: GiFTDownloadContainer.java,v 1.6 2004/03/23 19:36:21 vanto Exp $
50   */
51  public class GiFTDownloadContainer extends AbstractDownload {
52  
53  	// FIX: should be initialized in constructor
54      private String gid = "";
55  	private boolean done = false;
56  	private boolean paused = true;
57  
58      /***
59       * The number of bytes that were already transfered when the 
60       * container was constructed.
61       */
62  	private GiFTDaemon daemon;
63      private long offset;
64  	private long totalBytesTransferred;
65  	private String filename;
66      private String hash;
67      private long currentRate;
68      private long filesize;
69  	private String status;
70  	private Hashtable sources;
71      private LinkedList segments = new LinkedList();
72  
73  	private AbstractTransferAction cancelAction = new CancelAction();
74  
75      //~ Constructors -----------------------------------------------------------
76  
77      /***
78       * Constructor for GiFTDownloadContainer.
79       *
80       * @param filename DOCUMENT ME!
81       * @param hash DOCUMENT ME!
82       * @param filesize DOCUMENT ME!
83       * @param transmit DOCUMENT ME!
84       * @param state DOCUMENT ME!
85       */
86      public GiFTDownloadContainer(GiFTDaemon daemon, String filename, 
87  								 String hash, long filesize) 
88      {
89  		this.daemon = daemon;
90  		
91          this.filename = filename;
92          this.filesize = filesize;
93          this.hash = hash;
94  
95  		this.sources = new Hashtable();
96  		this.status = XNap.tr("Waiting for daemon");
97      }
98  	
99      /***
100      * 
101      */
102     public void cancel() 
103 	{
104         daemon.changeDownload(this, "cancel");
105     	setStatus(XNap.tr("Cancelling"));    
106     }
107 
108 	/***
109      * @see xnap.net.ITransferContainer#getFilename()
110      */
111     public String getFilename() {
112         return filename.substring(filename.lastIndexOf("/") + 1);
113     }
114 
115     /***
116      * @see xnap.net.ITransferContainer#getFilesize()
117      */
118     public long getFilesize() {
119         return filesize;
120     }
121 
122     public Plugin getPlugin()
123     {
124 	return GiFTPlugin.getInstance();
125     }
126 
127 	/***
128 	 * Invoked by {@link GiFTDaemon} when the download has been deleted.
129 	 */
130 	void deleted() 
131 	{
132 		// in case of a successful completion this method will also be called
133 		// so only change the status if we haven't noticed already
134 		if (!done) {
135 			done();
136 			setStatus("Deleted");
137 		}
138 	}
139 
140 	private void done()
141 	{
142 		done = true;
143 		transferStopped();
144 	}
145 	
146 	/***
147 	 * @see xnap.transfer.Transfer#getActions()
148 	 */
149 	public Action[] getActions(String url) 
150 	{
151 		return new Action[] { 
152 			new PauseAction(),
153 			cancelAction,
154 			new CancelSourceAction(url),
155 			new FindMoreSourcesAction(), 
156 			new ClearSourcesAction(),
157 		};
158 	}
159 
160 	public Action[] getActions() 
161 	{
162 		return getActions(null);
163 	}
164 
165 	/***
166 	 * @see xnap.transfer.Transfer#getFile()
167 	 */
168 	public File getFile() 
169 	{
170 		return null;
171 	}
172 
173 	/***
174 	 * @see xnap.transfer.Transfer#getPeer()
175 	 */
176 	public Peer getPeer() 
177 	{
178 		return null;
179 	}
180 
181     public Segment[] getSegments()
182     {
183 		return (Segment[])segments.toArray(new Segment[0]);
184     }
185 
186 	/***
187 	 * @see xnap.transfer.Transfer#getStatus()
188 	 */
189 	public String getStatus() 
190 	{
191 		return status;
192 	}
193 
194 	/***
195 	 * @see xnap.transfer.Transfer#getTotalBytesTransferred()
196 	 */
197 	public long getTotalBytesTransferred() 
198 	{
199 		return totalBytesTransferred;
200 	}
201 
202 	/***
203 	 * @see xnap.transfer.Transfer#isDone()
204 	 */
205 	public boolean isDone() 
206 	{
207 		return done;
208 	}
209 
210 	/***
211 	 * @see xnap.transfer.Transfer#isRunning()
212 	 */
213 	public boolean isRunning() 
214 	{
215 		return !done && !paused;
216 	}
217 
218 	/***
219 	 * @see xnap.transfer.AbstractTransfer#getBytesTransferred()
220 	 */
221 	public long getBytesTransferred() 
222 	{
223 		return totalBytesTransferred - offset;
224 	}
225 
226 	/***
227 	 * @see xnap.transfer.Transfer#getCurrentRate()
228 	 */
229 	public long getCurrentRate() 
230 	{
231 		return currentRate;
232 	}
233 
234 	
235 	public void markChildren() 
236 	{
237 		Enumeration enumeration = sources.elements();
238 		while (enumeration.hasMoreElements()) {
239 		    GiFTDownload element = (GiFTDownload) enumeration.nextElement();
240 		    element.setMarked(true);
241 		}
242 	}
243 
244 	public void orphanMarkedChildren() 
245 	{
246 		Enumeration enumeration = sources.elements();
247 		while (enumeration.hasMoreElements()) {
248 		    GiFTDownload element
249 				= (GiFTDownload) enumeration.nextElement();
250 		    if (element.isMarked()) {
251 				element.setState("Inactive", null);
252 		    }
253 		}
254 	}
255 	
256 	/***
257 	 * 
258 	 */
259 	public void clearOrphaned() 
260 	{
261 		Enumeration enumeration = sources.elements();
262 		while (enumeration.hasMoreElements()) {
263 			GiFTDownload element = (GiFTDownload) enumeration.nextElement();
264 			if (element.getStatus().equals("Inactive")) {
265 				sources.remove(element);
266 				remove(element);
267 			}
268 		}
269 	}
270 
271 	public GiFTDownload getSourceByURL(String url)
272 	{
273 		return (GiFTDownload)sources.get(url);
274 	}
275 
276 	public GiFTDownload addSource(GiFTUser user, String url)
277 	{
278 		GiFTDownload d = new GiFTDownload(this, user, url);	
279 
280 		// add the segment from the newly created download
281 		Segment[] s = d.getSegments();
282 		segments.add(s[0]);
283 
284 		sources.put(url, d);
285 		add(d);	
286 
287 		return d;
288 	}
289 
290 	/***
291 	 * @return unique id
292 	 */
293 	public String getGID() 
294 	{
295 		return gid;
296 	}
297 
298     /***
299 	 * @return unique hash
300 	 */
301 	public String getHash() 
302 	{
303 		return hash;
304 	}
305 
306     public Icon getIcon()
307     {
308 		return GiFTPlugin.ICON_16;
309     }
310 
311     /***
312      * 
313      */
314     public void pause() 
315 	{
316 		daemon.changeDownload(this, (paused) ? "unpause" : "pause");
317     }
318 
319 	public void setGID(String gid) 
320 	{
321         this.gid = gid;
322     }
323 
324 	public void setCurrentRate(long currentRate) 
325 	{
326 		this.currentRate = currentRate;
327 	}
328 
329     public void setOffset(long offset)
330     {
331 		this.offset = offset;
332     }
333 
334 	/***
335 	 * Invoked by {@link Enginge} when the download state changed.
336 	 */
337 	public void setState(String state) 
338 	{
339 		if (state.equals("Active")) {
340 			if (paused) {
341 				paused = false;
342 				transferStarted();
343 			}
344 		}
345 		else if (state.equals("Paused")) {
346 			if (!paused) {
347 				paused = true;
348 				transferStopped();
349 			}
350 		}
351 		else if (state.equals("Completed")) {
352 			if (!done) {
353 				done();
354 				
355 				Enumeration enumeration = sources.elements();
356 				while (enumeration.hasMoreElements()) {
357 					GiFTDownload download
358 						= (GiFTDownload)enumeration.nextElement();
359 					download.setState("Complete", null);
360 				}
361 			}
362 		}
363 
364 		setStatus(state);
365 	}
366 
367 	private void setStatus(String status)
368 	{
369 		this.status = status;
370 		stateChanged();
371 	}
372 
373 	public void setTotalBytesTransferred(long totalBytesTransferred) 
374 	{
375 		this.totalBytesTransferred = totalBytesTransferred;
376 	}
377 
378 	private class CancelAction extends AbstractDeleteAction  {
379 
380 		public void actionPerformed(ActionEvent e) 
381 		{
382 			GiFTDownloadContainer.this.cancel();
383 		}
384 
385 	}
386 
387 	private class CancelSourceAction extends AbstractDeleteAction  {
388 
389 		private String url;
390 
391 		public CancelSourceAction(String url)
392 		{
393 			this.url = url;
394 
395 			putValue(Action.NAME, XNap.tr("Delete Source"));
396 			setEnabled(url != null);
397 		}
398 
399 		public void actionPerformed(ActionEvent e) 
400 		{
401 			daemon.deleteSource(GiFTDownloadContainer.this, url);
402 		}
403 
404 	}
405 
406 
407 	private class ClearSourcesAction extends AbstractClearSourcesAction {
408 
409 		public void actionPerformed(ActionEvent e) 
410 		{
411 			GiFTDownloadContainer.this.clearOrphaned();	
412 		}
413 
414 	}
415 
416 	private class FindMoreSourcesAction extends AbstractFindMoreSourcesAction {
417 
418 		public void actionPerformed(ActionEvent e) 
419 		{
420 			setStatus(XNap.tr("Retrieving more sources"));
421 			daemon.locate(GiFTDownloadContainer.this);
422 		}
423 
424 	}
425 
426 	private class PauseAction extends AbstractTransferAction  {
427 
428 		public PauseAction() 
429 		{
430 			putValue(Action.NAME, XNap.tr("(Un)Pause Download"));
431 			putValue(Action.SHORT_DESCRIPTION,
432 					 XNap.tr("Pauses or unpauses the download."));
433 			putValue(IconHelper.XNAP_ICON, "player_pause.png");
434 		}
435 
436 		public void actionPerformed(ActionEvent e) 
437 		{
438 			GiFTDownloadContainer.this.pause();
439 		}
440 
441 	}
442 
443 }