1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
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
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
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
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
262
263 private class StateMachine extends FiniteStateMachine
264 {
265
266
267
268 public StateMachine()
269 {
270 super(State.NOT_STARTED, TRANSITION_TABLE);
271 }
272
273
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