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

Last change on this file since 638 was 634, checked in by alloc, 12 years ago

AEI2 0.92b:\n- Using zipped Depot cache

File size: 5.6 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 size = -1;
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 URLConnection connection = this.url.openConnection();
68 connection.connect();
69 size = connection.getContentLength();
70 }
71
72 /**
73 * @param listener
74 * Listener to add
75 */
76 public void addListener(FileDownloadListener listener) {
77 listeners.add(listener);
78 }
79
80 /**
81 * @param listener
82 * Listener to remove
83 */
84 public void removeListener(FileDownloadListener listener) {
85 listeners.remove(listener);
86 }
87
88 /**
89 * Start the download process
90 */
91 public synchronized void start() {
92 if (t == null) {
93 t = new Thread(this);
94 t.start();
95 state = EState.RUNNING;
96 updateStatus(downloaded, size);
97 }
98 }
99
100 /**
101 * @param suspend
102 * Suspend or resume
103 */
104 public synchronized void suspend(boolean suspend) {
105 if ((state == EState.RUNNING) || (state == EState.PAUSED)) {
106 if (suspend)
107 state = EState.PAUSED;
108 else
109 state = EState.RUNNING;
110 updateStatus(downloaded, size);
111 }
112 }
113
114 /**
115 * Stop (abort) download
116 */
117 public synchronized void stop() {
118 if (state != EState.FINISHED) {
119 state = EState.INTERRUPTED;
120 if (t != null) {
121 try {
122 t.join();
123 } catch (InterruptedException e) {
124 e.printStackTrace();
125 }
126 t = null;
127 }
128 updateStatus(0, 1);
129 if (target.exists())
130 target.delete();
131 }
132 }
133
134 /**
135 * @return current state
136 */
137 public EState getState() {
138 return state;
139 }
140
141 private synchronized void updateStatus(int current, int total) {
142 downloaded = current;
143 for (FileDownloadListener l : listeners) {
144 l.statusUpdate(this, state, current, total);
145 }
146 }
147
148 @Override
149 public void run() {
150 int downloaded = 0;
151 int fileLength = Integer.MAX_VALUE;
152 String strLastModified = null;
153 String strEtag = null;
154 RandomAccessFile outFile = null;
155 try {
156 outFile = new RandomAccessFile(target, "rw");
157 } catch (FileNotFoundException e1) {
158 e1.printStackTrace();
159 state = EState.ERROR;
160 updateStatus(downloaded, fileLength);
161 return;
162 }
163
164 try {
165 while (downloaded < fileLength) {
166 switch (state) {
167 case ERROR:
168 updateStatus(downloaded, fileLength);
169 return;
170 case PAUSED:
171 try {
172 Thread.sleep(100);
173 } catch (InterruptedException e) {
174 e.printStackTrace();
175 }
176 break;
177 case INTERRUPTED:
178 return;
179 case RUNNING:
180 BufferedInputStream input = null;
181 try {
182 URLConnection connection = url.openConnection();
183 if (downloaded == 0) {
184 connection.connect();
185 strLastModified = connection
186 .getHeaderField("Last-Modified");
187 strEtag = connection.getHeaderField("ETag");
188 fileLength = connection.getContentLength();
189 } else {
190 connection.setRequestProperty("Range", "bytes="
191 + downloaded + "-");
192 if (strEtag != null)
193 connection.setRequestProperty("If-Range",
194 strEtag);
195 else
196 connection.setRequestProperty("If-Range",
197 strLastModified);
198 connection.connect();
199 }
200
201 // Setup streams and buffers.
202 input = new BufferedInputStream(
203 connection.getInputStream(), 8192);
204 if (downloaded > 0)
205 outFile.seek(downloaded);
206 byte data[] = new byte[1024];
207
208 // Download file.
209 int dataRead = 0;
210 int i = 0;
211 while (((dataRead = input.read(data, 0, 1024)) != -1)
212 && (state == EState.RUNNING)) {
213 outFile.write(data, 0, dataRead);
214 downloaded += dataRead;
215 if (downloaded >= fileLength)
216 break;
217
218 i++;
219 if ((i % 50) == 0)
220 updateStatus(downloaded, fileLength);
221 }
222 input.close();
223 } catch (IOException e) {
224 // TODO Auto-generated catch block
225 e.printStackTrace();
226 try {
227 if (input != null)
228 input.close();
229 } catch (IOException e2) {
230 e2.printStackTrace();
231 }
232 }
233 break;
234 default:
235 break;
236 }
237 }
238 } finally {
239 try {
240 // Close streams.
241 outFile.close();
242 } catch (IOException e) {
243 e.printStackTrace();
244 }
245 }
246
247 state = EState.FINISHED;
248 updateStatus(downloaded, fileLength);
249 }
250
251 /**
252 * @return the target
253 */
254 public File getTarget() {
255 return target;
256 }
257
258 /**
259 * @return the size
260 */
261 public int getSize() {
262 return size;
263 }
264
265 /**
266 * @return the downloaded size
267 */
268 public int getDownloaded() {
269 return downloaded;
270 }
271
272}
Note: See TracBrowser for help on using the repository browser.