Hi,

This finishes the java code changes for java.lang.ClassLoader.
I added comments to the top of the file that briefly outline how I think
that the rest of the support should be written. Please let me know if
you have ideas how this could be better/easier integrate with the various VMs.

2001-01-10  Mark Wielaard  <[EMAIL PROTECTED]>
    * java/lang/ClassLoader.java: 1.2 updates
    (loadClass(String)): now calls loadClass with resolve set to false not true
    (loadClass(String,boolean)): no longer abstract
    (getResource): now calls parent classloader first
    (getResourceAsStream): Ditto
    (defineClass): There is now a version which takes a ProtectionDomain,
    but that needs native support
    (findLibrary): new method
    (getSystemResources):Ditto

Cheers,

Mark
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!
  **
+ ** <p>
+ ** 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.
+ ** <p>
+ ** 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 (<code>java.class.path</code> 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.
+ ** <p>
+ ** The bootstrap classloader in GNU Classpath is implemented as a couple of
+ ** static (native) methods on the package private class
+ ** <code>java.lang.VMClassLoader</code>, the system classloader is an
+ ** instance of <code>gnu.java.lang.SystemClassloader</code>
+ ** (which is a subclass of <code>java.net.URLClassLoader</code>).
+ ** <p>
+ ** Users of a <code>ClassLoader</code> will normally just use the methods
+ ** <ul>
+ ** <li> <code>loadClass()</code> to load a class.
+ ** <li> <code>getResource()</code> or <code>getResourceAsStream()</code>
+ ** to access a resource.
+ ** <li> <code>getResources()</code> to get an Enumeration of URLs to all
+ ** the resources provided by the classloader and its parents with the same
+ ** name.
+ ** </ul>
+ ** <p>
+ ** Subclasses should implement the methods
+ ** <ul>
+ ** <li> <code>findClass()</code> which is called by <code>loadClass()</code>
+ ** when the parent classloader cannot provide a named class.
+ ** <li> <code>findResource()</code> which is called by
+ ** <code>getResource()</code> when the parent classloader cannot provide
+ ** a named resource.
+ ** <li> <code>findResources()</code> which is called by
+ ** <code>getResource()</code> to combine all the resources with the same name
+ ** from the classloader and its parents.
+ ** <li> <code>findLibrary()</code> which is called by
+ ** <code>Runtime.loadLibrary()</code> when a class defined by the classloader
+ ** wants to load a native library.
+ ** </ul>
+ **
  ** @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 <code>loadClass(name, false)</code>.
+        ** <p>
+        ** Subclasses should not override this method but should override
+        ** <code>findClass()</code> 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 <code>resolveClass()</code>.
+        ** It first tries to find out if the class has already been loaded
+        ** through this classloader by calling <code>findLoadedClass()</code>.
+        ** Then it calls <code>loadClass()</code> 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 <code>findClass()</code>. Finally when
+        ** <code>resolve</code> is <code>true</code> it also calls
+        ** <code>resolveClass()</code> on the newly loaded class.
+        ** <p>
+        ** Subclasses should not override this method but should override
+        ** <code>findClass()</code> 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
+     ** <code>getResource()</code> on the parent classloader.
+     ** If the parent classloader returns null then it tries finding the
+     ** resource by calling <code>findResource()</code> on this
+     ** classloader.
+     ** <p>
+     ** Subclasses should not override this method but should override
+     ** <code>findResource()</code> 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 <code>getResource()</code> and if that
+     ** returns a URL to the resource then it calls and returns the
+     ** InputStream given by <code>URL.openStream()</code>.
+     ** <p>
+     ** Subclasses should not override this method but should override
+     ** <code>findResource()</code> 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.
+        ** <p>
+        ** Subclasses should call this method from their
+        ** <code>findClass()</code> 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.
+     ** <p>
+     ** Subclasses should call this method from their
+     ** <code>findClass()</code> 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 <code>Runtime.loadLibrary()</code> to get an absolute path
+     * to a (system specific) library that was requested by a class loaded
+     * by this classloader. The default implementation returns
+     * <code>null</code>. 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 <code>java.library.path</code> 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);
     }
 
 }

Reply via email to