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 @ 42140

History | View | Annotate | Download (14.7 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
 * @authors Laura D?az, jaume dominguez faus
44
 */
45
public class SEDownloader implements Downloader {
46

    
47
//    String characters;
48
    private boolean canceled;
49
    private final long latency = 500;
50
    private static int count = 0;
51
    private static Logger LOG = LoggerFactory.getLogger(SEDownloader.class);
52

    
53
    /**
54
     * Used to cancel a group of files
55
     * <b>key</b>: Group id, <b>value</b>: Boolean (true if the group has to be
56
     * canceled. Otherwise it is false)
57
     */
58
    private Hashtable canceledGroup = new Hashtable();
59
    /**
60
     * <b>key</b>: URL, <b>value</b>: path to the downloaded file.
61
     */
62
    private Hashtable cachedURItoFile;
63
    private Exception downloadException;
64
    final String tempDirectoryPath = System.getProperty("java.io.tmpdir") + "/tmp-andami";
65

    
66
    public SEDownloader() {
67
        super();
68
//        characters = "";
69
//        for (int j = 32; j <= 127; j++) {
70
//            characters += (char) j;
71
//        }
72
//        characters += "?????????????????????????????????????????????????\n\r\f\t??";
73
    }
74

    
75
    /**
76
     * Return the content of a file that has been created from a URL using the
77
     * HTTP GET protocol
78
     *
79
     * @param url The URL
80
     * @return File containing this URL's content or null if no file was found.
81
     */
82
    private File getPreviousDownloadedURL(URL url) {
83
        return getPreviousDownloaded(url);
84
    }
85

    
86
    /**
87
     * Return the content of a file that has been created from a URL using the
88
     * HTTP POST protocol
89
     *
90
     * @param url The URL
91
     * @param data The data to send on the query
92
     * @return File containing this URL's content or null if no file was found.
93
     */
94
    private File getPreviousDownloadedURL(URL url, String data) {
95
        if (data == null) {
96
            return getPreviousDownloaded(url);
97
        }
98
        return getPreviousDownloaded(url.toString() + data);
99
    }
100

    
101
    /**
102
     * Returns the content of a URL as a file from the file system.<br>
103
     * <p>
104
     * If the URL has been already downloaded in this session and notified to
105
     * the system using the static <b>Utilities.addDownloadedURL(URL)</b>
106
     * method, it can be restored faster from the file system avoiding to
107
     * download it again.
108
     * </p>
109
     *
110
     * @param url
111
     * @return File containing this URL's content or null if no file was found.
112
     */
113
    private File getPreviousDownloaded(Object theurl) {
114

    
115
        File f = null;
116
        Object thekey = null;
117
        try {
118
            if (theurl instanceof URL) {
119
                thekey = ((URL) theurl).toURI();
120
            } else {
121
                thekey = theurl;
122
            }
123
        } catch (Exception e) {
124
            LOG.info("Warning: did not check url: " + theurl, e);
125
            return null;
126
        }
127

    
128
        if (cachedURItoFile != null && cachedURItoFile.containsKey(thekey)) {
129
            String filePath = (String) cachedURItoFile.get(thekey);
130
            f = new File(filePath);
131
            if (!f.exists()) {
132
                return null;
133
            }
134
        }
135
        return f;
136
    }
137

    
138
    /**
139
     * Adds an URL to the table of downloaded files for further uses. If the URL
140
     * already exists in the table its filePath value is updated to the new one
141
     * and the old file itself is removed from the file system.
142
     *
143
     * @param url
144
     * @param filePath
145
     */
146
    public void addDownloadedURL(URL url, String filePath) {
147
        if (cachedURItoFile == null) {
148
            cachedURItoFile = new Hashtable();
149
        }
150

    
151
        URI theuri = null;
152
        try {
153
            theuri = url.toURI();
154
        } catch (Exception e) {
155
            LOG.info("Warning: did not cache bad url: " + url, e);
156
            return;
157
        }
158

    
159
        String fileName = (String) cachedURItoFile.put(theuri, filePath);
160
        //JMV: No se puede eliminar el anterior porque puede que alguien lo
161
        // este usando
162
                /*
163
         if (fileName!=null){
164
         File f = new File(fileName);
165
         if (f.exists())
166
         f.delete();
167
         }
168
         */
169
    }
170

    
171
    /**
172
     * Downloads an URL into a temporary file that is removed the next time the
173
     * tempFileManager class is called, which means the next time gvSIG is
174
     * launched.
175
     *
176
     * @param url
177
     * @param name
178
     * @return
179
     * @throws IOException
180
     * @throws ServerErrorResponseException
181
     * @throws ConnectException
182
     * @throws UnknownHostException
183
     */
184
    public synchronized File downloadFile(URL url, String name, ICancellable cancel) throws IOException, ConnectException, UnknownHostException {
185
        File f = null;
186

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

    
193
            f = new File(calculateFileName(name));
194

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

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

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

    
211
            monitor.start();
212
            downloader.start();
213
            while (!getCanceled(cancel.getID()) && downloader.isAlive()) {
214
                try {
215
                    Thread.sleep(latency);
216
                } catch (InterruptedException e) {
217
                    LOG.error("Error", e);
218
                }
219
            }
220

    
221
            try {
222
                monitorObj.setFinish(true);
223
                monitor.join();
224
                downloader.join();
225
            } catch (InterruptedException e1) {
226
                LOG.warn(e1.getMessage());
227
            }
228
            downloader = null;
229
            monitor = null;
230

    
231
            if (getCanceled(cancel.getID())) {
232
                return null;
233
            }
234
            downloader = null;
235
            monitor = null;
236
            if (this.downloadException != null) {
237
                Exception e = this.downloadException;
238
                if (e instanceof FileNotFoundException) {
239
                    throw (IOException) e;
240
                } else if (e instanceof IOException) {
241
                    throw (IOException) e;
242
                } else if (e instanceof ConnectException) {
243
                    throw (ConnectException) e;
244
                } else if (e instanceof UnknownHostException) {
245
                    throw (UnknownHostException) e;
246
                }
247
            }
248
        } else {
249
            LOG.info(url.toString() + " cached at '" + f.getAbsolutePath() + "'");
250
        }
251

    
252
        return f;
253
    }
254

    
255
    private String calculateFileName(String name) {
256
        count++;
257
        int index = name.lastIndexOf(".");
258
        if (index > 0) {
259
            return tempDirectoryPath + "/" + name.substring(0, index) + System.currentTimeMillis() + count
260
                    + name.substring(index, name.length());
261
        }
262
        return tempDirectoryPath + "/" + name + System.currentTimeMillis() + count;
263
    }
264

    
265
    /**
266
     * Downloads a URL using the HTTP Post protocol
267
     *
268
     * @param url The server URL
269
     * @param data The data to send in the request
270
     * @param name A common name for all the retrieved files
271
     * @param cancel Used to cancel the downloads
272
     * @return The retrieved file
273
     * @throws IOException
274
     * @throws ConnectException
275
     * @throws UnknownHostException
276
     */
277
    public synchronized File downloadFile(URL url, String data, String name, ICancellable cancel) throws IOException, ConnectException, UnknownHostException {
278
        return downloadFile(url, data, name, cancel, -1);
279
    }
280
        
281
    public synchronized File downloadFile(URL url, String data, String name, ICancellable cancel,int maxbytes) throws IOException, ConnectException, UnknownHostException {
282
        File f = null;
283

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

    
290
            f = new File(calculateFileName(name));
291

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

    
298
                    public Object getID() {
299
                        return SEDownloader.class.getName();
300
                    }
301
                };
302
            }
303
            SEMonitor monitorObj = new SEMonitor(this, cancel);
304
            Thread downloader = new Thread(
305
                    createDownloaderTask(this, url, data, f, cancel.getID(),maxbytes)
306
            );
307
            
308
            Thread monitor = new Thread(monitorObj);
309
            monitor.start();
310
            downloader.start();
311
            while (!getCanceled(cancel.getID()) && downloader.isAlive()) {
312
                try {
313
                    Thread.sleep(latency);
314
                } catch (InterruptedException e) {
315
                    LOG.error("Error", e);
316
                }
317
            }
318

    
319
            try {
320
                monitorObj.setFinish(true);
321
                monitor.join();
322
                downloader.join();
323
            } catch (InterruptedException e1) {
324
                LOG.warn(e1.getMessage());
325
            }
326
            downloader = null;
327
            monitor = null;
328

    
329
            if (getCanceled(cancel.getID())) {
330
                return null;
331
            }
332
            if (this.downloadException != null) {
333
                Exception e = this.downloadException;
334
                if (e instanceof FileNotFoundException) {
335
                    throw (IOException) e;
336
                } else if (e instanceof IOException) {
337
                    throw (IOException) e;
338
                } else if (e instanceof ConnectException) {
339
                    throw (ConnectException) e;
340
                } else if (e instanceof UnknownHostException) {
341
                    throw (UnknownHostException) e;
342
                }
343
            }
344
        } else {
345
            LOG.info(url.toString() + " cached at '" + f.getAbsolutePath() + "'");
346
        }
347

    
348
        return f;
349
    }
350

    
351
    /**
352
     * Try if a group of downloads has been canceled
353
     *
354
     * @param groupId Group id
355
     * @return If the group has been canceled
356
     */
357
    public boolean getCanceled(Object groupId) {
358
        Object obj = canceledGroup.get(groupId);
359
        if (obj != null) {
360
            return ((Boolean) obj).booleanValue();
361
        }
362
        return false;
363
    }
364

    
365
    /**
366
     * Cancel a group of downloads
367
     *
368
     * @param groupId Group id
369
     * @param isCanceled if the group has to be canceled
370
     */
371
    public void setCanceled(Object groupId, boolean isCanceled) {
372
        if (groupId == null) {
373
            groupId = SEDownloader.class.getName();
374
        }
375
        canceledGroup.put(groupId, new Boolean(isCanceled));
376
    }
377

    
378
    /**
379
     * Cleans every temporal file previously downloaded.
380
     */
381
    public void cleanUpTempFiles() {
382
        try {
383
            File tempDirectory = new File(tempDirectoryPath);
384

    
385
            File[] files = tempDirectory.listFiles();
386
            if (files != null) {
387
                for (int i = 0; i < files.length; i++) {
388
                    // s?lo por si en un futuro se necesitan crear directorios temporales
389
                    if (files[i].isDirectory()) {
390
                        deleteDirectory(files[i]);
391
                    }
392
                    files[i].delete();
393
                }
394
            }
395
            tempDirectory.delete();
396
        } catch (Exception e) {
397
        }
398

    
399
    }
400

    
401
    /**
402
     * Recursive directory delete.
403
     *
404
     * @param f
405
     */
406
    private void deleteDirectory(File f) {
407
        File[] files = f.listFiles();
408
        for (int i = 0; i < files.length; i++) {
409
            if (files[i].isDirectory()) {
410
                deleteDirectory(files[i]);
411
            }
412
            files[i].delete();
413
        }
414

    
415
    }
416

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

    
425
        URI theuri = null;
426

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

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

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

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

    
455
    public long getLatency() {
456
        return this.latency;
457
    }
458

    
459
    protected Runnable createDownloaderTask(Downloader downloader, URL url, String data, File target, Object groupID,int maxbytes){
460
        SEDownloaderTask t = new SEDownloaderTask(downloader, url, data, target, groupID);
461
        t.setMaxbytes(maxbytes);
462
        return t;
463
                
464
    }
465
}