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.jtella;
21  
22  import java.io.File;
23  import java.util.Hashtable;
24  import java.util.Iterator;
25  import java.util.LinkedList;
26  
27  import javax.swing.Action;
28  
29  import org.apache.log4j.Logger;
30  import org.xnap.event.StateEvent;
31  import org.xnap.event.StateListener;
32  import org.xnap.peer.Peer;
33  import org.xnap.plugin.Plugin;
34  import org.xnap.transfer.AbstractDownload;
35  import org.xnap.transfer.DownloadManager;
36  import org.xnap.transfer.Queueable;
37  import org.xnap.util.FiniteStateMachine;
38  import org.xnap.util.IllegalOperationException;
39  import org.xnap.util.State;
40  
41  /***
42   * Manages {@link JTellaDownload} objects.
43   */
44  public class JTellaDownloadContainer extends AbstractDownload 
45      implements Queueable {
46  
47      //--- Constant(s) ---
48  
49      private static final Hashtable TRANSITION_TABLE;
50      static {
51  		State[][] table = new State[][] {
52  			{ State.NOT_STARTED,  
53  			  State.RUNNING, },
54  			{ State.RUNNING, 
55  			  State.SUCCEEDED, State.FAILED, },
56  		};
57  
58  		TRANSITION_TABLE = FiniteStateMachine.createStateTable(table);
59      }
60      
61      //--- Data field(s) ---
62  
63      private static Logger logger 
64  		= Logger.getLogger(JTellaDownloadContainer.class);
65  
66      private JTellaDownload activeDownload;
67  	private long enqueueTime = System.currentTimeMillis();
68      private String filename;
69      private long filesize;
70      private int queuePosition;
71      private StateMachine sm = new StateMachine();
72  
73      /***
74       * A list of {@link JTellaDownload} objects.
75       */
76      private LinkedList queue = new LinkedList();
77  
78      //--- Constructor(s) ---
79  
80      /***
81       * Constructs a JTellaDownload. Creates {@link JTellaDownload}
82       * objects from the results contained in <code>container</code>.
83       * Sequentially tries each download until one succeeds.
84       */
85      public JTellaDownloadContainer(JTellaSearchResultContainer container) 
86      {
87  		this.filename = container.getFilename();
88  		this.filesize = container.getFilesize();
89  
90  		for (Iterator i = container.iterator(); i.hasNext();) {
91  			add(new JTellaDownload((JTellaSearchResult)i.next()));
92  		}
93      }
94  
95      /***
96       * Constructs a JTellaDownload. Creates {@link JTellaDownload}
97       * objects from the <code>result</code>.
98       */
99      public JTellaDownloadContainer(JTellaSearchResult result) 
100     {
101 		this.filename = result.getFilename();
102 		this.filesize = result.getFilesize();
103 
104 		add(new JTellaDownload(result));
105     }
106 
107     //--- Method(s) ---
108 
109     public void add(JTellaDownload d)
110     {
111 		queue.add(d);
112 		super.add(d);
113     }
114 
115     public Action[] getActions()
116     {
117 		return null;
118     }
119 
120     public long getBytesTransferred() 
121     {
122 		JTellaDownload download = getDownload();
123 		return (download != null) ? download.getBytesTransferred() : 0;
124     }
125 
126     public JTellaDownload getDownload()
127     {
128 		return activeDownload;
129     }
130 
131 	public long getEnqueueTime()
132 	{
133 		return enqueueTime;
134 	}
135 
136     public File getFile()
137     {
138 		JTellaDownload download = getDownload();
139 		return (download != null) ? download.getFile() : null;
140     }
141 
142     public String getFilename()
143     {
144 		return filename;
145     }
146 
147     public long getFilesize()
148     {
149 		return filesize;
150     }
151 
152     public Peer getPeer()
153     {
154 		JTellaDownload download = getDownload();
155 		return (download != null) ? download.getPeer() : null;
156     }
157 
158     public Plugin getPlugin()
159     {
160 		return JTellaPlugin.getInstance();
161     }
162 
163     public String getStatus()
164     {
165 		JTellaDownload download = getDownload();
166 		return (download != null) ? download.getStatus() : null;
167     }
168 
169     public long getTotalBytesTransferred()
170     {
171 		JTellaDownload download = getDownload();
172 		return (download != null) ? download.getTotalBytesTransferred() : 0;
173     }
174 
175     public boolean isDone()
176     {
177 		State s = sm.getState();
178 		return s == State.SUCCEEDED || s == State.FAILED;
179     }
180 
181     public boolean isFailed()
182     {
183 		return sm.getState() == State.FAILED;
184     }
185 
186     public boolean isRunning()
187     {
188 		return sm.getState() == State.RUNNING;
189     }
190 
191     /***
192      * Returns 1.
193      */
194     public int getPriority()
195     {
196 		return 1;
197     }
198 
199     /***
200      * Returns the position in the {@link DownloadManager} queue.
201      */
202     public int getQueuePosition()
203     {
204 		return queuePosition;
205     }
206 
207     /***
208      *
209      */
210     public void setQueuePosition(int position)
211     {
212 		queuePosition = position;
213     }
214 
215     private void setState(State newState)
216     {
217 		sm.setState(newState);
218 		stateChanged();
219     }
220 
221     public void start()
222     {
223 		DownloadManager.getInstance().getQueue().add(this);
224     }
225 
226     public void startNextDownload()
227     {
228 		if (queue.isEmpty()) {
229 			activeDownload = null;
230 			try {
231 				setState(State.FAILED);
232 			}
233 			catch (IllegalOperationException e) {
234 				logger.error("unexpected exception", e);
235 			}
236 			return;
237 		}
238 
239 		activeDownload = (JTellaDownload)queue.removeFirst();
240 		activeDownload.addStateListener(new DownloadListener());
241 		try {
242 			activeDownload.start();
243 		}
244 		catch (IllegalOperationException e) {
245 			logger.error("unexpected exception", e);
246 		}
247     }
248 
249 	public boolean startTransfer()
250 	{
251 		try {
252 			setState(State.RUNNING);
253 			return true;
254 		}
255 		catch (IllegalOperationException e) {
256 			logger.error("unexpected exception", e);
257 			return false;
258 		}
259 	}
260 
261     //--- Inner Class(es) ---
262 
263     private class StateMachine extends FiniteStateMachine
264     {
265 
266 		//--- Constructor(s) ---
267 
268 		public StateMachine()
269 		{
270 			super(State.NOT_STARTED, TRANSITION_TABLE);
271 		}
272 
273 		//--- Method(s) ---
274 
275 		protected synchronized void stateChanged(State oldState,
276 												 State newState)
277 		{
278 			if (oldState == State.NOT_STARTED) {
279 				if (newState == State.RUNNING) {
280 					startNextDownload();
281 				}
282 			}
283 			else if (newState == State.SUCCEEDED || newState == State.FAILED) {
284 				DownloadManager.getInstance().getQueue().remove
285 					(JTellaDownloadContainer.this);
286 			}
287 		}
288     }
289 
290     private class DownloadListener implements StateListener
291     {
292 	
293 		public void stateChanged(StateEvent event)
294 		{
295 			if (activeDownload.isDone()) {
296 				activeDownload.removeStateListener(this);
297 				if (activeDownload.isFailed()) {
298 					startNextDownload();
299 				}
300 			}
301 		}
302 
303     }
304 
305 }
306