Index: java/lang/ClassLoader.java =================================================================== RCS file: /cvs/classpath/java/lang/ClassLoader.java,v retrieving revision 1.10 diff -u -r1.10 ClassLoader.java --- java/lang/ClassLoader.java 2001/01/09 23:35:07 1.10 +++ java/lang/ClassLoader.java 2001/01/10 12:19:06 @@ -31,6 +31,7 @@ import gnu.java.lang.*; import java.io.*; import java.net.*; +import java.security.*; import java.util.*; import gnu.java.util.DoubleEnumeration; import gnu.java.util.EmptyEnumeration; @@ -45,8 +46,58 @@ ** ** XXX - Not all support has been written for the new 1.2 methods yet! ** + **
+ ** Every classloader has a parent classloader that is consulted before + ** the 'child' classloader when classes or resources should be loaded. + ** This is done to make sure that classes can be loaded from an hierarchy of + ** multiple classloaders and classloaders do not accidentially redefine + ** already loaded classes by classloaders higher in the hierarchy. + **
+ ** The grandparent of all classloaders is the bootstrap classloader.
+ ** It is one of two special classloaders.
+ ** The bootstrap classloader loads all the standard system classes as
+ ** implemented by GNU Classpath. The other special classloader is the
+ ** system classloader (also called application classloader) that loads
+ ** all classes from the classpath (java.class.path
system
+ ** property). The system classloader is responsible for finding the
+ ** application classes from the classpath, and delegates all requests for
+ ** the standard library classes to its parent the bootstrap classloader.
+ ** Most programs will load all their classes through the system classloaders.
+ **
+ ** The bootstrap classloader in GNU Classpath is implemented as a couple of
+ ** static (native) methods on the package private class
+ ** java.lang.VMClassLoader
, the system classloader is an
+ ** instance of gnu.java.lang.SystemClassloader
+ ** (which is a subclass of java.net.URLClassLoader
).
+ **
+ ** Users of a ClassLoader
will normally just use the methods
+ **
loadClass()
to load a class.
+ ** getResource()
or getResourceAsStream()
+ ** to access a resource.
+ ** getResources()
to get an Enumeration of URLs to all
+ ** the resources provided by the classloader and its parents with the same
+ ** name.
+ ** + ** Subclasses should implement the methods + **
findClass()
which is called by loadClass()
+ ** when the parent classloader cannot provide a named class.
+ ** findResource()
which is called by
+ ** getResource()
when the parent classloader cannot provide
+ ** a named resource.
+ ** findResources()
which is called by
+ ** getResource()
to combine all the resources with the same name
+ ** from the classloader and its parents.
+ ** findLibrary()
which is called by
+ ** Runtime.loadLibrary()
when a class defined by the classloader
+ ** wants to load a native library.
+ ** loadClass(name, false)
.
+ **
+ ** Subclasses should not override this method but should override
+ ** findClass()
which is called by this method.
+ **
** @param name the name of the class relative to this ClassLoader.
** @exception ClassNotFoundException if the class cannot be found to
** be loaded.
** @return the loaded class.
**/
public Class loadClass(String name) throws ClassNotFoundException {
- return loadClass(name,true);
+ return loadClass(name,false);
}
- /** Load a class using this ClassLoader, possibly resolving it as well
- ** using resolveClass().
- ** @param name the name of the class relative to this ClassLoader.
+ /** Load a class using this ClassLoader or its parent,
+ ** possibly resolving it as well using resolveClass()
.
+ ** It first tries to find out if the class has already been loaded
+ ** through this classloader by calling findLoadedClass()
.
+ ** Then it calls loadClass()
on the parent classloader
+ ** (or when there is no parent on the bootstrap classloader).
+ ** When the parent could not load the class it tries to create
+ ** a new class by calling findClass()
. Finally when
+ ** resolve
is true
it also calls
+ ** resolveClass()
on the newly loaded class.
+ **
+ ** Subclasses should not override this method but should override
+ ** findClass()
which is called by this method.
+ **
+ ** @param name the fully qualified name of the class to load.
** @param resolve whether or not to resolve the class.
** @exception ClassNotFoundException if the class cannot be found to
** be loaded.
** @return the loaded class.
**/
- protected abstract Class loadClass(String name, boolean resolve) throws ClassNotFoundException;
-
- /** Get the URL to a resource using this classloader.
- ** @param name the name of the resource relative to this
- ** classloader.
- ** @return the URL to the resource.
- **/
- public URL getResource(String name) {
- return ClassLoader.getSystemResource(name);
- }
-
- /** Get a resource using this classloader.
- ** @param name the name of the resource relative to this
- ** classloader.
- ** @return the resource.
- **/
- public InputStream getResourceAsStream(String name) {
- return ClassLoader.getSystemResourceAsStream(name);
+ protected synchronized Class loadClass(String name, boolean resolve)
+ throws ClassNotFoundException
+ {
+ // Have we already loaded this class?
+ Class c = findLoadedClass(name);
+ if (c != null)
+ return c;
+
+ // Can the class be loaded by one of our parent?
+ try {
+ if (parent == null)
+ // XXX - use the bootstrap classloader
+ // return VMClassLoader.loadClass(name, resolve);
+ return findSystemClass(name);
+ else
+ return parent.loadClass(name, resolve);
+ } catch (ClassNotFoundException e) { /* ignore use findClass() */ }
+
+ // Still not found, we have to do it ourselfs.
+ c = findClass(name);
+
+ // resolve if necessary
+ if (resolve)
+ resolveClass(c);
+
+ return c;
+ }
+
+ /** Get the URL to a resource using this classloader
+ ** or one of its parents. First tries to get the resource by calling
+ ** getResource()
on the parent classloader.
+ ** If the parent classloader returns null then it tries finding the
+ ** resource by calling findResource()
on this
+ ** classloader.
+ **
+ ** Subclasses should not override this method but should override
+ ** findResource()
which is called by this method.
+ **
+ ** @param name the name of the resource relative to this
+ ** classloader.
+ ** @return the URL to the resource or null when not found.
+ **/
+ public URL getResource(String name) {
+ URL result;
+
+ if (parent == null)
+ // XXX - try bootstrap classloader;
+ // result = VMClassLoader.getResource(name);
+ return ClassLoader.getSystemResource(name);
+ else
+ result = parent.getResource(name);
+
+ if (result == null)
+ result = findResource(name);
+
+ return result;
}
-
+ /** Get a resource as stream using this classloader or one of its
+ ** parents. First calls getResource()
and if that
+ ** returns a URL to the resource then it calls and returns the
+ ** InputStream given by URL.openStream()
.
+ **
+ ** Subclasses should not override this method but should override
+ ** findResource()
which is called by this method.
+ **
+ ** @param name the name of the resource relative to this
+ ** classloader.
+ ** @return An InputStream to the resource or null when the resource
+ ** could not be found or when the stream could not be opened.
+ **/
+ public InputStream getResourceAsStream(String name) {
+ URL url = getResource(name);
+ if (url == null)
+ return(null);
+
+ try {
+ return url.openStream();
+ } catch(IOException e) {
+ return null;
+ }
+ }
+
/** Helper to define a class using a string of bytes.
** @param data the data representing the classfile, in classfile format.
** @param offset the offset into the data where the classfile starts.
@@ -148,7 +278,11 @@
return defineClass(null,data,offset,len);
}
- /** Helper to define a class using a string of bytes.
+ /** Helper to define a class using a string of bytes without a
+ ** ProtectionDomain.
+ **
+ ** Subclasses should call this method from their
+ ** findClass()
implementation.
** @param name the name to give the class. null if unknown.
** @param data the data representing the classfile, in classfile format.
** @param offset the offset into the data where the classfile starts.
@@ -157,11 +291,45 @@
** @exception ClassFormatError if the byte array is not in proper classfile format.
**/
protected final Class defineClass(String name, byte[] data, int offset, int len) throws ClassFormatError {
+ // XXX - return defineClass(name,data,offset,len,null);
Class retval = VMClassLoader.defineClass(this,name,data,offset,len);
loadedClasses.put(retval.getName(),retval);
return retval;
}
+ /** Helper to define a class using a string of bytes.
+ **
+ ** Subclasses should call this method from their
+ ** findClass()
implementation.
+ **
+ ** XXX - not implemented yet. Needs native support.
+ **
+ ** @param name the name to give the class. null if unknown.
+ ** @param data the data representing the classfile, in classfile format.
+ ** @param offset the offset into the data where the classfile starts.
+ ** @param len the length of the classfile data in the array.
+ ** @param domain the ProtectionDomain to give to the class.
+ ** null if unknown (the class will get the default protection domain).
+ ** @return the class that was defined.
+ ** @exception ClassFormatError if the byte array is not in proper
+ ** classfile format.
+ **
+ ** @since 1.2
+ **/
+ protected final Class defineClass(String name, byte[] data, int offset,
+ int len, ProtectionDomain domain)
+ throws ClassFormatError
+ {
+ /*
+ XXX - needs native support.
+ Class retval
+ = VMClassLoader.defineClass(this,name,data,offset,len,domain);
+ loadedClasses.put(retval.getName(),retval);
+ return retval;
+ */
+ return defineClass(name, data, offset, len, domain);
+ }
+
/** Helper to resolve all references to other classes from this class.
** @param c the class to resolve.
**/
@@ -513,6 +681,45 @@
parentResources = parent.getResources(name);
return new DoubleEnumeration(parentResources, findResources(name));
+ }
+
+ /**
+ * Called by Runtime.loadLibrary()
to get an absolute path
+ * to a (system specific) library that was requested by a class loaded
+ * by this classloader. The default implementation returns
+ * null
. It should be implemented by subclasses when they
+ * have a way to find the absolute path to a library. If this method
+ * returns null the library is searched for in the default locations
+ * (the directories listed in the java.library.path
system
+ * property).
+ *
+ * @param name the (system specific) name of the requested library.
+ * @return the full pathname to the requested library
+ * or null when not found
+ *
+ * @see Runtime#loadLibrary()
+ * @since 1.2
+ */
+ protected String findLibrary(String name)
+ {
+ return null;
+ }
+
+ /** Get an Enumeration of URLs to resources with a given name using
+ ** the system classloader. The enumeration firsts lists the resources
+ ** with the given name that can be found by the bootstrap classloader
+ ** followed by the resources with the given name that can be found
+ ** on the classpath.
+ ** @param name the name of the resource relative to the
+ ** system classloader.
+ ** @return an Enumeration of URLs to the resources.
+ **
+ ** @since 1.2
+ **/
+ public static Enumeration getSystemResources(String name)
+ throws IOException
+ {
+ return systemClassLoader.getResources(name);
}
}