Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: edu/emory/mathcs/util/classloader/URIClassLoader.java


1   /* ***** BEGIN LICENSE BLOCK *****
2    * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3    *
4    * The contents of this file are subject to the Mozilla Public License Version
5    * 1.1 (the "License"); you may not use this file except in compliance with
6    * the License. You may obtain a copy of the License at
7    * http://www.mozilla.org/MPL/
8    *
9    * Software distributed under the License is distributed on an "AS IS" basis,
10   * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11   * for the specific language governing rights and limitations under the
12   * License.
13   *
14   * The Original Code is the Emory Utilities.
15   *
16   * The Initial Developer of the Original Code is
17   * The Distributed Computing Laboratory, Emory University.
18   * Portions created by the Initial Developer are Copyright (C) 2002
19   * the Initial Developer. All Rights Reserved.
20   *
21   * Alternatively, the contents of this file may be used under the terms of
22   * either the GNU General Public License Version 2 or later (the "GPL"), or
23   * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
24   * in which case the provisions of the GPL or the LGPL are applicable instead
25   * of those above. If you wish to allow use of your version of this file only
26   * under the terms of either the GPL or the LGPL, and not to allow others to
27   * use your version of this file under the terms of the MPL, indicate your
28   * decision by deleting the provisions above and replace them with the notice
29   * and other provisions required by the GPL or the LGPL. If you do not delete
30   * the provisions above, a recipient may use your version of this file under
31   * the terms of any one of the MPL, the GPL or the LGPL.
32   *
33   * ***** END LICENSE BLOCK ***** */
34  
35  package edu.emory.mathcs.util.classloader;
36  
37  import java.net.*;
38  import java.util.*;
39  
40  /**
41   * Equivalent of java.net.URLClassloader but without bugs related to ill-formed
42   * URLs and with customizable JAR caching policy. The standard URLClassLoader
43   * accepts URLs containing spaces and other characters which are forbidden in
44   * the URI syntax, according to the RFC 2396.
45   * As a workaround to this problem, Java escapes and un-escapes URLs in various
46   * arbitrary places; however, this is inconsistent and leads to numerous
47   * problems with URLs referring to local files with spaces in the path. SUN
48   * acknowledges the problem, see  but refuses to modify the behavior for
49   * compatibility reasons; see Java Bug Parade 4273532, 4466485.
50   * <p>
51   * Additionally, the JAR caching policy used by
52   * URLClassLoader is system-wide and inflexible: once downloaded JAR files are
53   * never re-downloaded, even if one creates a fresh instance of the class
54   * loader that happens to have the same URL in its search path. In fact, that
55   * policy is a security vulnerability: it is possible to crash any URL class
56   * loader, thus affecting potentially separate part of the system, by creating
57   * URL connection to one of the URLs of that class loader search path and
58   * closing the associated JAR file.
59   * See Java Bug Parade 4405789, 4388666, 4639900.
60   * <p>
61   * This class avoids these problems by 1) using URIs instead of URLs for the
62   * search path (thus enforcing strict syntax conformance and defining precise
63   * escaping semantics), and 2) using custom URLStreamHandler which ensures
64   * per-classloader JAR caching policy.
65   *
66   * @author Dawid Kurzyniec
67   * @version 1.0
68   *
69   * @see File#toURL
70   * @see File#toURI
71   */
72  public class URIClassLoader extends GenericClassLoader {
73  
74      /**
75       * Creates URIClassLoader with the specified search path.
76       * @param uris the search path
77       */
78      public URIClassLoader(URI[] uris) {
79          super(new URIResourceFinder(uris));
80      }
81  
82      /**
83       * Creates URIClassLoader with the specified search path and parent class
84       * loader.
85       * @param uris the search path
86       * @param parent the parent class loader.
87       */
88      public URIClassLoader(URI[] uris, ClassLoader parent) {
89          super(new URIResourceFinder(uris), parent);
90      }
91  
92      /**
93       * Add specified URI at the end of the search path.
94       * @param uri the URI to add
95       */
96      public void addURI(URI uri) {
97          ((URIResourceFinder)finder).addURI(uri);
98      }
99  
100     private static class URIResourceFinder implements ResourceFinder {
101         URL[] urls;
102         final ResourceLoader loader = new ResourceLoader();
103         public URIResourceFinder(URI[] uris) {
104             try {
105                 URL[] urls = new URL[uris.length];
106                 for (int i = 0; i < uris.length; i++) {
107                     urls[i] = uris[i].toURL();
108                 }
109                 this.urls = urls;
110             }
111             catch (MalformedURLException e) {
112                 throw new IllegalArgumentException(e.getMessage());
113             }
114         }
115         public synchronized void addURI(URI uri) {
116             try {
117                 URL url = uri.toURL();
118                 int len = this.urls.length;
119                     URL[] urls = new URL[len + 1];
120                 System.arraycopy(this.urls, 0, urls, 0, len);
121                 urls[len] = url;
122                 this.urls = urls;
123             }
124             catch (MalformedURLException e) {
125                 throw new IllegalArgumentException(e.getMessage());
126             }
127         }
128         private synchronized final URL[] getUrls() {
129             return urls;
130         }
131         public ResourceHandle getResource(String name) {
132             return loader.getResource(getUrls(), name);
133         }
134         public Enumeration getResources(String name) {
135             return loader.getResources(getUrls(), name);
136         }
137         public URL findResource(String name) {
138             return loader.findResource(getUrls(), name);
139         }
140         public Enumeration findResources(String name) {
141             return loader.findResources(getUrls(), name);
142         }
143     }
144 }