Statistics
| Revision:

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
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * 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
 *
11
 * 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
 *
16
 * 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
 *
20
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.compat.se.net.downloader.se;
24

    
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
import org.gvsig.compat.se.net.downloader.Downloader;
39

    
40
/**
41
 * Clase con m?todos de utilidad en el protocolo WMS
42
 *
43
 */
44
public class SEDownloader implements Downloader {
45

    
46
//    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

    
52
    /**
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
     * @param theurl
110
     * @return File containing this URL's content or null if no file was found.
111
     */
112
    private File getPreviousDownloaded(Object theurl) {
113

    
114
        File f = null;
115
        Object thekey = null;
116
        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
        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
            theuri = url.toURI();
153
        } catch (Exception e) {
154
            LOG.info("Warning: did not cache bad url: " + url, e);
155
            return;
156
        }
157

    
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
                /*
162
         if (fileName!=null){
163
         File f = new File(fileName);
164
         if (f.exists())
165
         f.delete();
166
         }
167
         */
168
    }
169

    
170
    /**
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

    
185
        if ((f = getPreviousDownloadedURL(url)) == null) {
186
            File tempDirectory = new File(tempDirectoryPath);
187
            if (!tempDirectory.exists()) {
188
                tempDirectory.mkdir();
189
            }
190

    
191
            f = new File(calculateFileName(name));
192

    
193
            if (cancel == null) {
194
                cancel = new ICancellable() {
195
                    public boolean isCanceled() {
196
                        return false;
197
                    }
198

    
199
                    public Object getID() {
200
                        return SEDownloader.class.getName();
201
                    }
202
                };
203
            }
204

    
205
            SEMonitor monitorObj = new SEMonitor(this, cancel);
206
            Thread downloader = new Thread(createDownloaderTask(this, url, null, f, cancel.getID().getClass(),-1));
207
            Thread monitor = new Thread(monitorObj);
208

    
209
            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

    
219
            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

    
229
            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

    
250
        return f;
251
    }
252

    
253
    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

    
263
    /**
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
        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
        File f = null;
281

    
282
        if ((f = getPreviousDownloadedURL(url, data)) == null) {
283
            File tempDirectory = new File(tempDirectoryPath);
284
            if (!tempDirectory.exists()) {
285
                tempDirectory.mkdir();
286
            }
287

    
288
            f = new File(calculateFileName(name));
289

    
290
            if (cancel == null) {
291
                cancel = new ICancellable() {
292
                    public boolean isCanceled() {
293
                        return false;
294
                    }
295

    
296
                    public Object getID() {
297
                        return SEDownloader.class.getName();
298
                    }
299
                };
300
            }
301
            SEMonitor monitorObj = new SEMonitor(this, cancel);
302
            Thread downloader = new Thread(
303
                    createDownloaderTask(this, url, data, f, cancel.getID(),maxbytes)
304
            );
305
            
306
            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

    
317
            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

    
327
            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

    
346
        return f;
347
    }
348

    
349
    /**
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

    
363
    /**
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

    
376
    /**
377
     * Cleans every temporal file previously downloaded.
378
     */
379
    public void cleanUpTempFiles() {
380
        try {
381
            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
        } catch (Exception e) {
395
        }
396

    
397
    }
398

    
399
    /**
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

    
413
    }
414

    
415
    /**
416
     * Remove an URL from the system cache. The file will remain in the file
417
     * system for further eventual uses.
418
     *
419
     * @param url
420
     */
421
    public void removeURL(URL url) {
422

    
423
        URI theuri = null;
424

    
425
        try {
426
            theuri = url.toURI();
427
        } catch (Exception e) {
428
            LOG.info("Warning: did not remove bad url: " + url, e);
429
            return;
430
        }
431

    
432
        if (cachedURItoFile != null && cachedURItoFile.containsKey(theuri)) {
433
            cachedURItoFile.remove(theuri);
434
        }
435
    }
436

    
437
    /**
438
     * Remove an URL from the system cache. The file will remain in the file
439
     * system for further eventual uses.
440
     *
441
     * @param url
442
     */
443
    public void removeURL(Object url) {
444
        if (cachedURItoFile != null && cachedURItoFile.containsKey(url)) {
445
            cachedURItoFile.remove(url);
446
        }
447
    }
448

    
449
    public void setDownloadException(Exception exception) {
450
        this.downloadException = exception;
451
    }
452

    
453
    public long getLatency() {
454
        return this.latency;
455
    }
456

    
457
    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
    }
463
}