Statistics
| Revision:

root / trunk / libraries / libGPE / src / org / gvsig / xmlschema / utils / DownloadUtilities.java @ 12175

History | View | Annotate | Download (15.7 KB)

1
package org.gvsig.xmlschema.utils;
2
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
3
 *
4
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
19
 *
20
 * For more information, contact:
21
 *
22
 *  Generalitat Valenciana
23
 *   Conselleria d'Infraestructures i Transport
24
 *   Av. Blasco Ib??ez, 50
25
 *   46010 VALENCIA
26
 *   SPAIN
27
 *
28
 *      +34 963862235
29
 *   gvsig@gva.es
30
 *      www.gvsig.gva.es
31
 *
32
 *    or
33
 *
34
 *   IVER T.I. S.A
35
 *   Salamanca 50
36
 *   46005 Valencia
37
 *   Spain
38
 *
39
 *   +34 963163400
40
 *   dac@iver.es
41
 */
42

    
43
import java.io.BufferedOutputStream;
44
import java.io.DataInputStream;
45
import java.io.DataOutputStream;
46
import java.io.File;
47
import java.io.FileNotFoundException;
48
import java.io.FileOutputStream;
49
import java.io.FileReader;
50
import java.io.IOException;
51
import java.io.InputStream;
52
import java.io.OutputStream;
53
import java.net.ConnectException;
54
import java.net.URL;
55
import java.net.UnknownHostException;
56
import java.rmi.NoSuchObjectException;
57
import java.util.Hashtable;
58
import java.util.StringTokenizer;
59
import java.util.Vector;
60

    
61

    
62

    
63
/**
64
 * Clase con m?todos de utilidad en el protocolo WMS
65
 *
66
 * @authors Laura D?az, jaume dominguez faus
67
 */
68
public class DownloadUtilities {
69
        private static String characters;
70
        static boolean canceled;
71
        static final long latency = 500;
72
        /**
73
     * <b>key</b>: URL, <b>value</b>: path to the downloaded file.
74
     */
75
    private static Hashtable downloadedFiles;
76
        static Exception downloadException;
77
    private static final String tempDirectoryPath = System.getProperty("java.io.tmpdir")+"/tmp-andami";
78

    
79

    
80
        static {
81
                characters = "";
82
                for (int j = 32; j<=127; j++){
83
                        characters += (char) j;
84
                }
85
                characters += "?????????????????????????????????????????????????\n\r\f\t??";
86
        }
87

    
88

    
89
        /**
90
         * Checks a File and tries to figure if the file is a text or a binary file.<br>
91
         * Keep in mind that binary files are those that contains at least one
92
         * non-printable character.
93
         *
94
         * @param file
95
         * @return <b>true</b> when the file is <b>pretty problably</b> text,
96
         * <b>false</b> if the file <b>is</b> binary.
97
         */
98
        public static boolean isTextFile(File file){
99
                return isTextFile(file, 1024);
100
        }
101

    
102
        /**
103
         * Checks a File and tries to figure if the file is a text or a binary file.<br>
104
         * Keep in mind that binary files are those that contains at least one
105
         * non-printable character.
106
         *
107
         * @param file
108
         * @param byteAmount, number of bytes to check.
109
         * @return <b>true</b> when the file is <b>pretty problably</b> text,
110
         * <b>false</b> if the file <b>is</b> binary.
111
         */
112
        public static boolean isTextFile(File file, int byteAmount){
113
                int umbral = byteAmount;
114
                try {
115
                        FileReader fr = new FileReader(file);
116
                        for (int i = 0; i < umbral; i++) {
117
                                int c = fr.read();
118
                                if (c==-1){
119
                                        // End of file. If we reach this
120
                                        // everything before is printable data.
121
                                        return true;
122
                                }
123
                                char ch = (char) c;
124
                                if (characters.indexOf(ch)==-1){
125
                                        // We've found a non-printable character.
126
                                        // Then we'll assume that this file is binary.
127
                                        return false;
128
                                }
129
                        }
130
                } catch (FileNotFoundException e) {
131
                        e.printStackTrace();
132
                } catch (IOException e) {
133
                        e.printStackTrace();
134
                }
135
                return true;
136
        }
137

    
138
        /**
139
         * Checks a byte array and tells if it contains only text or contains
140
         * any binary data.
141
         *
142
         * @param file
143
         * @return <b>true</b> when the data is <b>only</b> text, <b>false</b> otherwise.
144
         * @deprecated
145
         */
146
        public static boolean isTextData(byte[] data){
147
                char[] charData = new char[data.length];
148
                for (int i = 0; i<data.length; i++){
149
                        charData[i] = (char) data[i];
150
                }
151

    
152
                for (int i = 0; i < data.length; i++) {
153
                        int c = charData[i];
154

    
155

    
156
                        if (c==-1){
157
                                // End of file. If we reach this
158
                                // everything before is printable data.
159
                                return true;
160
                        }
161
                        char ch = (char) c;
162
                        if (characters.indexOf(ch)==-1){
163
                                // We've found a non-printable character.
164
                                // Then we'll assume that this file is binary.
165

    
166
                                //System.out.println(ch+" at "+i);
167
                                return false;
168
                        }
169
                }
170
                return true;
171
        }
172

    
173

    
174

    
175

    
176
        /**
177
         * Copia el contenido de un InputStream en un OutputStream
178
         *
179
         * @param in InputStream
180
         * @param out OutputStream
181
         */
182
        public static void serializar(InputStream in, OutputStream out) {
183
                byte[] buffer = new byte[102400];
184

    
185
                int n;
186

    
187
                try {
188
                        while ((n = in.read(buffer)) != -1) {
189
                                out.write(buffer, 0, n);
190
                        }
191
                } catch (IOException e) {
192
                        e.printStackTrace();
193
                }
194
        }
195

    
196
        /**
197
         * Elimina del xml la declaraci?n del DTD
198
         *
199
         * @param bytes bytes del fichero XML de respuesta a getCapabilities
200
         * @param startTag Tag raiz del xml respuesta a getCapabilities
201
         *
202
         * @return bytes del fichero XML sin la declaraci?n del DTD
203
         */
204
        public static byte[] eliminarDTD(byte[] bytes, String startTag) {
205
                String text = new String(bytes);
206
                int index1 = text.indexOf("?>") + 2;
207
                int index2;
208

    
209
                try {
210
                        index2 = findBeginIndex(bytes, startTag);
211
                } catch (NoSuchObjectException e) {
212
                        return bytes;
213
                }
214

    
215
                byte[] buffer = new byte[bytes.length - (index2 - index1)];
216
                System.arraycopy(bytes, 0, buffer, 0, index1);
217
                System.arraycopy(bytes, index2, buffer, index1, bytes.length - index2);
218

    
219
                return buffer;
220
        }
221

    
222
        /**
223
         * Obtiene el ?ndice del comienzo del xml
224
         *
225
         * @param bytes bytes del fichero XML en el que se busca
226
         * @param tagRaiz Tag raiz del xml respuesta a getCapabilities
227
         *
228
         * @return ?ndice donde empieza el tag raiz
229
         *
230
         * @throws NoSuchObjectException Si no se encuentra el tag
231
         */
232
        private static int findBeginIndex(byte[] bytes, String tagRaiz)
233
        throws NoSuchObjectException {
234
                try {
235
                        int nodo = 0;
236
                        int ret = -1;
237

    
238
                        int i = 0;
239

    
240
                        while (true) {
241
                                switch (nodo) {
242
                                case 0:
243

    
244
                                        if (bytes[i] == '<') {
245
                                                ret = i;
246
                                                nodo = 1;
247
                                        }
248

    
249
                                        break;
250

    
251
                                case 1:
252

    
253
                                        if (bytes[i] == ' ') {
254
                                        } else if (bytes[i] == tagRaiz.charAt(0)) {
255
                                                nodo = 2;
256
                                        } else {
257
                                                nodo = 0;
258
                                        }
259

    
260
                                        break;
261

    
262
                                case 2:
263

    
264
                                        String aux = new String(bytes, i, 18);
265

    
266
                                        if (aux.equalsIgnoreCase(tagRaiz.substring(1))) {
267
                                                return ret;
268
                                        }
269

    
270
                                        nodo = 0;
271

    
272
                                        break;
273
                                }
274

    
275
                                i++;
276
                        }
277
                } catch (Exception e) {
278
                        throw new NoSuchObjectException("No se pudo parsear el xml");
279
                }
280
        }
281

    
282
        /**
283
         * Converts the contents of a Vector to a comma separated list
284
         *
285
         * */
286
        public static String Vector2CS(Vector v)
287
        {
288
                String str = new String();
289
                if (v != null)
290
                {
291
                        int i;
292
                        for (i=0; i<v.size() ;i++)
293
                        {
294
                                str = str + v.elementAt(i);
295
                                if (i<v.size()-1)
296
                                        str = str + ",";
297
                        }
298
                }
299
                return str;
300
        }
301

    
302
        public static boolean isValidVersion(String version)
303
        {
304
                if(version.trim().length() == 5)
305
                {
306
                        if ( (version.charAt(1)=='.') && (version.charAt(3)=='.'))
307
                        {
308
                                char x = version.charAt(0);
309
                                char y = version.charAt(2);
310
                                char z = version.charAt(4);
311

    
312
                                if ((Character.isDigit(x)) && (Character.isDigit(y)) && (Character.isDigit(z)))
313
                                {
314
                                        return true;
315
                                }
316
                                else
317
                                {
318
                                        return false;
319
                                }
320
                        }
321
                        else
322
                        {
323
                                return false;
324
                        }
325
                }
326
                else
327
                {
328
                        return false;
329
                }
330
        }
331

    
332
        /**
333
         * Crea un fichero temporal con un nombre concreto y unos datos pasados por
334
         * par?metro.
335
         * @param fileName Nombre de fichero
336
         * @param data datos a guardar en el fichero
337
         */
338
        public static void createTemp(String fileName, String data)throws IOException{
339
                File f = new File(fileName);
340
                DataOutputStream dos = new DataOutputStream( new BufferedOutputStream(new FileOutputStream(f)) );
341
                dos.writeBytes(data);
342
                dos.close();
343
                f.deleteOnExit();
344
        }
345

    
346
        /**
347
         * Checks if a String is a number or not
348
         *
349
         * @param String, s
350
         * @return boolean, true if s is a number
351
         */
352
        public static boolean isNumber(String s)
353
        {
354
                try
355
                {
356
                        //double d = Double.parseDouble(s);
357
                        return true;
358
                }
359
                catch(NumberFormatException e)
360
                {
361
                        return false;
362
                }
363

    
364
        }
365

    
366
        /**
367
         * Parses the String containing different items [character] separated and
368
         * creates a vector with them.
369
         * @param str String contains item1[c]item2[c]item3...
370
         * @param c is the string value for separating the items
371
         * @return Vector containing all the items
372
         */
373
        public static Vector createVector(String str, String c)
374
        {
375
                StringTokenizer tokens = new StringTokenizer(str, c);
376
                Vector v = new Vector();
377
                try
378
                {
379
                        while (tokens.hasMoreTokens())
380
                        {
381
                                v.addElement(tokens.nextToken());
382
                        }
383
                        return v;
384
                }
385
                catch (Exception e)
386
                {
387
                        return new Vector();
388
                }
389
        }
390

    
391
        /**
392
         * @param dimensions
393
         * @return
394
         */
395
        public static String Vector2URLParamString(Vector v) {
396
                if (v==null) return "";
397
                String s = "";
398
                for (int i = 0; i < v.size(); i++) {
399
                        s += v.get(i);
400
                        if (i<v.size()-1)
401
                                s += "&";
402
                }
403
                return s;
404
        }
405

    
406
        /**
407
     * Returns the content of this URL as a file from the file system.<br>
408
     * <p>
409
     * If the URL has been already downloaded in this session and notified
410
     * to the system using the static <b>Utilities.addDownloadedURL(URL)</b>
411
     * method, it can be restored faster from the file system avoiding to
412
     * download it again.
413
     * </p>
414
     * @param url
415
     * @return File containing this URL's content or null if no file was found.
416
     */
417
    private static File getPreviousDownloadedURL(URL url){
418
        File f = null;
419
        if (downloadedFiles!=null && downloadedFiles.containsKey(url)){
420
            String filePath = (String) downloadedFiles.get(url);
421
            f = new File(filePath);
422
            if (!f.exists())
423
                    return null;
424
        }
425
        return f;
426
    }
427

    
428
    /**
429
     * Adds an URL to the table of downloaded files for further uses. If the URL
430
     * already exists in the table its filePath value is updated to the new one and
431
     * the old file itself is removed from the file system.
432
     *
433
     * @param url
434
     * @param filePath
435
     */
436
    static void addDownloadedURL(URL url, String filePath){
437
        if (downloadedFiles==null)
438
            downloadedFiles = new Hashtable();
439
        String fileName = (String) downloadedFiles.put(url, filePath);
440
        //JMV: No se puede eliminar el anterior porque puede que alguien lo
441
        // este usando
442
        /*
443
        if (fileName!=null){
444
            File f = new File(fileName);
445
            if (f.exists())
446
                f.delete();
447
        }
448
        */
449
    }
450

    
451
    /**
452
     * Downloads an URL into a temporary file that is removed the next time the
453
     * tempFileManager class is called, which means the next time gvSIG is launched.
454
     *
455
     * @param url
456
     * @param name
457
     * @return
458
     * @throws IOException
459
     * @throws ServerErrorResponseException
460
     * @throws ConnectException
461
     * @throws UnknownHostException
462
     */
463
    public static synchronized File downloadFile(URL url, String name) throws IOException,ConnectException, UnknownHostException{
464
            File f = null;
465

    
466
            if ((f=getPreviousDownloadedURL(url))==null){
467
                    File tempDirectory = new File(tempDirectoryPath);
468
                    if (!tempDirectory.exists())
469
                            tempDirectory.mkdir();
470

    
471
                    f = new File(tempDirectoryPath+"/"+name+System.currentTimeMillis());
472

    
473
//                    if (cancel == null) {
474
//                            cancel = new ICancellable() {
475
//                                        public boolean isCanceled() {
476
//                                                return false;
477
//                                        }
478
//                            };
479
//                    }
480
                    Thread downloader = new Thread(new Downloader(url, f));
481
//                    Thread monitor = new Thread(new Monitor(cancel));
482
//                    monitor.start();
483
                    downloader.start();
484
                    while(!canceled && downloader.isAlive()) {
485
                            try {
486
                                        Thread.sleep(latency);
487
                                } catch (InterruptedException e) {
488
                                        // TODO Auto-generated catch block
489
                                        e.printStackTrace();
490
                                }
491
                    }
492

    
493
                    if (canceled)
494
                            return null;
495
                    downloader = null;
496
//                    monitor = null;
497
                    if (DownloadUtilities.downloadException!=null) {
498
                            Exception e = DownloadUtilities.downloadException;
499
                            if (e instanceof FileNotFoundException)
500
                                    throw (IOException) e;
501
                            else if (e instanceof IOException)
502
                                    throw (IOException) e;
503
                            else if (e instanceof ConnectException)
504
                                    throw (ConnectException) e;
505
                            else if (e instanceof UnknownHostException)
506
                                    throw (UnknownHostException) e;
507
                    }
508
            } else {
509
                    System.out.println(url.toString()+" cached at '"+f.getAbsolutePath()+"'");
510
            }
511

    
512
            return f;
513
        }
514

    
515
    /**
516
     * Cleans every temporal file previously downloaded.
517
     */
518
    public static void cleanUpTempFiles() {
519
            try{
520
                    File tempDirectory = new File(tempDirectoryPath);
521

    
522
                    File[] files = tempDirectory.listFiles();
523
                    if (files!=null) {
524
                            for (int i = 0; i < files.length; i++) {
525
                                     // s?lo por si en un futuro se necesitan crear directorios temporales
526
                                    if (files[i].isDirectory())        deleteDirectory(files[i]);
527
                                    files[i].delete();
528
                            }
529
                    }
530
                    tempDirectory.delete();
531
            } catch (Exception e) {        }
532

    
533
    }
534
    /**
535
     * Recursive directory delete.
536
     * @param f
537
     */
538
        private static void deleteDirectory(File f) {
539
                File[] files = f.listFiles();
540
                for (int i = 0; i < files.length; i++) {
541
                        if (files[i].isDirectory()) deleteDirectory(files[i]);
542
                        files[i].delete();
543
                }
544

    
545
        }
546

    
547

    
548
    /**
549
     * Remove an URL from the system cache. The file will remain in the file
550
     * system for further eventual uses.
551
     * @param request
552
     */
553
        public static void removeURL(URL url) {
554
                if (downloadedFiles != null && downloadedFiles.containsKey(url))
555
                        downloadedFiles.remove(url);
556
        }
557

    
558

    
559
}
560

    
561
final class Monitor implements Runnable {
562
//        ICancellable c;
563
//        public Monitor(ICancellable cancel) {
564
//                Utilities.canceled = false;
565
//                this.c = cancel;
566
//        }
567
        public void run() {
568
//                while (!c.isCanceled()) {
569
                        try {
570
                                Thread.sleep(DownloadUtilities.latency);
571
                        } catch (InterruptedException e) {
572
                                e.printStackTrace();
573
                        }
574
//                }
575

    
576
                /*  WARNING!! This works because only one download is being processed at once.
577
                 *  You could prefer to start several transfers simultaneously. If so, you
578
                 *  should consideer using a non-static variable such is Utilities.canceled to
579
                 *  control when and which transfer in particular has been canceled.
580
                 *
581
                 *  The feature of transfer several files is at the moment under study. We are
582
                 *  planning to add an intelligent system that will give you a lot of services
583
                 *  and ease-of-use. So, we encourage you to wait for it instead of write your
584
                 *  own code.
585
                 */
586

    
587
                DownloadUtilities.canceled = true;
588
        }
589
}
590

    
591
final class Downloader implements Runnable {
592
        private URL url;
593
        private File dstFile;
594

    
595
        public Downloader(URL url, File dstFile) {
596
                this.url = url;
597
                this.dstFile = dstFile;
598
                DownloadUtilities.downloadException = null;
599
        }
600

    
601
        public void run() {
602
                System.out.println("downloading '"+url.toString()+"' to: "+dstFile.getAbsolutePath());
603

    
604
                DataOutputStream dos;
605
                try {
606
                        dos = new DataOutputStream( new BufferedOutputStream(new FileOutputStream(dstFile)));
607
                        byte[] buffer = new byte[1024*4];
608
                        DataInputStream is = new DataInputStream(url.openStream());
609
                        long readed = 0;
610
                        for (int i = is.read(buffer); !DownloadUtilities.canceled && i>0; i = is.read(buffer)){
611
                                dos.write(buffer, 0, i);
612
                                readed += i;
613

    
614
                        }
615
                        dos.close();
616
                        is.close();
617
                        is = null;
618
                        dos = null;
619
                        if (DownloadUtilities.canceled) {
620
                                System.err.println("[RemoteClients] '"+url+"' CANCELED.");
621
                                dstFile.delete();
622
                                dstFile= null;
623
                        } else {
624
                                DownloadUtilities.addDownloadedURL(url, dstFile.getAbsolutePath());
625
                        }
626
                } catch (Exception e) {
627
                        DownloadUtilities.downloadException = e;
628
                }
629

    
630
        }
631
}