svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.compat / org.gvsig.compat.se / src / main / java / org / gvsig / compat / se / net / downloader / se / SEDownloader.java @ 42543
History | View | Annotate | Download (14.6 KB)
1 | 40559 | jjdelcerro | /**
|
---|---|---|---|
2 | * gvSIG. Desktop Geographic Information System.
|
||
3 | *
|
||
4 | * Copyright (C) 2007-2013 gvSIG Association.
|
||
5 | *
|
||
6 | 41528 | jjdelcerro | * This program is free software; you can redistribute it and/or modify it under
|
7 | * the terms of the GNU General Public License as published by the Free Software
|
||
8 | * Foundation; either version 3 of the License, or (at your option) any later
|
||
9 | * version.
|
||
10 | 40559 | jjdelcerro | *
|
11 | 41528 | jjdelcerro | * This program is distributed in the hope that it will be useful, but WITHOUT
|
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||
13 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||
14 | * details.
|
||
15 | 40559 | jjdelcerro | *
|
16 | 41528 | jjdelcerro | * You should have received a copy of the GNU General Public License along with
|
17 | * this program; if not, write to the Free Software Foundation, Inc., 51
|
||
18 | * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||
19 | 40559 | jjdelcerro | *
|
20 | 41528 | jjdelcerro | * For any additional information, do not hesitate to contact us at info AT
|
21 | * gvsig.com, or visit our website www.gvsig.com.
|
||
22 | 40559 | jjdelcerro | */
|
23 | 41528 | jjdelcerro | package org.gvsig.compat.se.net.downloader.se; |
24 | 40435 | jjdelcerro | |
25 | import java.io.File; |
||
26 | import java.io.FileNotFoundException; |
||
27 | import java.io.IOException; |
||
28 | import java.net.ConnectException; |
||
29 | import java.net.URI; |
||
30 | import java.net.URL; |
||
31 | import java.net.UnknownHostException; |
||
32 | import java.util.Hashtable; |
||
33 | |||
34 | import org.slf4j.Logger; |
||
35 | import org.slf4j.LoggerFactory; |
||
36 | |||
37 | import org.gvsig.compat.net.ICancellable; |
||
38 | 41528 | jjdelcerro | import org.gvsig.compat.se.net.downloader.Downloader; |
39 | 40435 | jjdelcerro | |
40 | /**
|
||
41 | * Clase con m?todos de utilidad en el protocolo WMS
|
||
42 | *
|
||
43 | */
|
||
44 | 41528 | jjdelcerro | public class SEDownloader implements Downloader { |
45 | 40435 | jjdelcerro | |
46 | 41528 | jjdelcerro | // String characters;
|
47 | private boolean canceled; |
||
48 | private final long latency = 500; |
||
49 | private static int count = 0; |
||
50 | private static Logger LOG = LoggerFactory.getLogger(SEDownloader.class); |
||
51 | 40435 | jjdelcerro | |
52 | 41528 | jjdelcerro | /**
|
53 | * Used to cancel a group of files
|
||
54 | * <b>key</b>: Group id, <b>value</b>: Boolean (true if the group has to be
|
||
55 | * canceled. Otherwise it is false)
|
||
56 | */
|
||
57 | private Hashtable canceledGroup = new Hashtable(); |
||
58 | /**
|
||
59 | * <b>key</b>: URL, <b>value</b>: path to the downloaded file.
|
||
60 | */
|
||
61 | private Hashtable cachedURItoFile; |
||
62 | private Exception downloadException; |
||
63 | final String tempDirectoryPath = System.getProperty("java.io.tmpdir") + "/tmp-andami"; |
||
64 | |||
65 | public SEDownloader() {
|
||
66 | super();
|
||
67 | // characters = "";
|
||
68 | // for (int j = 32; j <= 127; j++) {
|
||
69 | // characters += (char) j;
|
||
70 | // }
|
||
71 | // characters += "?????????????????????????????????????????????????\n\r\f\t??";
|
||
72 | } |
||
73 | |||
74 | /**
|
||
75 | * Return the content of a file that has been created from a URL using the
|
||
76 | * HTTP GET protocol
|
||
77 | *
|
||
78 | * @param url The URL
|
||
79 | * @return File containing this URL's content or null if no file was found.
|
||
80 | */
|
||
81 | private File getPreviousDownloadedURL(URL url) { |
||
82 | return getPreviousDownloaded(url);
|
||
83 | } |
||
84 | |||
85 | /**
|
||
86 | * Return the content of a file that has been created from a URL using the
|
||
87 | * HTTP POST protocol
|
||
88 | *
|
||
89 | * @param url The URL
|
||
90 | * @param data The data to send on the query
|
||
91 | * @return File containing this URL's content or null if no file was found.
|
||
92 | */
|
||
93 | private File getPreviousDownloadedURL(URL url, String data) { |
||
94 | if (data == null) { |
||
95 | return getPreviousDownloaded(url);
|
||
96 | } |
||
97 | return getPreviousDownloaded(url.toString() + data);
|
||
98 | } |
||
99 | |||
100 | /**
|
||
101 | * Returns the content of a URL as a file from the file system.<br>
|
||
102 | * <p>
|
||
103 | * If the URL has been already downloaded in this session and notified to
|
||
104 | * the system using the static <b>Utilities.addDownloadedURL(URL)</b>
|
||
105 | * method, it can be restored faster from the file system avoiding to
|
||
106 | * download it again.
|
||
107 | * </p>
|
||
108 | *
|
||
109 | 42543 | jjdelcerro | * @param theurl
|
110 | 41528 | jjdelcerro | * @return File containing this URL's content or null if no file was found.
|
111 | */
|
||
112 | private File getPreviousDownloaded(Object theurl) { |
||
113 | |||
114 | 40435 | jjdelcerro | File f = null; |
115 | 41528 | jjdelcerro | Object thekey = null; |
116 | 40435 | jjdelcerro | try {
|
117 | if (theurl instanceof URL) { |
||
118 | thekey = ((URL) theurl).toURI();
|
||
119 | } else {
|
||
120 | thekey = theurl; |
||
121 | } |
||
122 | } catch (Exception e) { |
||
123 | LOG.info("Warning: did not check url: " + theurl, e);
|
||
124 | return null; |
||
125 | } |
||
126 | |||
127 | 41528 | jjdelcerro | if (cachedURItoFile != null && cachedURItoFile.containsKey(thekey)) { |
128 | String filePath = (String) cachedURItoFile.get(thekey); |
||
129 | f = new File(filePath); |
||
130 | if (!f.exists()) {
|
||
131 | return null; |
||
132 | } |
||
133 | } |
||
134 | return f;
|
||
135 | } |
||
136 | |||
137 | /**
|
||
138 | * Adds an URL to the table of downloaded files for further uses. If the URL
|
||
139 | * already exists in the table its filePath value is updated to the new one
|
||
140 | * and the old file itself is removed from the file system.
|
||
141 | *
|
||
142 | * @param url
|
||
143 | * @param filePath
|
||
144 | */
|
||
145 | public void addDownloadedURL(URL url, String filePath) { |
||
146 | if (cachedURItoFile == null) { |
||
147 | cachedURItoFile = new Hashtable(); |
||
148 | } |
||
149 | |||
150 | URI theuri = null; |
||
151 | try {
|
||
152 | 40435 | jjdelcerro | theuri = url.toURI(); |
153 | } catch (Exception e) { |
||
154 | LOG.info("Warning: did not cache bad url: " + url, e);
|
||
155 | return;
|
||
156 | } |
||
157 | 41528 | jjdelcerro | |
158 | String fileName = (String) cachedURItoFile.put(theuri, filePath); |
||
159 | //JMV: No se puede eliminar el anterior porque puede que alguien lo
|
||
160 | // este usando
|
||
161 | 40435 | jjdelcerro | /*
|
162 | 41528 | jjdelcerro | if (fileName!=null){
|
163 | File f = new File(fileName);
|
||
164 | if (f.exists())
|
||
165 | f.delete();
|
||
166 | }
|
||
167 | */
|
||
168 | } |
||
169 | 40435 | jjdelcerro | |
170 | 41528 | jjdelcerro | /**
|
171 | * Downloads an URL into a temporary file that is removed the next time the
|
||
172 | * tempFileManager class is called, which means the next time gvSIG is
|
||
173 | * launched.
|
||
174 | *
|
||
175 | * @param url
|
||
176 | * @param name
|
||
177 | * @return
|
||
178 | * @throws IOException
|
||
179 | * @throws ConnectException
|
||
180 | * @throws UnknownHostException
|
||
181 | */
|
||
182 | public synchronized File downloadFile(URL url, String name, ICancellable cancel) throws IOException, ConnectException, UnknownHostException { |
||
183 | File f = null; |
||
184 | 40435 | jjdelcerro | |
185 | 41528 | jjdelcerro | if ((f = getPreviousDownloadedURL(url)) == null) { |
186 | File tempDirectory = new File(tempDirectoryPath); |
||
187 | if (!tempDirectory.exists()) {
|
||
188 | tempDirectory.mkdir(); |
||
189 | } |
||
190 | 40435 | jjdelcerro | |
191 | 41528 | jjdelcerro | f = new File(calculateFileName(name)); |
192 | 40435 | jjdelcerro | |
193 | 41528 | jjdelcerro | if (cancel == null) { |
194 | cancel = new ICancellable() {
|
||
195 | public boolean isCanceled() { |
||
196 | return false; |
||
197 | } |
||
198 | 40435 | jjdelcerro | |
199 | 41528 | jjdelcerro | public Object getID() { |
200 | return SEDownloader.class.getName();
|
||
201 | } |
||
202 | }; |
||
203 | } |
||
204 | 40435 | jjdelcerro | |
205 | 41528 | jjdelcerro | SEMonitor monitorObj = new SEMonitor(this, cancel); |
206 | 42140 | jjdelcerro | Thread downloader = new Thread(createDownloaderTask(this, url, null, f, cancel.getID().getClass(),-1)); |
207 | 41528 | jjdelcerro | Thread monitor = new Thread(monitorObj); |
208 | 40435 | jjdelcerro | |
209 | 41528 | jjdelcerro | monitor.start(); |
210 | downloader.start(); |
||
211 | while (!getCanceled(cancel.getID()) && downloader.isAlive()) {
|
||
212 | try {
|
||
213 | Thread.sleep(latency);
|
||
214 | } catch (InterruptedException e) { |
||
215 | LOG.error("Error", e);
|
||
216 | } |
||
217 | } |
||
218 | 40435 | jjdelcerro | |
219 | 41528 | jjdelcerro | try {
|
220 | monitorObj.setFinish(true);
|
||
221 | monitor.join(); |
||
222 | downloader.join(); |
||
223 | } catch (InterruptedException e1) { |
||
224 | LOG.warn(e1.getMessage()); |
||
225 | } |
||
226 | downloader = null;
|
||
227 | monitor = null;
|
||
228 | 40435 | jjdelcerro | |
229 | 41528 | jjdelcerro | if (getCanceled(cancel.getID())) {
|
230 | return null; |
||
231 | } |
||
232 | downloader = null;
|
||
233 | monitor = null;
|
||
234 | if (this.downloadException != null) { |
||
235 | Exception e = this.downloadException; |
||
236 | if (e instanceof FileNotFoundException) { |
||
237 | throw (IOException) e; |
||
238 | } else if (e instanceof IOException) { |
||
239 | throw (IOException) e; |
||
240 | } else if (e instanceof ConnectException) { |
||
241 | throw (ConnectException) e; |
||
242 | } else if (e instanceof UnknownHostException) { |
||
243 | throw (UnknownHostException) e; |
||
244 | } |
||
245 | } |
||
246 | } else {
|
||
247 | LOG.info(url.toString() + " cached at '" + f.getAbsolutePath() + "'"); |
||
248 | } |
||
249 | 40435 | jjdelcerro | |
250 | 41528 | jjdelcerro | return f;
|
251 | } |
||
252 | 40435 | jjdelcerro | |
253 | 41528 | jjdelcerro | private String calculateFileName(String name) { |
254 | count++; |
||
255 | int index = name.lastIndexOf("."); |
||
256 | if (index > 0) { |
||
257 | return tempDirectoryPath + "/" + name.substring(0, index) + System.currentTimeMillis() + count |
||
258 | + name.substring(index, name.length()); |
||
259 | } |
||
260 | return tempDirectoryPath + "/" + name + System.currentTimeMillis() + count; |
||
261 | } |
||
262 | 40435 | jjdelcerro | |
263 | 41528 | jjdelcerro | /**
|
264 | * Downloads a URL using the HTTP Post protocol
|
||
265 | *
|
||
266 | * @param url The server URL
|
||
267 | * @param data The data to send in the request
|
||
268 | * @param name A common name for all the retrieved files
|
||
269 | * @param cancel Used to cancel the downloads
|
||
270 | * @return The retrieved file
|
||
271 | * @throws IOException
|
||
272 | * @throws ConnectException
|
||
273 | * @throws UnknownHostException
|
||
274 | */
|
||
275 | public synchronized File downloadFile(URL url, String data, String name, ICancellable cancel) throws IOException, ConnectException, UnknownHostException { |
||
276 | 42140 | jjdelcerro | return downloadFile(url, data, name, cancel, -1); |
277 | } |
||
278 | |||
279 | public synchronized File downloadFile(URL url, String data, String name, ICancellable cancel,int maxbytes) throws IOException, ConnectException, UnknownHostException { |
||
280 | 41528 | jjdelcerro | File f = null; |
281 | 40435 | jjdelcerro | |
282 | 41528 | jjdelcerro | if ((f = getPreviousDownloadedURL(url, data)) == null) { |
283 | File tempDirectory = new File(tempDirectoryPath); |
||
284 | if (!tempDirectory.exists()) {
|
||
285 | tempDirectory.mkdir(); |
||
286 | } |
||
287 | 40435 | jjdelcerro | |
288 | 41528 | jjdelcerro | f = new File(calculateFileName(name)); |
289 | 40435 | jjdelcerro | |
290 | 41528 | jjdelcerro | if (cancel == null) { |
291 | cancel = new ICancellable() {
|
||
292 | public boolean isCanceled() { |
||
293 | return false; |
||
294 | } |
||
295 | 40435 | jjdelcerro | |
296 | 41528 | jjdelcerro | public Object getID() { |
297 | return SEDownloader.class.getName();
|
||
298 | } |
||
299 | }; |
||
300 | } |
||
301 | SEMonitor monitorObj = new SEMonitor(this, cancel); |
||
302 | 42140 | jjdelcerro | Thread downloader = new Thread( |
303 | createDownloaderTask(this, url, data, f, cancel.getID(),maxbytes)
|
||
304 | ); |
||
305 | |||
306 | 41528 | jjdelcerro | Thread monitor = new Thread(monitorObj); |
307 | monitor.start(); |
||
308 | downloader.start(); |
||
309 | while (!getCanceled(cancel.getID()) && downloader.isAlive()) {
|
||
310 | try {
|
||
311 | Thread.sleep(latency);
|
||
312 | } catch (InterruptedException e) { |
||
313 | LOG.error("Error", e);
|
||
314 | } |
||
315 | } |
||
316 | 40435 | jjdelcerro | |
317 | 41528 | jjdelcerro | try {
|
318 | monitorObj.setFinish(true);
|
||
319 | monitor.join(); |
||
320 | downloader.join(); |
||
321 | } catch (InterruptedException e1) { |
||
322 | LOG.warn(e1.getMessage()); |
||
323 | } |
||
324 | downloader = null;
|
||
325 | monitor = null;
|
||
326 | 40435 | jjdelcerro | |
327 | 41528 | jjdelcerro | if (getCanceled(cancel.getID())) {
|
328 | return null; |
||
329 | } |
||
330 | if (this.downloadException != null) { |
||
331 | Exception e = this.downloadException; |
||
332 | if (e instanceof FileNotFoundException) { |
||
333 | throw (IOException) e; |
||
334 | } else if (e instanceof IOException) { |
||
335 | throw (IOException) e; |
||
336 | } else if (e instanceof ConnectException) { |
||
337 | throw (ConnectException) e; |
||
338 | } else if (e instanceof UnknownHostException) { |
||
339 | throw (UnknownHostException) e; |
||
340 | } |
||
341 | } |
||
342 | } else {
|
||
343 | LOG.info(url.toString() + " cached at '" + f.getAbsolutePath() + "'"); |
||
344 | } |
||
345 | 40435 | jjdelcerro | |
346 | 41528 | jjdelcerro | return f;
|
347 | } |
||
348 | 40435 | jjdelcerro | |
349 | 41528 | jjdelcerro | /**
|
350 | * Try if a group of downloads has been canceled
|
||
351 | *
|
||
352 | * @param groupId Group id
|
||
353 | * @return If the group has been canceled
|
||
354 | */
|
||
355 | public boolean getCanceled(Object groupId) { |
||
356 | Object obj = canceledGroup.get(groupId);
|
||
357 | if (obj != null) { |
||
358 | return ((Boolean) obj).booleanValue(); |
||
359 | } |
||
360 | return false; |
||
361 | } |
||
362 | 40435 | jjdelcerro | |
363 | 41528 | jjdelcerro | /**
|
364 | * Cancel a group of downloads
|
||
365 | *
|
||
366 | * @param groupId Group id
|
||
367 | * @param isCanceled if the group has to be canceled
|
||
368 | */
|
||
369 | public void setCanceled(Object groupId, boolean isCanceled) { |
||
370 | if (groupId == null) { |
||
371 | groupId = SEDownloader.class.getName(); |
||
372 | } |
||
373 | canceledGroup.put(groupId, new Boolean(isCanceled)); |
||
374 | } |
||
375 | 40435 | jjdelcerro | |
376 | 41528 | jjdelcerro | /**
|
377 | * Cleans every temporal file previously downloaded.
|
||
378 | */
|
||
379 | public void cleanUpTempFiles() { |
||
380 | 40435 | jjdelcerro | try {
|
381 | 41528 | jjdelcerro | File tempDirectory = new File(tempDirectoryPath); |
382 | |||
383 | File[] files = tempDirectory.listFiles(); |
||
384 | if (files != null) { |
||
385 | for (int i = 0; i < files.length; i++) { |
||
386 | // s?lo por si en un futuro se necesitan crear directorios temporales
|
||
387 | if (files[i].isDirectory()) {
|
||
388 | deleteDirectory(files[i]); |
||
389 | } |
||
390 | files[i].delete(); |
||
391 | } |
||
392 | } |
||
393 | tempDirectory.delete(); |
||
394 | 40435 | jjdelcerro | } catch (Exception e) { |
395 | } |
||
396 | |||
397 | 41528 | jjdelcerro | } |
398 | 40435 | jjdelcerro | |
399 | 41528 | jjdelcerro | /**
|
400 | * Recursive directory delete.
|
||
401 | *
|
||
402 | * @param f
|
||
403 | */
|
||
404 | private void deleteDirectory(File f) { |
||
405 | File[] files = f.listFiles(); |
||
406 | for (int i = 0; i < files.length; i++) { |
||
407 | if (files[i].isDirectory()) {
|
||
408 | deleteDirectory(files[i]); |
||
409 | } |
||
410 | files[i].delete(); |
||
411 | } |
||
412 | 40435 | jjdelcerro | |
413 | 41528 | jjdelcerro | } |
414 | 40435 | jjdelcerro | |
415 | 41528 | jjdelcerro | /**
|
416 | * Remove an URL from the system cache. The file will remain in the file
|
||
417 | * system for further eventual uses.
|
||
418 | *
|
||
419 | 42543 | jjdelcerro | * @param url
|
420 | 41528 | jjdelcerro | */
|
421 | public void removeURL(URL url) { |
||
422 | 40435 | jjdelcerro | |
423 | 41528 | jjdelcerro | URI theuri = null; |
424 | 40435 | jjdelcerro | |
425 | 41528 | jjdelcerro | try {
|
426 | theuri = url.toURI(); |
||
427 | } catch (Exception e) { |
||
428 | LOG.info("Warning: did not remove bad url: " + url, e);
|
||
429 | return;
|
||
430 | } |
||
431 | 40435 | jjdelcerro | |
432 | 41528 | jjdelcerro | if (cachedURItoFile != null && cachedURItoFile.containsKey(theuri)) { |
433 | cachedURItoFile.remove(theuri); |
||
434 | } |
||
435 | } |
||
436 | 40435 | jjdelcerro | |
437 | 41528 | jjdelcerro | /**
|
438 | * Remove an URL from the system cache. The file will remain in the file
|
||
439 | * system for further eventual uses.
|
||
440 | *
|
||
441 | 42543 | jjdelcerro | * @param url
|
442 | 41528 | jjdelcerro | */
|
443 | public void removeURL(Object url) { |
||
444 | if (cachedURItoFile != null && cachedURItoFile.containsKey(url)) { |
||
445 | cachedURItoFile.remove(url); |
||
446 | } |
||
447 | } |
||
448 | 40435 | jjdelcerro | |
449 | 41528 | jjdelcerro | public void setDownloadException(Exception exception) { |
450 | this.downloadException = exception;
|
||
451 | } |
||
452 | 40435 | jjdelcerro | |
453 | 41528 | jjdelcerro | public long getLatency() { |
454 | return this.latency; |
||
455 | } |
||
456 | 40435 | jjdelcerro | |
457 | 42140 | jjdelcerro | protected Runnable createDownloaderTask(Downloader downloader, URL url, String data, File target, Object groupID,int maxbytes){ |
458 | SEDownloaderTask t = new SEDownloaderTask(downloader, url, data, target, groupID);
|
||
459 | t.setMaxbytes(maxbytes); |
||
460 | return t;
|
||
461 | |||
462 | 41528 | jjdelcerro | } |
463 | 40435 | jjdelcerro | } |