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 + **

+ **

+ ** Subclasses should implement the methods + **

+ ** ** @author John Keiser - ** @version 1.1.0, Aug 6 1998 + ** @author Mark Wielaard + ** @version 1.1.99, Jan 2000 ** @since JDK1.0 **/ @@ -98,45 +149,124 @@ this.parent = parent; } - /** Load a class using this ClassLoader, resolving it as well. + /** Load a class using this ClassLoader or its parent, + ** without resolving it. Calls 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); } }