1 |
/* URLClassLoader.java -- ClassLoader that loads classes from one or more URLs |
/* URLClassLoader.java -- ClassLoader that loads classes from one or more URLs |
2 |
Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. |
Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 |
3 |
|
Free Software Foundation, Inc. |
4 |
|
|
5 |
This file is part of GNU Classpath. |
This file is part of GNU Classpath. |
6 |
|
|
55 |
import java.security.cert.Certificate; |
import java.security.cert.Certificate; |
56 |
import java.util.Enumeration; |
import java.util.Enumeration; |
57 |
import java.util.HashMap; |
import java.util.HashMap; |
58 |
|
import java.util.Iterator; |
59 |
|
import java.util.StringTokenizer; |
60 |
import java.util.Vector; |
import java.util.Vector; |
61 |
import java.util.jar.Attributes; |
import java.util.jar.Attributes; |
62 |
import java.util.jar.JarEntry; |
import java.util.jar.JarEntry; |
63 |
import java.util.jar.JarFile; |
import java.util.jar.JarFile; |
64 |
import java.util.jar.Manifest; |
import java.util.jar.Manifest; |
65 |
|
|
66 |
|
|
67 |
/** |
/** |
68 |
* A secure class loader that can load classes and resources from |
* A secure class loader that can load classes and resources from |
69 |
* multiple locations. Given an array of <code>URL</code>s this class |
* multiple locations. Given an array of <code>URL</code>s this class |
146 |
private final Vector urls = new Vector(); |
private final Vector urls = new Vector(); |
147 |
|
|
148 |
/** |
/** |
149 |
* Store pre-parsed information for each url into this vector |
* Store pre-parsed information for each url into this vector: each |
150 |
* each element is a URL loader, corresponding to the URL of |
* element is a URL loader. A jar file has its own class-path |
151 |
* the same index in "urls" |
* attribute which adds to the URLs that will be searched, but this |
152 |
|
* does not add to the list of urls. |
153 |
*/ |
*/ |
154 |
private final Vector urlinfos = new Vector(); |
private final Vector urlinfos = new Vector(); |
155 |
|
|
192 |
|
|
193 |
URLLoader(URLClassLoader classloader, URL baseURL) |
URLLoader(URLClassLoader classloader, URL baseURL) |
194 |
{ |
{ |
195 |
|
this(classloader, baseURL, baseURL); |
196 |
|
} |
197 |
|
|
198 |
|
URLLoader(URLClassLoader classloader, URL baseURL, URL overrideURL) |
199 |
|
{ |
200 |
this.classloader = classloader; |
this.classloader = classloader; |
201 |
this.baseURL = baseURL; |
this.baseURL = baseURL; |
202 |
this.noCertCodeSource = new CodeSource(baseURL, null); |
this.noCertCodeSource = new CodeSource(overrideURL, null); |
203 |
} |
} |
204 |
|
|
205 |
/** |
/** |
218 |
{ |
{ |
219 |
return null; |
return null; |
220 |
} |
} |
221 |
|
|
222 |
|
Vector getClassPath() |
223 |
|
{ |
224 |
|
return null; |
225 |
|
} |
226 |
} |
} |
227 |
|
|
228 |
/** |
/** |
292 |
final JarFile jarfile; // The jar file for this url |
final JarFile jarfile; // The jar file for this url |
293 |
final URL baseJarURL; // Base jar: url for all resources loaded from jar |
final URL baseJarURL; // Base jar: url for all resources loaded from jar |
294 |
|
|
295 |
|
Vector classPath; // The "Class-Path" attribute of this Jar's manifest |
296 |
|
|
297 |
public JarURLLoader(URLClassLoader classloader, URL baseURL) |
public JarURLLoader(URLClassLoader classloader, URL baseURL) |
298 |
{ |
{ |
299 |
super(classloader, baseURL); |
super(classloader, baseURL); |
306 |
sb.append("!/"); |
sb.append("!/"); |
307 |
String jarURL = sb.toString(); |
String jarURL = sb.toString(); |
308 |
|
|
309 |
|
this.classPath = null; |
310 |
URL baseJarURL = null; |
URL baseJarURL = null; |
311 |
JarFile jarfile = null; |
JarFile jarfile = null; |
312 |
try |
try |
313 |
{ |
{ |
314 |
baseJarURL = |
baseJarURL = |
315 |
new URL(null, jarURL, classloader.getURLStreamHandler("jar")); |
new URL(null, jarURL, classloader.getURLStreamHandler("jar")); |
316 |
|
|
317 |
jarfile = |
jarfile = |
318 |
((JarURLConnection) baseJarURL.openConnection()).getJarFile(); |
((JarURLConnection) baseJarURL.openConnection()).getJarFile(); |
319 |
} |
|
320 |
|
Manifest manifest; |
321 |
|
Attributes attributes; |
322 |
|
String classPathString; |
323 |
|
|
324 |
|
if ((manifest = jarfile.getManifest()) != null |
325 |
|
&& (attributes = manifest.getMainAttributes()) != null |
326 |
|
&& ((classPathString |
327 |
|
= attributes.getValue(Attributes.Name.CLASS_PATH)) |
328 |
|
!= null)) |
329 |
|
{ |
330 |
|
this.classPath = new Vector(); |
331 |
|
|
332 |
|
StringTokenizer st = new StringTokenizer(classPathString, " "); |
333 |
|
while (st.hasMoreElements ()) |
334 |
|
{ |
335 |
|
String e = st.nextToken (); |
336 |
|
try |
337 |
|
{ |
338 |
|
URL url = new URL(baseURL, e); |
339 |
|
this.classPath.add(url); |
340 |
|
} |
341 |
|
catch (java.net.MalformedURLException xx) |
342 |
|
{ |
343 |
|
// Give up |
344 |
|
} |
345 |
|
} |
346 |
|
} |
347 |
|
} |
348 |
catch (IOException ioe) |
catch (IOException ioe) |
349 |
{ |
{ |
350 |
/* ignored */ |
/* ignored */ |
351 |
} |
} |
352 |
|
|
353 |
this.baseJarURL = baseJarURL; |
this.baseJarURL = baseJarURL; |
381 |
return null; |
return null; |
382 |
} |
} |
383 |
} |
} |
384 |
|
|
385 |
|
Vector getClassPath() |
386 |
|
{ |
387 |
|
return classPath; |
388 |
|
} |
389 |
} |
} |
390 |
|
|
391 |
static final class JarURLResource extends Resource |
static final class JarURLResource extends Resource |
695 |
*/ |
*/ |
696 |
protected void addURL(URL newUrl) |
protected void addURL(URL newUrl) |
697 |
{ |
{ |
698 |
|
urls.add(newUrl); |
699 |
addURLImpl(newUrl); |
addURLImpl(newUrl); |
700 |
} |
} |
701 |
|
|
726 |
urlloaders.put(newUrl, loader); |
urlloaders.put(newUrl, loader); |
727 |
} |
} |
728 |
|
|
729 |
urls.add(newUrl); |
urlinfos.add(loader); |
730 |
urlinfos.add(loader); |
|
731 |
|
Vector extraUrls = loader.getClassPath(); |
732 |
|
if (extraUrls != null) |
733 |
|
{ |
734 |
|
Iterator it = extraUrls.iterator(); |
735 |
|
while (it.hasNext()) |
736 |
|
{ |
737 |
|
URL url = (URL)it.next(); |
738 |
|
URLLoader extraLoader = (URLLoader) urlloaders.get(url); |
739 |
|
if (! urlinfos.contains (extraLoader)) |
740 |
|
addURLImpl(url); |
741 |
|
} |
742 |
|
} |
743 |
|
|
744 |
} |
} |
745 |
} |
} |
746 |
|
|
751 |
private void addURLs(URL[] newUrls) |
private void addURLs(URL[] newUrls) |
752 |
{ |
{ |
753 |
for (int i = 0; i < newUrls.length; i++) |
for (int i = 0; i < newUrls.length; i++) |
754 |
addURLImpl(newUrls[i]); |
addURL(newUrls[i]); |
755 |
} |
} |
756 |
|
|
757 |
/** |
/** |
810 |
String resourceName = className.replace('.', '/') + ".class"; |
String resourceName = className.replace('.', '/') + ".class"; |
811 |
Resource resource = findURLResource(resourceName); |
Resource resource = findURLResource(resourceName); |
812 |
if (resource == null) |
if (resource == null) |
813 |
throw new ClassNotFoundException(className + " not found in " + urls); |
throw new ClassNotFoundException(className + " not found in " + this); |
814 |
|
|
815 |
// Try to read the class data, create the CodeSource, Package and |
// Try to read the class data, create the CodeSource, Package and |
816 |
// construct the class (and watch out for those nasty IOExceptions) |
// construct the class (and watch out for those nasty IOExceptions) |
902 |
} |
} |
903 |
catch (IOException ioe) |
catch (IOException ioe) |
904 |
{ |
{ |
905 |
throw new ClassNotFoundException(className, ioe); |
ClassNotFoundException cnfe; |
906 |
|
cnfe = new ClassNotFoundException(className + " not found in " + this); |
907 |
|
cnfe.initCause(ioe); |
908 |
|
throw cnfe; |
909 |
|
} |
910 |
|
} |
911 |
|
|
912 |
|
// Cached String representation of this URLClassLoader |
913 |
|
private String thisString; |
914 |
|
|
915 |
|
/** |
916 |
|
* Returns a String representation of this URLClassLoader giving the |
917 |
|
* actual Class name, the URLs that are searched and the parent |
918 |
|
* ClassLoader. |
919 |
|
*/ |
920 |
|
public String toString() |
921 |
|
{ |
922 |
|
if (thisString == null) |
923 |
|
{ |
924 |
|
StringBuffer sb = new StringBuffer(); |
925 |
|
sb.append(this.getClass().getName()); |
926 |
|
sb.append("{urls=[" ); |
927 |
|
URL[] thisURLs = getURLs(); |
928 |
|
for (int i = 0; i < thisURLs.length; i++) |
929 |
|
{ |
930 |
|
sb.append(thisURLs[i]); |
931 |
|
if (i < thisURLs.length - 1) |
932 |
|
sb.append(','); |
933 |
|
} |
934 |
|
sb.append(']'); |
935 |
|
sb.append(", parent="); |
936 |
|
sb.append(getParent()); |
937 |
|
sb.append('}'); |
938 |
|
thisString = sb.toString(); |
939 |
} |
} |
940 |
|
return thisString; |
941 |
} |
} |
942 |
|
|
943 |
/** |
/** |
949 |
*/ |
*/ |
950 |
private Resource findURLResource(String resourceName) |
private Resource findURLResource(String resourceName) |
951 |
{ |
{ |
952 |
int max = urls.size(); |
int max = urlinfos.size(); |
953 |
for (int i = 0; i < max; i++) |
for (int i = 0; i < max; i++) |
954 |
{ |
{ |
955 |
URLLoader loader = (URLLoader) urlinfos.elementAt(i); |
URLLoader loader = (URLLoader) urlinfos.elementAt(i); |
1020 |
throws IOException |
throws IOException |
1021 |
{ |
{ |
1022 |
Vector resources = new Vector(); |
Vector resources = new Vector(); |
1023 |
int max = urls.size(); |
int max = urlinfos.size(); |
1024 |
for (int i = 0; i < max; i++) |
for (int i = 0; i < max; i++) |
1025 |
{ |
{ |
1026 |
URLLoader loader = (URLLoader) urlinfos.elementAt(i); |
URLLoader loader = (URLLoader) urlinfos.elementAt(i); |