Revision 33738 branches/v2_0_0_prep/libraries/libRemoteServices/src/org/gvsig/remoteclient/utils/Utilities.java

View differences:

Utilities.java
41 41
 */
42 42

  
43 43
import java.io.BufferedOutputStream;
44
import java.io.DataInputStream;
45 44
import java.io.DataOutputStream;
46 45
import java.io.File;
47 46
import java.io.FileNotFoundException;
......
50 49
import java.io.IOException;
51 50
import java.io.InputStream;
52 51
import java.io.OutputStream;
53
import java.io.OutputStreamWriter;
54 52
import java.net.ConnectException;
55
import java.net.HttpURLConnection;
56 53
import java.net.URL;
57 54
import java.net.UnknownHostException;
58
import java.rmi.NoSuchObjectException;
59
import java.security.KeyManagementException;
60
import java.security.NoSuchAlgorithmException;
61 55
import java.util.Hashtable;
62 56
import java.util.StringTokenizer;
63 57
import java.util.Vector;
64 58

  
65
import javax.net.ssl.HttpsURLConnection;
66
import javax.net.ssl.SSLContext;
67
import javax.net.ssl.TrustManager;
68
import javax.net.ssl.X509TrustManager;
69

  
59
import org.gvsig.compat.CompatLocator;
60
import org.gvsig.compat.net.Downloader;
70 61
import org.gvsig.remoteclient.wms.ICancellable;
71 62

  
72 63

  
......
78 69
 * @authors Laura D?az, jaume dominguez faus
79 70
 */
80 71
public class Utilities {
81
	private static String characters;
72
	private static final Downloader downloader = CompatLocator.getDownloader();
73
    private static String characters;
82 74
	static boolean canceled;
83 75
	static final long latency = 500;
84 76
	/**
......
227 219

  
228 220
		try {
229 221
			index2 = findBeginIndex(bytes, startTag);
230
		} catch (NoSuchObjectException e) {
222
		} catch (Exception e) {
231 223
			return bytes;
232 224
		}
233 225

  
......
246 238
	 *
247 239
	 * @return ?ndice donde empieza el tag raiz
248 240
	 *
249
	 * @throws NoSuchObjectException Si no se encuentra el tag
241
	 * @throws Exception Si no se encuentra el tag
250 242
	 */
251 243
	private static int findBeginIndex(byte[] bytes, String tagRaiz)
252
	throws NoSuchObjectException {
244
	throws Exception {
253 245
		try {
254 246
			int nodo = 0;
255 247
			int ret = -1;
......
294 286
				i++;
295 287
			}
296 288
		} catch (Exception e) {
297
			throw new NoSuchObjectException("No se pudo parsear el xml");
289
			throw new Exception("No se pudo parsear el xml", e);
298 290
		}
299 291
	}
300 292

  
......
421 413
		}
422 414
		return s;
423 415
	}
424

  
416
	
425 417
	/**
426
	 * Return the content of a file that has been created 
427
	 * from a URL using the HTTP GET protocol
428
	 * @param url
429
	 * The URL
430
	 * @return
431
	 * File containing this URL's content or null if no file was found.
432
	 */
433
	private static File getPreviousDownloadedURL(URL url){
434
		return getPreviousDownloaded(url);
435
	}
436

  
437
	/**
438
	 * Return the content of a file that has been created 
439
	 * from a URL using the HTTP POST protocol
440
	 * @param url
441
	 * The URL
442
	 * @param data
443
	 * The data to send on the query
444
	 * @return
445
	 * File containing this URL's content or null if no file was found.
446
	 */
447
	private static File getPreviousDownloadedURL(URL url, String data){
448
		return getPreviousDownloaded(url+data);
449
	}
450

  
451
	/**
452
	 * Returns the content of a URL as a file from the file system.<br>
453
	 * <p>
454
	 * If the URL has been already downloaded in this session and notified
455
	 * to the system using the static <b>Utilities.addDownloadedURL(URL)</b>
456
	 * method, it can be restored faster from the file system avoiding to
457
	 * download it again.
458
	 * </p>
459
	 * @param url
460
	 * @return File containing this URL's content or null if no file was found.
461
	 */
462
	private static File getPreviousDownloaded(Object object){
463
		File f = null;
464
		if (downloadedFiles!=null && downloadedFiles.containsKey(object)){
465
			String filePath = (String) downloadedFiles.get(object);
466
			f = new File(filePath);
467
			if (!f.exists())
468
				return null;
469
		}
470
		return f;
471
	}
472

  
473
	/**
474
	 * Adds an URL to the table of downloaded files for further uses. If the URL
475
	 * already exists in the table its filePath value is updated to the new one and
476
	 * the old file itself is removed from the file system.
477
	 *
478
	 * @param url
479
	 * @param filePath
480
	 */
481
	static void addDownloadedURL(URL url, String filePath){
482
		if (downloadedFiles==null)
483
			downloadedFiles = new Hashtable();
484
		String fileName = (String) downloadedFiles.put(url, filePath);
485
		//JMV: No se puede eliminar el anterior porque puede que alguien lo
486
		// este usando
487
		/*
488
        if (fileName!=null){
489
            File f = new File(fileName);
490
            if (f.exists())
491
                f.delete();
492
        }
493
		 */
494
	}
495

  
496
	/**
497 418
	 * Downloads an URL into a temporary file that is removed the next time the
498 419
	 * tempFileManager class is called, which means the next time gvSIG is launched.
499 420
	 *
......
506 427
	 * @throws UnknownHostException
507 428
	 */
508 429
	public static synchronized File downloadFile(URL url, String name, ICancellable cancel) throws IOException,ConnectException, UnknownHostException{
509
		File f = null;
510

  
511
		if ((f=getPreviousDownloadedURL(url))==null){
512
			File tempDirectory = new File(tempDirectoryPath);
513
			if (!tempDirectory.exists())
514
				tempDirectory.mkdir();
515

  
516
			f = new File(calculateFileName(name));
517

  
518
			if (cancel == null) {
519
				cancel = new ICancellable() {
520
					public boolean isCanceled() {
521
						return false;
522
					}
523
					public Object getID(){
524
						return Utilities.class.getName();
525
					}
526
				};
527
			}
528
			Thread downloader = new Thread(new Downloader(url, f, cancel.getID()));
529
			Thread monitor = new Thread(new Monitor(cancel));
530
			monitor.start();
531
			downloader.start();
532
			while(!getCanceled(cancel.getID()) && downloader.isAlive()) {
533
				try {
534
					Thread.sleep(latency);
535
				} catch (InterruptedException e) {
536
					// TODO Auto-generated catch block
537
					e.printStackTrace();
538
				}
539
			}
540

  
541
			if (getCanceled(cancel.getID()))
542
				return null;
543
			downloader = null;
544
			monitor = null;
545
			if (Utilities.downloadException!=null) {
546
				Exception e = Utilities.downloadException;
547
				if (e instanceof FileNotFoundException)
548
					throw (IOException) e;
549
				else if (e instanceof IOException)
550
					throw (IOException) e;
551
				else if (e instanceof ConnectException)
552
					throw (ConnectException) e;
553
				else if (e instanceof UnknownHostException)
554
					throw (UnknownHostException) e;
555
			}
556
		} else {
557
			System.out.println(url.toString()+" cached at '"+f.getAbsolutePath()+"'");
558
		}
559

  
560
		return f;
430
	    return downloader.downloadFile(url, name, new CancellableAdapter(cancel));
561 431
	}
562 432
	
563 433
	private static String calculateFileName(String name){
......
586 456
	 * @throws UnknownHostException
587 457
	 */
588 458
	public static synchronized File downloadFile(URL url, String data, String name, ICancellable cancel) throws IOException,ConnectException, UnknownHostException{
589
		File f = null;
590

  
591
		if ((f=getPreviousDownloadedURL(url,data))==null){
592
			File tempDirectory = new File(tempDirectoryPath);
593
			if (!tempDirectory.exists())
594
				tempDirectory.mkdir();
595

  
596
			f = new File(calculateFileName(name));
597

  
598
			if (cancel == null) {
599
				cancel = new ICancellable() {
600
					public boolean isCanceled() {
601
						return false;
602
					}
603
					public Object getID(){
604
						return Utilities.class.getName();
605
					}
606
				};
607
			}
608
			Thread downloader = new Thread(new Downloader(url, data, f, cancel.getID()));
609
			Thread monitor = new Thread(new Monitor(cancel));
610
			monitor.start();
611
			downloader.start();
612
			while(!getCanceled(cancel.getID()) && downloader.isAlive()) {
613
				try {
614
					Thread.sleep(latency);
615
				} catch (InterruptedException e) {
616
					// TODO Auto-generated catch block
617
					e.printStackTrace();
618
				}
619
			}
620

  
621
			if (getCanceled(cancel.getID()))
622
				return null;
623
			downloader = null;
624
			monitor = null;
625
			if (Utilities.downloadException!=null) {
626
				Exception e = Utilities.downloadException;
627
				if (e instanceof FileNotFoundException)
628
					throw (IOException) e;
629
				else if (e instanceof IOException)
630
					throw (IOException) e;
631
				else if (e instanceof ConnectException)
632
					throw (ConnectException) e;
633
				else if (e instanceof UnknownHostException)
634
					throw (UnknownHostException) e;
635
			}
636
		} else {
637
			System.out.println(url.toString()+" cached at '"+f.getAbsolutePath()+"'");
638
		}
639

  
640
		return f;
459
	    return downloader.downloadFile(url, data, name, new CancellableAdapter(cancel));
641 460
	}
642 461

  
643 462
	/**
644
	 * Try if a group of downloads has been canceled
645
	 * @param groupId
646
	 * Group id
647
	 * @return
648
	 * If the group has been canceled
649
	 */
650
	protected static boolean getCanceled(Object groupId){
651
		Object obj = canceledGroup.get(groupId);
652
		if (obj != null){
653
			return ((Boolean)obj).booleanValue();
654
		}
655
		return false;
656
	}
657

  
658
	/**
659
	 * Cancel a group of downloads
660
	 * @param groupId
661
	 * Group id
662
	 * @param isCanceled
663
	 * if the group has to be canceled
664
	 */
665
	protected static void setCanceled(Object groupId, boolean isCanceled){
666
		if (groupId == null){
667
			groupId = Utilities.class.getName();
668
		}
669
		canceledGroup.put(groupId,new Boolean(isCanceled));
670
	}
671

  
672
	/**
673 463
	 * Cleans every temporal file previously downloaded.
674 464
	 */
675 465
	public static void cleanUpTempFiles() {
676
		try{
677
			File tempDirectory = new File(tempDirectoryPath);
678

  
679
			File[] files = tempDirectory.listFiles();
680
			if (files!=null) {
681
				for (int i = 0; i < files.length; i++) {
682
					// s?lo por si en un futuro se necesitan crear directorios temporales
683
					if (files[i].isDirectory())	deleteDirectory(files[i]);
684
					files[i].delete();
685
				}
686
			}
687
			tempDirectory.delete();
688
		} catch (Exception e) {	}
689

  
466
		downloader.cleanUpTempFiles();
690 467
	}
691
	/**
692
	 * Recursive directory delete.
693
	 * @param f
694
	 */
695
	private static void deleteDirectory(File f) {
696
		File[] files = f.listFiles();
697
		for (int i = 0; i < files.length; i++) {
698
			if (files[i].isDirectory()) deleteDirectory(files[i]);
699
			files[i].delete();
700
		}
701 468

  
702
	}
703 469

  
704

  
705 470
	/**
706 471
	 * Remove an URL from the system cache. The file will remain in the file
707 472
	 * system for further eventual uses.
708 473
	 * @param request
709 474
	 */
710 475
	public static void removeURL(URL url) {
711
		if (downloadedFiles != null && downloadedFiles.containsKey(url))
712
			downloadedFiles.remove(url);
476
		downloader.removeURL(url);
713 477
	}
714 478

  
715 479
	/**
......
718 482
	 * @param request
719 483
	 */
720 484
	public static void removeURL(Object url) {
721
		if (downloadedFiles != null && downloadedFiles.containsKey(url))
722
			downloadedFiles.remove(url);
485
	    downloader.removeURL(url);
723 486
	}
724
}
487
	
488
	/**
489
	 * This class has to be deleted when all the classes uses the ICancellable
490
	 * method from libCompat
491
	 * @author gvSIG Team
492
	 * @version $Id$
493
	 *
494
	 */
495
	private static class CancellableAdapter implements org.gvsig.compat.net.ICancellable{
496
	    private ICancellable cancellable = null;
725 497

  
726
final class Monitor implements Runnable {
727
	ICancellable c;
728
	public Monitor(ICancellable cancel) {
729
		Utilities.setCanceled(cancel.getID(),false);
730
		this.c = cancel;
731
	}
732
	public void run() {
733
		while (!c.isCanceled()) {
734
			try {
735
				Thread.sleep(Utilities.latency);
736
			} catch (InterruptedException e) {
737
				e.printStackTrace();
738
			}
739
		}
498
        public CancellableAdapter(
499
            org.gvsig.remoteclient.wms.ICancellable cancellable) {
500
            super();
501
            this.cancellable = cancellable;
502
        }
740 503

  
741
		/*  WARNING!! This works because only one download is being processed at once.
742
		 *  You could prefer to start several transfers simultaneously. If so, you
743
		 *  should consideer using a non-static variable such is Utilities.canceled to
744
		 *  control when and which transfer in particular has been canceled.
745
		 *
746
		 *  The feature of transfer several files is at the moment under study. We are
747
		 *  planning to add an intelligent system that will give you a lot of services
748
		 *  and ease-of-use. So, we encourage you to wait for it instead of write your
749
		 *  own code.
750
		 */
504
        public Object getID() {            
505
            return cancellable.getID();
506
        }
751 507

  
752
		Utilities.setCanceled(c.getID(),true);
508
        public boolean isCanceled() {     
509
            return cancellable.isCanceled();
510
        } 	    
753 511
	}
754 512
}
755

  
756
final class Downloader implements Runnable {
757
	private URL url;
758
	private File dstFile;
759
	private Object groupID = null;
760
	private String data = null;
761

  
762
	public Downloader(URL url, File dstFile, Object groupID) {
763
		this.url = url;
764
		this.dstFile = dstFile;
765
		this.groupID = groupID;
766
		Utilities.downloadException = null;
767
	}
768

  
769
	public Downloader(URL url, String data, File dstFile, Object groupID) {
770
		this.url = url;
771
		this.data = data;
772
		this.dstFile = dstFile;
773
		this.groupID = groupID;
774
		Utilities.downloadException = null;
775
	}
776

  
777
	public void run() {
778
		System.out.println("downloading '"+url.toString()+"' to: "+dstFile.getAbsolutePath());
779

  
780
		DataOutputStream dos;
781
		try {
782
			DataInputStream is;
783
			OutputStreamWriter os = null;
784
			HttpURLConnection connection = null;
785
			//If the used protocol is HTTPS
786
			if (url.getProtocol().equals("https")){
787
				disableHttsValidation();
788
			}
789
			connection = (HttpURLConnection)url.openConnection();
790
			//If it uses a HTTP POST
791
			if (data != null){
792
				connection.setRequestProperty("SOAPAction","post");
793
				connection.setRequestMethod("POST");
794
				connection.setDoOutput(true);
795
				connection.setRequestProperty("Content-Type", "text/xml; charset=UTF-8");
796
				os = new OutputStreamWriter(connection.getOutputStream());
797
				os.write(data);
798
				os.flush();	
799
				is = new DataInputStream(connection.getInputStream());
800
			}else{
801
				is = new DataInputStream(url.openStream());
802
			}
803
			
804
			dos = new DataOutputStream( new BufferedOutputStream(new FileOutputStream(dstFile)));
805
			byte[] buffer = new byte[1024*4];
806

  
807

  
808
			long readed = 0;
809
			for (int i = is.read(buffer); !Utilities.getCanceled(groupID) && i>0; i = is.read(buffer)){
810
				dos.write(buffer, 0, i);
811
				readed += i;
812

  
813
			}
814
			if(os != null){
815
				os.close();
816
			}
817
			dos.close();
818
			is.close();
819
			is = null;
820
			dos = null;
821
			if (Utilities.getCanceled(groupID)) {
822
				System.err.println("[RemoteServices] '"+url+"' CANCELED.");
823
				dstFile.delete();
824
				dstFile= null;
825
			} else {
826
				Utilities.addDownloadedURL(url, dstFile.getAbsolutePath());
827
			}
828
		} catch (Exception e) {
829
			e.printStackTrace();
830
			Utilities.downloadException = e;
831
		}		
832
	}
833

  
834
	/**
835
	 * This method disables the Https certificate validation.
836
	 * @throws KeyManagementException
837
	 * @throws NoSuchAlgorithmException
838
	 */
839
	private void disableHttsValidation() throws KeyManagementException, NoSuchAlgorithmException{
840
		// Create a trust manager that does not validate certificate chains
841
		TrustManager[] trustAllCerts = new TrustManager[]{
842
				new X509TrustManager() {
843
					public java.security.cert.X509Certificate[] getAcceptedIssuers() {
844
						return null;
845
					}
846
					public void checkClientTrusted(
847
							java.security.cert.X509Certificate[] certs, String authType) {
848
					}
849
					public void checkServerTrusted(
850
							java.security.cert.X509Certificate[] certs, String authType) {
851
					}
852
				}
853
		};
854

  
855
		// Install the all-trusting trust manager
856
		SSLContext sc = SSLContext.getInstance("SSL");
857
		sc.init(null, trustAllCerts, new java.security.SecureRandom());
858
		HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
859
	}
860
}

Also available in: Unified diff