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

History | View | Annotate | Download (13.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.HashMap;
33
import java.util.Map;
34
import org.apache.commons.io.FileUtils;
35

    
36
import org.slf4j.Logger;
37
import org.slf4j.LoggerFactory;
38

    
39
import org.gvsig.compat.net.ICancellable;
40
import org.gvsig.compat.se.net.downloader.Downloader;
41
import org.gvsig.tools.ToolsLocator;
42
import org.gvsig.tools.folders.FoldersManager;
43

    
44
/**
45
 * Clase con m?todos de utilidad en el protocolo WMS
46
 *
47
 */
48
public class SEDownloader implements Downloader {
49

    
50
//    private boolean canceled;
51
    private final long latency = 500;
52
    private static final Logger LOG = LoggerFactory.getLogger(SEDownloader.class);
53

    
54
    /**
55
     * Used to cancel a group of files
56
     * <b>key</b>: Group id, <b>value</b>: Boolean (true if the group has to be
57
     * canceled. Otherwise it is false)
58
     */
59
    private final Map<Object,Boolean> canceledGroup = new HashMap();
60
    /**
61
     * <b>key</b>: URL, <b>value</b>: path to the downloaded file.
62
     */
63
    private Map<Object,String> cachedURItoFile;
64
    private Exception downloadException;
65
    
66
    public SEDownloader() {
67
        super();
68
    }
69

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

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

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

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

    
123
        if (cachedURItoFile != null && cachedURItoFile.containsKey(thekey)) {
124
            String filePath = (String) cachedURItoFile.get(thekey);
125
            f = new File(filePath);
126
            if (!f.exists()) {
127
                return null;
128
            }
129
        }
130
        return f;
131
    }
132

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

    
147
        URI theuri;
148
        try {
149
            theuri = url.toURI();
150
        } catch (Exception e) {
151
            LOG.info("Warning: did not cache bad url: " + url, e);
152
            return;
153
        }
154

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

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

    
183
        if ((f = getPreviousDownloadedURL(url)) == null) {
184
            f = getUniqueTemporaryFile(name);
185

    
186
            if (cancel == null) {
187
                cancel = new ICancellable() {
188
                    @Override
189
                    public boolean isCanceled() {
190
                        return false;
191
                    }
192

    
193
                    @Override
194
                    public Object getID() {
195
                        return SEDownloader.class.getName();
196
                    }
197
                };
198
            }
199

    
200
            SEMonitor monitorObj = new SEMonitor(this, cancel);
201
            Thread downloader = new Thread(createDownloaderTask(this, url, null, f, cancel.getID().getClass(),-1));
202
            Thread monitor = new Thread(monitorObj);
203

    
204
            monitor.start();
205
            downloader.start();
206
            while (!getCanceled(cancel.getID()) && downloader.isAlive()) {
207
                try {
208
                    Thread.sleep(latency);
209
                } catch (InterruptedException e) {
210
                    LOG.error("Error", e);
211
                }
212
            }
213

    
214
            try {
215
                monitorObj.setFinish(true);
216
                monitor.join();
217
                downloader.join();
218
            } catch (InterruptedException e1) {
219
                LOG.warn(e1.getMessage());
220
            }
221
            downloader = null;
222
            monitor = null;
223

    
224
            if (getCanceled(cancel.getID())) {
225
                return null;
226
            }
227
            downloader = null;
228
            monitor = null;
229
            if (this.downloadException != null) {
230
                Exception e = this.downloadException;
231
                if (e instanceof FileNotFoundException) {
232
                    throw (IOException) e;
233
                } else if (e instanceof IOException) {
234
                    throw (IOException) e;
235
                } else if (e instanceof ConnectException) {
236
                    throw (ConnectException) e;
237
                } else if (e instanceof UnknownHostException) {
238
                    throw (UnknownHostException) e;
239
                }
240
            }
241
        } else {
242
            LOG.info(url.toString() + " cached at '" + f.getAbsolutePath() + "'");
243
        }
244

    
245
        return f;
246
    }
247

    
248
    /**
249
     * Downloads a URL using the HTTP Post protocol
250
     *
251
     * @param url The server URL
252
     * @param data The data to send in the request
253
     * @param name A common name for all the retrieved files
254
     * @param cancel Used to cancel the downloads
255
     * @return The retrieved file
256
     * @throws IOException
257
     * @throws ConnectException
258
     * @throws UnknownHostException
259
     */
260
    @Override
261
    public synchronized File downloadFile(URL url, String data, String name, ICancellable cancel) throws IOException, ConnectException, UnknownHostException {
262
        return downloadFile(url, data, name, cancel, -1);
263
    }
264
        
265
    @Override
266
    public synchronized File downloadFile(URL url, String data, String name, ICancellable cancel,int maxbytes) throws IOException, ConnectException, UnknownHostException {
267
        File f;
268

    
269
        if ((f = getPreviousDownloadedURL(url, data)) == null) {
270
            f = getUniqueTemporaryFile(name);
271

    
272
            if (cancel == null) {
273
                cancel = new ICancellable() {
274
                    @Override
275
                    public boolean isCanceled() {
276
                        return false;
277
                    }
278

    
279
                    @Override
280
                    public Object getID() {
281
                        return SEDownloader.class.getName();
282
                    }
283
                };
284
            }
285
            SEMonitor monitorObj = new SEMonitor(this, cancel);
286
            Thread downloader = new Thread(
287
                    createDownloaderTask(this, url, data, f, cancel.getID(),maxbytes)
288
            );
289
            
290
            Thread monitor = new Thread(monitorObj);
291
            monitor.start();
292
            downloader.start();
293
            while (!getCanceled(cancel.getID()) && downloader.isAlive()) {
294
                try {
295
                    Thread.sleep(latency);
296
                } catch (InterruptedException e) {
297
                    LOG.error("Error", e);
298
                }
299
            }
300

    
301
            try {
302
                monitorObj.setFinish(true);
303
                monitor.join();
304
                downloader.join();
305
            } catch (InterruptedException e1) {
306
                LOG.warn(e1.getMessage());
307
            }
308
            downloader = null;
309
            monitor = null;
310

    
311
            if (getCanceled(cancel.getID())) {
312
                return null;
313
            }
314
            if (this.downloadException != null) {
315
                Exception e = this.downloadException;
316
                if (e instanceof FileNotFoundException) {
317
                    throw (IOException) e;
318
                } else if (e instanceof IOException) {
319
                    throw (IOException) e;
320
                } else if (e instanceof ConnectException) {
321
                    throw (ConnectException) e;
322
                } else if (e instanceof UnknownHostException) {
323
                    throw (UnknownHostException) e;
324
                }
325
            }
326
        } else {
327
            LOG.info(url.toString() + " cached at '" + f.getAbsolutePath() + "'");
328
        }
329

    
330
        return f;
331
    }
332

    
333
    /**
334
     * Try if a group of downloads has been canceled
335
     *
336
     * @param groupId Group id
337
     * @return If the group has been canceled
338
     */
339
    @Override
340
    public boolean getCanceled(Object groupId) {
341
        Boolean obj = canceledGroup.get(groupId);
342
        if (obj != null) {
343
            return obj;
344
        }
345
        return false;
346
    }
347

    
348
    /**
349
     * Cancel a group of downloads
350
     *
351
     * @param groupId Group id
352
     * @param isCanceled if the group has to be canceled
353
     */
354
    @Override
355
    public void setCanceled(Object groupId, boolean isCanceled) {
356
        if (groupId == null) {
357
            groupId = SEDownloader.class.getName();
358
        }
359
        canceledGroup.put(groupId, isCanceled);
360
    }
361

    
362
    /**
363
     * Remove an URL from the system cache. The file will remain in the file
364
     * system for further eventual uses.
365
     *
366
     * @param url
367
     */
368
    @Override
369
    public void removeURL(URL url) {
370

    
371
        URI theuri = null;
372

    
373
        try {
374
            theuri = url.toURI();
375
        } catch (Exception e) {
376
            LOG.info("Warning: did not remove bad url: " + url, e);
377
            return;
378
        }
379

    
380
        if (cachedURItoFile != null && cachedURItoFile.containsKey(theuri)) {
381
            cachedURItoFile.remove(theuri);
382
        }
383
    }
384

    
385
    /**
386
     * Remove an URL from the system cache. The file will remain in the file
387
     * system for further eventual uses.
388
     *
389
     * @param url
390
     */
391
    @Override
392
    public void removeURL(Object url) {
393
        if (cachedURItoFile != null && cachedURItoFile.containsKey(url)) {
394
            cachedURItoFile.remove(url);
395
        }
396
    }
397

    
398
    @Override
399
    public void setDownloadException(Exception exception) {
400
        this.downloadException = exception;
401
    }
402

    
403
    @Override
404
    public long getLatency() {
405
        return this.latency;
406
    }
407

    
408
    protected Runnable createDownloaderTask(Downloader downloader, URL url, String data, File target, Object groupID,int maxbytes){
409
        SEDownloaderTask t = new SEDownloaderTask(downloader, url, data, target, groupID);
410
        t.setMaxbytes(maxbytes);
411
        return t;
412
                
413
    }
414
    
415
    /**
416
     * Cleans every temporal file previously downloaded.
417
     */
418
    @Override
419
    public void cleanUpTempFiles() {
420
        FoldersManager foldersManager = ToolsLocator.getFoldersManager();
421
        File folder = foldersManager.getTemporaryFile("downloader");
422
        try {
423
            FileUtils.cleanDirectory(folder);
424
        } catch (IOException ex) {
425
            LOG.warn("Can't clean folder '"+folder.getAbsolutePath()+"'.",ex);
426
        }
427
    }
428

    
429
    private File getUniqueTemporaryFile(String name) {
430
        FoldersManager foldersManager = ToolsLocator.getFoldersManager();
431
        File folder = foldersManager.getTemporaryFile("downloader");
432
        if( !folder.exists() ) {
433
            folder.mkdirs();
434
        }
435
        File f = foldersManager.getUniqueTemporaryFile("downloader",name);
436
        return f;
437
    }
438
}