source: AE/installer2/src/net/oni2/aeinstaller/backend/network/FileDownloader.java@ 670

Last change on this file since 670 was 641, checked in by alloc, 12 years ago

AEI2 0.98:

  • Reduced number+size of HTTP queries
  • Removed "submitter" field
  • Added output of dependencies to be selected before continuing
File size: 5.4 KB
Line 
1package net.oni2.aeinstaller.backend.network;
2
3import java.io.BufferedInputStream;
4import java.io.File;
5import java.io.FileNotFoundException;
6import java.io.IOException;
7import java.io.RandomAccessFile;
8import java.net.URL;
9import java.net.URLConnection;
10import java.util.HashSet;
11
12/**
13 * @author Christian Illy
14 */
15public class FileDownloader implements Runnable {
16 /**
17 * @author Christian Illy
18 */
19 public enum EState {
20 /**
21 * Downloader initialized but not started
22 */
23 INIT,
24 /**
25 * Download running
26 */
27 RUNNING,
28 /**
29 * Download suspended
30 */
31 PAUSED,
32 /**
33 * Download interrupted
34 */
35 INTERRUPTED,
36 /**
37 * Download finished successfully
38 */
39 FINISHED,
40 /**
41 * Aborted because of an error
42 */
43 ERROR
44 };
45
46 private HashSet<FileDownloadListener> listeners = new HashSet<FileDownloadListener>();
47 private Thread t = null;
48 private URL url = null;
49 private File target = null;
50 private int fileLength = Integer.MAX_VALUE;
51 private int downloaded = 0;
52
53 private EState state = EState.INIT;
54
55 /**
56 * @param url
57 * URL of file to download
58 * @param target
59 * Path of target file to save to
60 * @throws IOException
61 * If url could not be opened
62 */
63 public FileDownloader(String url, File target) throws IOException {
64 this.url = new URL(url);
65 this.target = target;
66 }
67
68 /**
69 * @param listener
70 * Listener to add
71 */
72 public void addListener(FileDownloadListener listener) {
73 listeners.add(listener);
74 }
75
76 /**
77 * @param listener
78 * Listener to remove
79 */
80 public void removeListener(FileDownloadListener listener) {
81 listeners.remove(listener);
82 }
83
84 /**
85 * Start the download process
86 */
87 public synchronized void start() {
88 if (t == null) {
89 t = new Thread(this);
90 t.start();
91 state = EState.RUNNING;
92 }
93 }
94
95 /**
96 * @param suspend
97 * Suspend or resume
98 */
99 public synchronized void suspend(boolean suspend) {
100 if ((state == EState.RUNNING) || (state == EState.PAUSED)) {
101 if (suspend)
102 state = EState.PAUSED;
103 else
104 state = EState.RUNNING;
105 updateStatus(downloaded, fileLength);
106 }
107 }
108
109 /**
110 * Stop (abort) download
111 */
112 public synchronized void stop() {
113 if (state != EState.FINISHED) {
114 state = EState.INTERRUPTED;
115 if (t != null) {
116 try {
117 t.join();
118 } catch (InterruptedException e) {
119 e.printStackTrace();
120 }
121 t = null;
122 }
123 updateStatus(0, 1);
124 if (target.exists())
125 target.delete();
126 }
127 }
128
129 /**
130 * @return current state
131 */
132 public EState getState() {
133 return state;
134 }
135
136 private synchronized void updateStatus(int current, int total) {
137 downloaded = current;
138 for (FileDownloadListener l : listeners) {
139 l.statusUpdate(this, state, current, total);
140 }
141 }
142
143 @Override
144 public void run() {
145 int downloaded = 0;
146 String strLastModified = null;
147 String strEtag = null;
148 RandomAccessFile outFile = null;
149 try {
150 outFile = new RandomAccessFile(target, "rw");
151 } catch (FileNotFoundException e1) {
152 e1.printStackTrace();
153 state = EState.ERROR;
154 updateStatus(downloaded, fileLength);
155 return;
156 }
157
158 try {
159 while (downloaded < fileLength) {
160 switch (state) {
161 case ERROR:
162 updateStatus(downloaded, fileLength);
163 return;
164 case PAUSED:
165 try {
166 Thread.sleep(100);
167 } catch (InterruptedException e) {
168 e.printStackTrace();
169 }
170 break;
171 case INTERRUPTED:
172 return;
173 case RUNNING:
174 BufferedInputStream input = null;
175 try {
176 URLConnection connection = url.openConnection();
177 connection.setRequestProperty("Cache-Control", "no-cache");
178 if (downloaded == 0) {
179 connection.connect();
180 strLastModified = connection
181 .getHeaderField("Last-Modified");
182 strEtag = connection.getHeaderField("ETag");
183 fileLength = connection.getContentLength();
184 } else {
185 connection.setRequestProperty("Range", "bytes="
186 + downloaded + "-");
187 if (strEtag != null)
188 connection.setRequestProperty("If-Range",
189 strEtag);
190 else
191 connection.setRequestProperty("If-Range",
192 strLastModified);
193 connection.connect();
194 }
195
196 // Setup streams and buffers.
197 input = new BufferedInputStream(
198 connection.getInputStream(), 8192);
199 if (downloaded > 0)
200 outFile.seek(downloaded);
201 byte data[] = new byte[1024];
202
203 // Download file.
204 int dataRead = 0;
205 int i = 0;
206 while (((dataRead = input.read(data, 0, 1024)) != -1)
207 && (state == EState.RUNNING)) {
208 outFile.write(data, 0, dataRead);
209 downloaded += dataRead;
210 if (downloaded >= fileLength)
211 break;
212
213 i++;
214 if ((i % 50) == 0)
215 updateStatus(downloaded, fileLength);
216 }
217 input.close();
218 } catch (IOException e) {
219 // TODO Auto-generated catch block
220 e.printStackTrace();
221 try {
222 if (input != null)
223 input.close();
224 } catch (IOException e2) {
225 e2.printStackTrace();
226 }
227 }
228 break;
229 default:
230 break;
231 }
232 }
233 } finally {
234 try {
235 // Close streams.
236 outFile.close();
237 } catch (IOException e) {
238 e.printStackTrace();
239 }
240 }
241
242 state = EState.FINISHED;
243 updateStatus(downloaded, fileLength);
244 }
245
246 /**
247 * @return the target
248 */
249 public File getTarget() {
250 return target;
251 }
252
253 /**
254 * @return the downloaded size
255 */
256 public int getDownloaded() {
257 return downloaded;
258 }
259
260}
Note: See TracBrowser for help on using the repository browser.