You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by ko...@apache.org on 2005/08/13 20:51:45 UTC

svn commit: r232515 - /jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ContinuationClassLoader.java

Author: kohsuke
Date: Sat Aug 13 11:51:41 2005
New Revision: 232515

URL: http://svn.apache.org/viewcvs?rev=232515&view=rev
Log:
rewritten by using the URLClassLoader as the base class

Modified:
    jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ContinuationClassLoader.java

Modified: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ContinuationClassLoader.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ContinuationClassLoader.java?rev=232515&r1=232514&r2=232515&view=diff
==============================================================================
--- jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ContinuationClassLoader.java (original)
+++ jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ContinuationClassLoader.java Sat Aug 13 11:51:41 2005
@@ -15,37 +15,26 @@
  */
 package org.apache.commons.javaflow;
 
+import org.apache.commons.javaflow.bytecode.transformation.ClassTransformer;
+import org.apache.commons.javaflow.bytecode.transformation.bcel.BcelClassTransformer;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
 import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URLClassLoader;
 import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.security.ProtectionDomain;
 import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Enumeration;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-import org.apache.commons.javaflow.bytecode.transformation.ClassTransformer;
-import org.apache.commons.javaflow.bytecode.transformation.bcel.BcelClassTransformer;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 
 /**
- * ClassLoader with bytecode instrumentation for javaflow.
- *
- * <p>
- * This <tt>ClassLoader</tt> works like an <tt>URLClassLoader</tt>
- * in the sense that it locates class files from specified {@link File}s.
- * But instead of simply loading classes into the VM, this class loader
- * performs the bytecode instrumentation necessary for javaflow.
+ * {@link URLClassLoader} with bytecode instrumentation for javaflow.
  *
  * <p>
  * This class loader is useful where the application can set up multiple
@@ -54,110 +43,14 @@
  * <a href="http://forehead.werken.com/">Forehead</a>) and when you can
  * isolate the continuation-enabled portion of your application into a separate
  * jar file.
- *
- * <p>
- * This code is based on <tt>AntClassLoader</tt>.
  */
-public final class ContinuationClassLoader extends ClassLoader {
+public final class ContinuationClassLoader extends URLClassLoader {
 
     private final static Log log = LogFactory.getLog(ContinuationClassLoader.class);
 
-    /**
-     * An enumeration of all resources of a given name found within the
-     * classpath of this class loader. This enumeration is used by the
-     * ClassLoader.findResources method, which is in
-     * turn used by the ClassLoader.getResources method.
-     *
-     * @see ContinuationClassLoader#findResources(String)
-     * @see java.lang.ClassLoader#getResources(String)
-     */
-    private class ResourceEnumeration implements Enumeration {
-        /**
-         * The name of the resource being searched for.
-         */
-        private String resourceName;
-
-        /**
-         * The index of the next classpath element to search.
-         */
-        private int pathElementsIndex;
-
-        /**
-         * The URL of the next resource to return in the enumeration. If this
-         * field is <code>null</code> then the enumeration has been completed,
-         * i.e., there are no more elements to return.
-         */
-        private URL nextResource;
-
-        /**
-         * Constructs a new enumeration of resources of the given name found
-         * within this class loader's classpath.
-         *
-         * @param name the name of the resource to search for.
-         */
-        ResourceEnumeration(String name) {
-            this.resourceName = name;
-            this.pathElementsIndex = 0;
-            findNextResource();
-        }
-
-        /**
-         * Indicates whether there are more elements in the enumeration to
-         * return.
-         *
-         * @return <code>true</code> if there are more elements in the
-         *         enumeration; <code>false</code> otherwise.
-         */
-        public boolean hasMoreElements() {
-            return (this.nextResource != null);
-        }
-
-        /**
-         * Returns the next resource in the enumeration.
-         *
-         * @return the next resource in the enumeration
-         */
-        public Object nextElement() {
-            URL ret = this.nextResource;
-            findNextResource();
-            return ret;
-        }
-
-        /**
-         * Locates the next resource of the correct name in the classpath and
-         * sets <code>nextResource</code> to the URL of that resource. If no
-         * more resources can be found, <code>nextResource</code> is set to
-         * <code>null</code>.
-         */
-        private void findNextResource() {
-            synchronized(ContinuationClassLoader.this) {
-                URL url = null;
-                while ((pathElementsIndex < pathComponents.size())
-                        && (url == null)) {
-                    File pathComponent
-                        = (File) pathComponents.get(pathElementsIndex);
-                    url = getResourceURL(pathComponent, this.resourceName);
-                    pathElementsIndex++;
-                }
-                this.nextResource = url;
-            }
-        }
-    }
-
     private final ClassTransformer transformer;
 
     /**
-     * The size of buffers to be used in this classloader.
-     */
-    private static final int BUFFER_SIZE = 8192;
-
-    /**
-     * The components of the classpath that the classloader searches
-     * for classes. {@link List} of {@link File}s.
-     */
-    private List pathComponents  = new ArrayList();
-
-    /**
      * Indicates whether the parent class loader should be
      * consulted before trying to load with this class loader.
      */
@@ -190,66 +83,42 @@
      */
     private ClassLoader parent = null;
 
-    /**
-     * A hashtable of zip files opened by the classloader (File to ZipFile).
-     */
-    private Map zipFiles = new HashMap();
+    /* The context to be used when loading classes and resources */
+    private final AccessControlContext acc;
 
+    private static final int BUFFER_SIZE = 4096;
 
     /**
-     * Creates a classloader  using the classpath given.
+     * Creates a classloader by using the classpath given.
      *
-     * @param parent The parent classloader to which unsatisfied loading
-     *               attempts are delegated. May be <code>null</code>,
-     *               in which case the classloader which loaded this
-     *               class is used as the parent.
-     * @param classpath
-     *      a {@link Collection} of {@link File}s.
-     *      the classpath to use to load the classes.
-     *      May be <code>null</code>, in which case no path
-     *      elements are set up to start with.
-     */
-    public ContinuationClassLoader(ClassLoader parent, Collection classpath) {
-        this(parent,new BcelClassTransformer(),classpath);
+     * @param urls
+     *      The URLs from which to load classes and resources
+     * @param parent
+     *      The parent classloader to which unsatisfied loading
+     *      attempts are delegated. May be <code>null</code>,
+     *      in which case the {@link ClassLoader#getSystemClassLoader() system classloader}
+     *      is used as the parent.
+     * @param transformer
+     *      This transformer is used to perform the byte-code enhancement.
+     *      May not be null.
+     */
+    public ContinuationClassLoader(URL[] urls, ClassLoader parent, ClassTransformer transformer) {
+        super(urls,fixNullParent(parent));
+        if(transformer==null)
+            throw new IllegalArgumentException();
+        this.transformer = transformer;
+        acc = AccessController.getContext();
     }
 
-    /**
-     * Creates a classloader  using the classpath given.
-     *
-     * @param parent The parent classloader to which unsatisfied loading
-     *               attempts are delegated. May be <code>null</code>,
-     *               in which case the classloader which loaded this
-     *               class is used as the parent.
-     * @param classpath
-     *      a {@link Collection} of {@link File}s.
-     *      the classpath to use to load the classes.
-     *      May be <code>null</code>, in which case no path
-     *      elements are set up to start with.
-     */
-    public ContinuationClassLoader(ClassLoader parent, ClassTransformer transformer, Collection classpath) {
-        this.transformer = transformer;
-        if (parent != null) {
-            setParent(parent);
-        }
-        if(classpath!=null) {
-            for (Iterator itr = classpath.iterator(); itr.hasNext();) {
-                File f = (File) itr.next();
-                addPathFile(f);
-            }
-        }
+    public ContinuationClassLoader(URL[] urls, ClassLoader parent) {
+        this(urls,parent,new BcelClassTransformer());
     }
 
-    /**
-     * Set the parent for this class loader. This is the class loader to which
-     * this class loader will delegate to load classes
-     *
-     * @param parent the parent class loader.
-     */
-    public void setParent(ClassLoader parent) {
-        if (parent == null) {
-            this.parent = ContinuationClassLoader.class.getClassLoader();
+    private static ClassLoader fixNullParent(ClassLoader classLoader) {
+        if(classLoader!=null) {
+            return classLoader;
         } else {
-            this.parent = parent;
+            return getSystemClassLoader();
         }
     }
 
@@ -266,16 +135,6 @@
     }
 
     /**
-     * Add a file to the path
-     *
-     * @param pathComponent the URL which is to be added to the path for
-     *                      this class loader
-     */
-    protected synchronized void addPathFile(File pathComponent) {
-        pathComponents.add(pathComponent);
-    }
-
-    /**
      * Sets whether this classloader should run in isolated mode. In
      * isolated mode, classes not found on the given classpath will
      * not be referred to the parent class loader but will cause a
@@ -349,166 +208,6 @@
     }
 
     /**
-     * Loads a class through this class loader but defer to the parent class
-     * loader.
-     *
-     * This ensures that instances of the returned class will be compatible
-     * with instances which have already been loaded on the parent
-     * loader.
-     *
-     * @param classname The name of the class to be loaded.
-     *                  Must not be <code>null</code>.
-     *
-     * @return the required Class object
-     *
-     * @exception ClassNotFoundException if the requested class does not exist
-     * on this loader's classpath.
-     */
-    public Class forceLoadSystemClass(String classname)
-         throws ClassNotFoundException {
-        log.debug("force system loading " + classname);
-
-        Class theClass = findLoadedClass(classname);
-
-        if (theClass == null) {
-            theClass = findBaseClass(classname);
-        }
-
-        return theClass;
-    }
-
-    /**
-     * Returns a stream to read the requested resource name.
-     *
-     * @param name The name of the resource for which a stream is required.
-     *             Must not be <code>null</code>.
-     *
-     * @return a stream to the required resource or <code>null</code> if the
-     *         resource cannot be found on the loader's classpath.
-     */
-    public InputStream getResourceAsStream(String name) {
-
-        InputStream resourceStream;
-        if (isParentFirst(name)) {
-            resourceStream = loadBaseResource(name);
-            if (resourceStream != null) {
-                log.debug("ResourceStream for " + name
-                    + " loaded from parent loader");
-
-            } else {
-                resourceStream = loadResource(name);
-                if (resourceStream != null) {
-                    log.debug("ResourceStream for " + name
-                        + " loaded from ant loader");
-                }
-            }
-        } else {
-            resourceStream = loadResource(name);
-            if (resourceStream != null) {
-                log.debug("ResourceStream for " + name
-                    + " loaded from ant loader");
-
-            } else {
-                resourceStream = loadBaseResource(name);
-                if (resourceStream != null) {
-                    log.debug("ResourceStream for " + name
-                        + " loaded from parent loader");
-                }
-            }
-        }
-
-        if (resourceStream == null) {
-            log.debug("Couldn't load ResourceStream for " + name);
-        }
-
-        return resourceStream;
-    }
-
-    /**
-     * Returns a stream to read the requested resource name from this loader.
-     *
-     * @param name The name of the resource for which a stream is required.
-     *             Must not be <code>null</code>.
-     *
-     * @return a stream to the required resource or <code>null</code> if
-     *         the resource cannot be found on the loader's classpath.
-     */
-    private synchronized InputStream loadResource(String name) {
-        // we need to search the components of the path to see if we can
-        // find the class we want.
-        InputStream stream = null;
-
-        for (Iterator itr = pathComponents.iterator(); itr.hasNext() && stream==null;) {
-            File pathComponent = (File) itr.next();
-            stream = getResourceStream(pathComponent, name);
-        }
-        return stream;
-    }
-
-    /**
-     * Finds a system resource (which should be loaded from the parent
-     * classloader).
-     *
-     * @param name The name of the system resource to load.
-     *             Must not be <code>null</code>.
-     *
-     * @return a stream to the named resource, or <code>null</code> if
-     *         the resource cannot be found.
-     */
-    private InputStream loadBaseResource(String name) {
-        if (parent == null) {
-            return getSystemResourceAsStream(name);
-        } else {
-            return parent.getResourceAsStream(name);
-        }
-    }
-
-    /**
-     * Returns an inputstream to a given resource in the given file which may
-     * either be a directory or a zip file.
-     *
-     * @param file the file (directory or jar) in which to search for the
-     *             resource. Must not be <code>null</code>.
-     * @param resourceName The name of the resource for which a stream is
-     *                     required. Must not be <code>null</code>.
-     *
-     * @return a stream to the required resource or <code>null</code> if
-     *         the resource cannot be found in the given file.
-     */
-    private synchronized InputStream getResourceStream(File file, String resourceName) {
-        try {
-            if (!file.exists()) {
-                return null;
-            }
-
-            if (file.isDirectory()) {
-                File resource = new File(file, resourceName);
-
-                if (resource.exists()) {
-                    return new FileInputStream(resource);
-                }
-            } else {
-                // is the zip file in the cache
-                ZipFile zipFile = (ZipFile) zipFiles.get(file);
-                if (zipFile == null) {
-                    zipFile = new ZipFile(file);
-                    zipFiles.put(file, zipFile);
-                }
-                ZipEntry entry = zipFile.getEntry(resourceName);
-                if (entry != null) {
-                    return zipFile.getInputStream(entry);
-                }
-            }
-        } catch (Exception e) {
-            log.debug("Ignoring Exception " + e.getClass().getName()
-                + ": " + e.getMessage() + " reading resource " + resourceName
-                + " from " + file);
-        }
-
-        return null;
-    }
-
-    /**
      * Tests whether or not the parent classloader should be checked for
      * a resource before this one. If the resource matches both the
      * "use parent classloader first" and the "use this classloader first"
@@ -550,124 +249,6 @@
     }
 
     /**
-     * Finds the resource with the given name. A resource is
-     * some data (images, audio, text, etc) that can be accessed by class
-     * code in a way that is independent of the location of the code.
-     *
-     * @param name The name of the resource for which a stream is required.
-     *             Must not be <code>null</code>.
-     *
-     * @return a URL for reading the resource, or <code>null</code> if the
-     *         resource could not be found or the caller doesn't have
-     *         adequate privileges to get the resource.
-     */
-    public synchronized URL getResource(String name) {
-        // we need to search the components of the path to see if
-        // we can find the class we want.
-        URL url = null;
-        if (isParentFirst(name)) {
-            url = (parent == null) ? super.getResource(name)
-                                   : parent.getResource(name);
-        }
-
-        if (url != null) {
-            log.debug("Resource " + name + " loaded from parent loader");
-
-        } else {
-            // try and load from this loader if the parent either didn't find
-            // it or wasn't consulted.
-            for (Iterator itr = pathComponents.iterator(); itr.hasNext() && url==null;) {
-                File pathComponent = (File) itr.next();
-                url = getResourceURL(pathComponent, name);
-                if (url != null) {
-                    log.debug("Resource " + name
-                        + " loaded from ant loader");
-                }
-            }
-        }
-
-        if (url == null && !isParentFirst(name)) {
-            // this loader was first but it didn't find it - try the parent
-
-            url = (parent == null) ? super.getResource(name)
-                : parent.getResource(name);
-            if (url != null) {
-                log.debug("Resource " + name + " loaded from parent loader");
-            }
-        }
-
-        if (url == null) {
-            log.debug("Couldn't load Resource " + name);
-        }
-
-        return url;
-    }
-
-    /**
-     * Returns an enumeration of URLs representing all the resources with the
-     * given name by searching the class loader's classpath.
-     *
-     * @param name The resource name to search for.
-     *             Must not be <code>null</code>.
-     * @return an enumeration of URLs for the resources
-     */
-    protected Enumeration findResources(String name) {
-        return new ResourceEnumeration(name);
-    }
-
-    /**
-     * Returns the URL of a given resource in the given file which may
-     * either be a directory or a zip file.
-     *
-     * @param file The file (directory or jar) in which to search for
-     *             the resource. Must not be <code>null</code>.
-     * @param resourceName The name of the resource for which a stream
-     *                     is required. Must not be <code>null</code>.
-     *
-     * @return a stream to the required resource or <code>null</code> if the
-     *         resource cannot be found in the given file object.
-     */
-    protected synchronized URL getResourceURL(File file, String resourceName) {
-        try {
-            if (!file.exists()) {
-                return null;
-            }
-
-            if (file.isDirectory()) {
-                File resource = new File(file, resourceName);
-
-                if (resource.exists()) {
-                    try {
-                        return resource.toURL();
-                    } catch (MalformedURLException ex) {
-                        return null;
-                    }
-                }
-            } else {
-                ZipFile zipFile = (ZipFile) zipFiles.get(file);
-                if (zipFile == null) {
-                    zipFile = new ZipFile(file);
-                    zipFiles.put(file, zipFile);
-                }
-
-                ZipEntry entry = zipFile.getEntry(resourceName);
-                if (entry != null) {
-                    try {
-                        return new URL("jar:" + file.toURL()
-                            + "!/" + entry);
-                    } catch (MalformedURLException ex) {
-                        return null;
-                    }
-                }
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-
-        return null;
-    }
-
-    /**
      * Loads a class with this class loader.
      *
      * This class attempts to load the class in an order determined by whether
@@ -700,7 +281,7 @@
 
         if (isParentFirst(classname)) {
             try {
-                theClass = findBaseClass(classname);
+                theClass = parent.loadClass(classname);
                 log.debug("Class " + classname + " loaded from parent loader "
                     + "(parentFirst)");
             } catch (ClassNotFoundException cnfe) {
@@ -716,7 +297,7 @@
                 if (ignoreBase) {
                     throw cnfe;
                 }
-                theClass = findBaseClass(classname);
+                theClass = parent.loadClass(classname);
                 log.debug("Class " + classname + " loaded from parent loader");
             }
         }
@@ -729,33 +310,31 @@
     }
 
     /**
-     * Converts the class dot notation to a filesystem equivalent for
-     * searching purposes.
-     *
-     * @param classname The class name in dot format (eg java.lang.Integer).
-     *                  Must not be <code>null</code>.
-     *
-     * @return the classname in filesystem format (eg java/lang/Integer.class)
-     */
-    private String getClassFilename(String classname) {
-        return classname.replace('.', '/') + ".class";
-    }
-
-    /**
      * Define a class given its bytes
      *
-     * @param container the container from which the class data has been read
-     *                  may be a directory or a jar/zip file.
-     *
      * @param classData the bytecode data for the class
      * @param classname the name of the class
      *
      * @return the Class instance created from the given data
      */
-    protected Class defineClassFromData(File container, byte[] classData, String classname) {
-        classData = transformer.transform(classData);
-        ProtectionDomain domain = this.getClass().getProtectionDomain();
-        return defineClass(classname,classData,0,classData.length,domain);
+    protected Class defineClassFromData(final byte[] classData, final String classname) {
+        return (Class)AccessController.doPrivileged(new PrivilegedAction() {
+            public Object run() {
+                // define a package if necessary.
+                int i = classname.lastIndexOf('.');
+                if (i>0) {
+                    String packageName = classname.substring(0,i);
+                    Package pkg = getPackage(packageName);
+                    if(pkg==null) {
+                        definePackage(packageName,null,null,null,null,null,null,null);
+                    }
+                }
+
+                byte[] newData = transformer.transform(classData);
+                ProtectionDomain domain = this.getClass().getProtectionDomain();
+                return defineClass(classname,newData,0,newData.length,domain);
+            }
+        },acc);
     }
 
     /**
@@ -765,7 +344,6 @@
      *               Must not be <code>null</code>.
      * @param classname The name of the class in the stream.
      *                  Must not be <code>null</code>.
-     * @param container the file or directory containing the class.
      *
      * @return the Class object read from the stream.
      *
@@ -774,8 +352,7 @@
      * @exception SecurityException if there is a security problem while
      * reading the class from the stream.
      */
-    private Class getClassFromStream(InputStream stream, String classname,
-                                       File container)
+    private Class getClassFromStream(InputStream stream, String classname)
                 throws IOException, SecurityException {
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         int bytesRead;
@@ -786,7 +363,7 @@
         }
 
         byte[] classData = baos.toByteArray();
-        return defineClassFromData(container, classData, classname);
+        return defineClassFromData(classData, classname);
     }
 
     /**
@@ -800,117 +377,52 @@
      * @exception ClassNotFoundException if the requested class does not exist
      *                                   on this loader's classpath.
      */
-    public Class findClass(String name) throws ClassNotFoundException {
+    public Class findClass(final String name) throws ClassNotFoundException {
         log.debug("Finding class " + name);
 
-        return findClassInComponents(name);
-    }
-
-    /**
-     * Indicate if the given URL is in this loader's path
-     *
-     * @param component the URL which is to be checked
-     *
-     * @return true if the URL is in the class path
-     */
-    protected synchronized boolean isInPath(File component) {
-        for (Iterator itr = pathComponents.iterator(); itr.hasNext();) {
-            File pathComponent = (File) itr.next();
-            if (pathComponent.equals(component)) {
-                return true;
-            }
-        }
-        return false;
-    }
+        // locate the class file
+        String classFileName = name.replace('.', '/') + ".class";
 
+        InputStream stream = getResourceAsStream(classFileName);
+        if(stream==null)
+            throw new ClassNotFoundException(name);
 
-    /**
-     * Finds a class on the given classpath.
-     *
-     * @param name The name of the class to be loaded. Must not be
-     *             <code>null</code>.
-     *
-     * @return the required Class object
-     *
-     * @exception ClassNotFoundException if the requested class does not exist
-     * on this loader's classpath.
-     */
-    private synchronized Class findClassInComponents(String name)
-         throws ClassNotFoundException {
-        // we need to search the components of the path to see if
-        // we can find the class we want.
-        InputStream stream = null;
-        String classFilename = getClassFilename(name);
         try {
-            for (Iterator itr = pathComponents.iterator(); itr.hasNext();) {
-                File pathComponent = (File) itr.next();
-                try {
-                    stream = getResourceStream(pathComponent, classFilename);
-                    if (stream != null) {
-                        log.debug("Loaded from " + pathComponent + " " + classFilename);
-                        return getClassFromStream(stream, name, pathComponent);
-                    }
-                } catch (SecurityException se) {
-                    throw se;
-                } catch (IOException ioe) {
-                    // ioe.printStackTrace();
-                    log.debug("Exception reading component " + pathComponent
-                        + " (reason: " + ioe.getMessage() + ")");
-                }
-            }
-
-            throw new ClassNotFoundException(name);
+            return getClassFromStream(stream, name);
+        } catch (IOException e) {
+            throw new ClassNotFoundException(name,e);
         } finally {
             try {
-                if (stream != null) {
-                    stream.close();
-                }
+                stream.close();
             } catch (IOException e) {
-                //ignore
+                // ignore
             }
         }
     }
 
     /**
-     * Finds a system class (which should be loaded from the same classloader
-     * as the Ant core).
-     *
-     * For JDK 1.1 compatibility, this uses the findSystemClass method if
-     * no parent classloader has been specified.
+     * Finds the resource with the given name. A resource is
+     * some data (images, audio, text, etc) that can be accessed by class
+     * code in a way that is independent of the location of the code.
      *
-     * @param name The name of the class to be loaded.
+     * @param name The name of the resource for which a stream is required.
      *             Must not be <code>null</code>.
-     *
-     * @return the required Class object
-     *
-     * @exception ClassNotFoundException if the requested class does not exist
-     * on this loader's classpath.
+     * @return a URL for reading the resource, or <code>null</code> if the
+     *         resource could not be found or the caller doesn't have
+     *         adequate privileges to get the resource.
      */
-    private Class findBaseClass(String name) throws ClassNotFoundException {
-        if (parent == null) {
-            return findSystemClass(name);
-        } else {
-            return parent.loadClass(name);
+    public synchronized URL getResource(String name) {
+        // we need to search the components of the path to see if
+        // we can find the class we want.
+        if (isParentFirst(name)) {
+            return super.getResource(name);
         }
-    }
 
-    protected void finalize() {
-        cleanup();
-    }
-
-    /**
-     * Cleans up any resources held by this classloader. Any open archive
-     * files are closed.
-     */
-    public synchronized void cleanup() {
-        for (Iterator itr = zipFiles.values().iterator(); itr.hasNext();) {
-            ZipFile zipFile = (ZipFile) itr.next();
-            try {
-                zipFile.close();
-            } catch (IOException ioe) {
-                // ignore
-            }
+        // try this class loader first, then parent
+        URL url = findResource(name);
+        if(url==null) {
+            url = parent.getResource(name);
         }
-        zipFiles = new HashMap();
+        return url;
     }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org