Statistics
| Revision:

svn-gvsig-desktop / tags / v1_1_Build_1011 / libraries / libRemoteServices / src / org / gvsig / remoteClient / utils / Utilities.java @ 12904

History | View | Annotate | Download (16.8 KB)

1
package org.gvsig.remoteClient.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
import org.gvsig.remoteClient.wms.ICancellable;
62

    
63
import sun.nio.cs.ext.ISCII91;
64

    
65

    
66
/**
67
 * Clase con m?todos de utilidad en el protocolo WMS
68
 *
69
 * @authors Laura D?az, jaume dominguez faus
70
 */
71
public class Utilities {
72
        private static String characters;
73
        static final long latency = 500;
74
        /**
75
         * Used to cancel a group of files
76
     * <b>key</b>: Group id, <b>value</b>: Boolean (true if
77
     * the group has to be canceled. Otherwise it is
78
     * false)
79
     */
80
        static Hashtable canceledGroup = new Hashtable();
81
        /**
82
     * <b>key</b>: URL, <b>value</b>: path to the downloaded file.
83
     */
84
    private static Hashtable downloadedFiles;
85
        static Exception downloadException;
86
    private static final String tempDirectoryPath = System.getProperty("java.io.tmpdir")+"/tmp-andami";
87

    
88

    
89
        static {
90
                characters = "";
91
                for (int j = 32; j<=127; j++){
92
                        characters += (char) j;
93
                }
94
                characters += "?????????????????????????????????????????????????\n\r\f\t??";
95
        }
96

    
97

    
98
        /**
99
         * Checks a File and tries to figure if the file is a text or a binary file.<br>
100
         * Keep in mind that binary files are those that contains at least one
101
         * non-printable character.
102
         *
103
         * @param file
104
         * @return <b>true</b> when the file is <b>pretty problably</b> text,
105
         * <b>false</b> if the file <b>is</b> binary.
106
         */
107
        public static boolean isTextFile(File file){
108
                return isTextFile(file, 1024);
109
        }
110

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

    
147
        /**
148
         * Checks a byte array and tells if it contains only text or contains
149
         * any binary data.
150
         *
151
         * @param file
152
         * @return <b>true</b> when the data is <b>only</b> text, <b>false</b> otherwise.
153
         * @deprecated
154
         */
155
        public static boolean isTextData(byte[] data){
156
                char[] charData = new char[data.length];
157
                for (int i = 0; i<data.length; i++){
158
                        charData[i] = (char) data[i];
159
                }
160

    
161
                for (int i = 0; i < data.length; i++) {
162
                        int c = charData[i];
163

    
164

    
165
                        if (c==-1){
166
                                // End of file. If we reach this
167
                                // everything before is printable data.
168
                                return true;
169
                        }
170
                        char ch = (char) c;
171
                        if (characters.indexOf(ch)==-1){
172
                                // We've found a non-printable character.
173
                                // Then we'll assume that this file is binary.
174

    
175
                                //System.out.println(ch+" at "+i);
176
                                return false;
177
                        }
178
                }
179
                return true;
180
        }
181

    
182

    
183

    
184

    
185
        /**
186
         * Copia el contenido de un InputStream en un OutputStream
187
         *
188
         * @param in InputStream
189
         * @param out OutputStream
190
         */
191
        public static void serializar(InputStream in, OutputStream out) {
192
                byte[] buffer = new byte[102400];
193

    
194
                int n;
195

    
196
                try {
197
                        while ((n = in.read(buffer)) != -1) {
198
                                out.write(buffer, 0, n);
199
                        }
200
                } catch (IOException e) {
201
                        e.printStackTrace();
202
                }
203
        }
204

    
205
        /**
206
         * Elimina del xml la declaraci?n del DTD
207
         *
208
         * @param bytes bytes del fichero XML de respuesta a getCapabilities
209
         * @param startTag Tag raiz del xml respuesta a getCapabilities
210
         *
211
         * @return bytes del fichero XML sin la declaraci?n del DTD
212
         */
213
        public static byte[] eliminarDTD(byte[] bytes, String startTag) {
214
                String text = new String(bytes);
215
                int index1 = text.indexOf("?>") + 2;
216
                int index2;
217

    
218
                try {
219
                        index2 = findBeginIndex(bytes, startTag);
220
                } catch (NoSuchObjectException e) {
221
                        return bytes;
222
                }
223

    
224
                byte[] buffer = new byte[bytes.length - (index2 - index1)];
225
                System.arraycopy(bytes, 0, buffer, 0, index1);
226
                System.arraycopy(bytes, index2, buffer, index1, bytes.length - index2);
227

    
228
                return buffer;
229
        }
230

    
231
        /**
232
         * Obtiene el ?ndice del comienzo del xml
233
         *
234
         * @param bytes bytes del fichero XML en el que se busca
235
         * @param tagRaiz Tag raiz del xml respuesta a getCapabilities
236
         *
237
         * @return ?ndice donde empieza el tag raiz
238
         *
239
         * @throws NoSuchObjectException Si no se encuentra el tag
240
         */
241
        private static int findBeginIndex(byte[] bytes, String tagRaiz)
242
        throws NoSuchObjectException {
243
                try {
244
                        int nodo = 0;
245
                        int ret = -1;
246

    
247
                        int i = 0;
248

    
249
                        while (true) {
250
                                switch (nodo) {
251
                                case 0:
252

    
253
                                        if (bytes[i] == '<') {
254
                                                ret = i;
255
                                                nodo = 1;
256
                                        }
257

    
258
                                        break;
259

    
260
                                case 1:
261

    
262
                                        if (bytes[i] == ' ') {
263
                                        } else if (bytes[i] == tagRaiz.charAt(0)) {
264
                                                nodo = 2;
265
                                        } else {
266
                                                nodo = 0;
267
                                        }
268

    
269
                                        break;
270

    
271
                                case 2:
272

    
273
                                        String aux = new String(bytes, i, 18);
274

    
275
                                        if (aux.equalsIgnoreCase(tagRaiz.substring(1))) {
276
                                                return ret;
277
                                        }
278

    
279
                                        nodo = 0;
280

    
281
                                        break;
282
                                }
283

    
284
                                i++;
285
                        }
286
                } catch (Exception e) {
287
                        throw new NoSuchObjectException("No se pudo parsear el xml");
288
                }
289
        }
290

    
291
        /**
292
         * Converts the contents of a Vector to a comma separated list
293
         *
294
         * */
295
        public static String Vector2CS(Vector v)
296
        {
297
                String str = new String();
298
                if (v != null)
299
                {
300
                        int i;
301
                        for (i=0; i<v.size() ;i++)
302
                        {
303
                                str = str + v.elementAt(i);
304
                                if (i<v.size()-1)
305
                                        str = str + ",";
306
                        }
307
                }
308
                return str;
309
        }
310

    
311
        public static boolean isValidVersion(String version)
312
        {
313
                if(version.trim().length() == 5)
314
                {
315
                        if ( (version.charAt(1)=='.') && (version.charAt(3)=='.'))
316
                        {
317
                                char x = version.charAt(0);
318
                                char y = version.charAt(2);
319
                                char z = version.charAt(4);
320

    
321
                                if ((Character.isDigit(x)) && (Character.isDigit(y)) && (Character.isDigit(z)))
322
                                {
323
                                        return true;
324
                                }
325
                                else
326
                                {
327
                                        return false;
328
                                }
329
                        }
330
                        else
331
                        {
332
                                return false;
333
                        }
334
                }
335
                else
336
                {
337
                        return false;
338
                }
339
        }
340

    
341
        /**
342
         * Crea un fichero temporal con un nombre concreto y unos datos pasados por
343
         * par?metro.
344
         * @param fileName Nombre de fichero
345
         * @param data datos a guardar en el fichero
346
         */
347
        public static void createTemp(String fileName, String data)throws IOException{
348
                File f = new File(fileName);
349
                DataOutputStream dos = new DataOutputStream( new BufferedOutputStream(new FileOutputStream(f)) );
350
                dos.writeBytes(data);
351
                dos.close();
352
                f.deleteOnExit();
353
        }
354

    
355
        /**
356
         * Checks if a String is a number or not
357
         *
358
         * @param String, s
359
         * @return boolean, true if s is a number
360
         */
361
        public static boolean isNumber(String s)
362
        {
363
                try
364
                {
365
                        //double d = Double.parseDouble(s);
366
                        return true;
367
                }
368
                catch(NumberFormatException e)
369
                {
370
                        return false;
371
                }
372

    
373
        }
374

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

    
400
        /**
401
         * @param dimensions
402
         * @return
403
         */
404
        public static String Vector2URLParamString(Vector v) {
405
                if (v==null) return "";
406
                String s = "";
407
                for (int i = 0; i < v.size(); i++) {
408
                        s += v.get(i);
409
                        if (i<v.size()-1)
410
                                s += "&";
411
                }
412
                return s;
413
        }
414

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

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

    
460
    /**
461
     * Downloads an URL into a temporary file that is removed the next time the
462
     * tempFileManager class is called, which means the next time gvSIG is launched.
463
     *
464
     * @param url
465
     * @param name
466
     * @return
467
     * @throws IOException
468
     * @throws ServerErrorResponseException
469
     * @throws ConnectException
470
     * @throws UnknownHostException
471
     */
472
    public static synchronized File downloadFile(URL url, String name, ICancellable cancel) throws IOException,ConnectException, UnknownHostException{
473
            File f = null;
474

    
475
            if ((f=getPreviousDownloadedURL(url))==null){
476
                    File tempDirectory = new File(tempDirectoryPath);
477
                    if (!tempDirectory.exists())
478
                            tempDirectory.mkdir();
479

    
480
                    f = new File(tempDirectoryPath+"/"+name+System.currentTimeMillis());
481

    
482
                    if (cancel == null) {
483
                            cancel = new ICancellable() {
484
                                        public boolean isCanceled() {
485
                                                return false;
486
                                        }
487
                                        public Object getID(){
488
                                                return Utilities.class.getName();
489
                                        }
490
                            };
491
                    }
492
                    Thread downloader = new Thread(new Downloader(url, f, cancel.getID()));
493
                    Thread monitor = new Thread(new Monitor(cancel));
494
                    monitor.start();
495
                    downloader.start();
496
                    while(!getCanceled(cancel.getID()) && downloader.isAlive()) {
497
                            try {
498
                                        Thread.sleep(latency);
499
                                } catch (InterruptedException e) {
500
                                        // TODO Auto-generated catch block
501
                                        e.printStackTrace();
502
                                }
503
                    }
504

    
505
                    if (getCanceled(cancel.getID()))
506
                            return null;
507
                    downloader = null;
508
                    monitor = null;
509
                    if (Utilities.downloadException!=null) {
510
                            Exception e = Utilities.downloadException;
511
                            if (e instanceof FileNotFoundException)
512
                                    throw (IOException) e;
513
                            else if (e instanceof IOException)
514
                                    throw (IOException) e;
515
                            else if (e instanceof ConnectException)
516
                                    throw (ConnectException) e;
517
                            else if (e instanceof UnknownHostException)
518
                                    throw (UnknownHostException) e;
519
                    }
520
            } else {
521
                    System.out.println(url.toString()+" cached at '"+f.getAbsolutePath()+"'");
522
            }
523

    
524
            return f;
525
        }
526
    
527
    /**
528
     * Try if a group of downloads has been canceled
529
     * @param groupId
530
     * Group id
531
     * @return
532
     * If the group has been canceled
533
     */
534
    protected static boolean getCanceled(Object groupId){
535
            Object obj = canceledGroup.get(groupId);
536
            if (obj != null){
537
                    return ((Boolean)obj).booleanValue();
538
            }
539
            return false;
540
    }
541
    
542
    /**
543
     * Cancel a group of downloads
544
     * @param groupId
545
     * Group id
546
     * @param isCanceled
547
     * if the group has to be canceled
548
     */
549
    protected static void setCanceled(Object groupId, boolean isCanceled){
550
            if (groupId == null){
551
                    groupId = Utilities.class.getName();
552
            }
553
            canceledGroup.put(groupId,new Boolean(isCanceled));
554
    }
555

    
556
    /**
557
     * Cleans every temporal file previously downloaded.
558
     */
559
    public static void cleanUpTempFiles() {
560
            try{
561
                    File tempDirectory = new File(tempDirectoryPath);
562

    
563
                    File[] files = tempDirectory.listFiles();
564
                    if (files!=null) {
565
                            for (int i = 0; i < files.length; i++) {
566
                                     // s?lo por si en un futuro se necesitan crear directorios temporales
567
                                    if (files[i].isDirectory())        deleteDirectory(files[i]);
568
                                    files[i].delete();
569
                            }
570
                    }
571
                    tempDirectory.delete();
572
            } catch (Exception e) {        }
573

    
574
    }
575
    /**
576
     * Recursive directory delete.
577
     * @param f
578
     */
579
        private static void deleteDirectory(File f) {
580
                File[] files = f.listFiles();
581
                for (int i = 0; i < files.length; i++) {
582
                        if (files[i].isDirectory()) deleteDirectory(files[i]);
583
                        files[i].delete();
584
                }
585

    
586
        }
587

    
588

    
589
    /**
590
     * Remove an URL from the system cache. The file will remain in the file
591
     * system for further eventual uses.
592
     * @param request
593
     */
594
        public static void removeURL(URL url) {
595
                if (downloadedFiles != null && downloadedFiles.containsKey(url))
596
                        downloadedFiles.remove(url);
597
        }
598

    
599

    
600
}
601

    
602
final class Monitor implements Runnable {
603
        ICancellable c;
604
        public Monitor(ICancellable cancel) {
605
                Utilities.setCanceled(cancel.getID(),false);
606
                this.c = cancel;
607
        }
608
        public void run() {
609
                while (!c.isCanceled()){
610
                        try {
611
                                Thread.sleep(Utilities.latency);
612
                        } catch (InterruptedException e) {
613
                                e.printStackTrace();
614
                        }
615
                }
616

    
617
                /*  WARNING!! This works because only one download is being processed at once.
618
                 *  You could prefer to start several transfers simultaneously. If so, you
619
                 *  should consideer using a non-static variable such is Utilities.canceled to
620
                 *  control when and which transfer in particular has been canceled.
621
                 *
622
                 *  The feature of transfer several files is at the moment under study. We are
623
                 *  planning to add an intelligent system that will give you a lot of services
624
                 *  and ease-of-use. So, we encourage you to wait for it instead of write your
625
                 *  own code.
626
                 */
627

    
628
                Utilities.setCanceled(c.getID(),true);
629
        }
630
}
631

    
632
final class Downloader implements Runnable {
633
        private URL url;
634
        private File dstFile;
635
        private Object groupID = null;
636

    
637
        public Downloader(URL url, File dstFile, Object groupID) {
638
                this.url = url;
639
                this.dstFile = dstFile;
640
                this.groupID = groupID;
641
                Utilities.downloadException = null;
642
        }
643

    
644
        public void run() {
645
                System.out.println("downloading '"+url.toString()+"' to: "+dstFile.getAbsolutePath());
646

    
647
                DataOutputStream dos;
648
                try {
649
                        dos = new DataOutputStream( new BufferedOutputStream(new FileOutputStream(dstFile)));
650
                        byte[] buffer = new byte[1024*4];
651
                        DataInputStream is = new DataInputStream(url.openStream());
652
                        long readed = 0;
653
                        for (int i = is.read(buffer); !Utilities.getCanceled(groupID) && i>0; i = is.read(buffer)){
654
                                dos.write(buffer, 0, i);
655
                                readed += i;
656

    
657
                        }
658
                        dos.close();
659
                        is.close();
660
                        is = null;
661
                        dos = null;
662
                        if (Utilities.getCanceled(groupID)) {
663
                                System.err.println("[RemoteClients] '"+url+"' CANCELED.");
664
                                dstFile.delete();
665
                                dstFile= null;
666
                        } else {
667
                                Utilities.addDownloadedURL(url, dstFile.getAbsolutePath());
668
                        }
669
                } catch (Exception e) {
670
                        Utilities.downloadException = e;
671
                }
672

    
673
        }
674
}