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

Last change on this file since 633 was 619, checked in by alloc, 12 years ago

AEI2:

  • Sanitizing level file names for MacOS (level*_Final.#)
File size: 5.5 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, String target) throws IOException {
64 this.url = new URL(url);
65 this.target = new File(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 private synchronized void updateStatus(int current, int total) {
135 downloaded = current;
136 for (FileDownloadListener l : listeners) {
137 l.statusUpdate(this, state, current, total);
138 }
139 }
140
141 @Override
142 public void run() {
143 int downloaded = 0;
144 int fileLength = Integer.MAX_VALUE;
145 String strLastModified = null;
146 String strEtag = null;
147 RandomAccessFile outFile = null;
148 try {
149 outFile = new RandomAccessFile(target, "rw");
150 } catch (FileNotFoundException e1) {
151 e1.printStackTrace();
152 state = EState.ERROR;
153 updateStatus(downloaded, fileLength);
154 return;
155 }
156
157 try {
158 while (downloaded < fileLength) {
159 switch (state) {
160 case ERROR:
161 updateStatus(downloaded, fileLength);
162 return;
163 case PAUSED:
164 try {
165 Thread.sleep(100);
166 } catch (InterruptedException e) {
167 e.printStackTrace();
168 }
169 break;
170 case INTERRUPTED:
171 return;
172 case RUNNING:
173 BufferedInputStream input = null;
174 try {
175 URLConnection connection = url.openConnection();
176 if (downloaded == 0) {
177 connection.connect();
178 strLastModified = connection
179 .getHeaderField("Last-Modified");
180 strEtag = connection.getHeaderField("ETag");
181 fileLength = connection.getContentLength();
182 } else {
183 connection.setRequestProperty("Range", "bytes="
184 + downloaded + "-");
185 if (strEtag != null)
186 connection.setRequestProperty("If-Range",
187 strEtag);
188 else
189 connection.setRequestProperty("If-Range",
190 strLastModified);
191 connection.connect();
192 }
193
194 // Setup streams and buffers.
195 input = new BufferedInputStream(
196 connection.getInputStream(), 8192);
197 if (downloaded > 0)
198 outFile.seek(downloaded);
199 byte data[] = new byte[1024];
200
201 // Download file.
202 int dataRead = 0;
203 int i = 0;
204 while (((dataRead = input.read(data, 0, 1024)) != -1)
205 && (state == EState.RUNNING)) {
206 outFile.write(data, 0, dataRead);
207 downloaded += dataRead;
208 if (downloaded >= fileLength)
209 break;
210
211 i++;
212 if ((i % 50) == 0)
213 updateStatus(downloaded, fileLength);
214 }
215 input.close();
216 } catch (IOException e) {
217 // TODO Auto-generated catch block
218 e.printStackTrace();
219 try {
220 if (input != null)
221 input.close();
222 } catch (IOException e2) {
223 e2.printStackTrace();
224 }
225 }
226 break;
227 default:
228 break;
229 }
230 }
231 } finally {
232 try {
233 // Close streams.
234 outFile.close();
235 } catch (IOException e) {
236 e.printStackTrace();
237 }
238 }
239
240 state = EState.FINISHED;
241 updateStatus(downloaded, fileLength);
242 }
243
244 /**
245 * @return the target
246 */
247 public File getTarget() {
248 return target;
249 }
250
251 /**
252 * @return the size
253 */
254 public int getSize() {
255 return size;
256 }
257
258 /**
259 * @return the downloaded size
260 */
261 public int getDownloaded() {
262 return downloaded;
263 }
264
265}
Note: See TracBrowser for help on using the repository browser.