You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by da...@apache.org on 2006/05/04 04:53:54 UTC

svn commit: r399522 - in /geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel: classloader/ classloader/jar/ classloader/jarcache/ classloader/util/ config/

Author: dain
Date: Wed May  3 19:53:50 2006
New Revision: 399522

URL: http://svn.apache.org/viewcvs?rev=399522&view=rev
Log:
Added new JarFile based class loader which lets us have complete control over the file locks.
The new class loader was created by merging the XBean JarFileClassLoader, some of the sandbox classloader and the Jar handling code from deployment.
The new class loader is disabled by default and can be enabled with -DXorg.apache.geronimo.NewClassLoader=true

Added:
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/
      - copied from r393370, geronimo/sandbox/classloader/src/java/org/apache/geronimo/kernel/classloader/
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/AbstractResourceHandle.java
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarFileClassLoader.java
      - copied, changed from r380988, geronimo/xbean/trunk/xbean-server/src/main/java/org/apache/xbean/server/classloader/JarFileClassLoader.java
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarFileResourceFinder.java
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarFileUrlConnection.java
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarFileUrlStreamHandler.java
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarResourceHandle.java
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/ResourceHandle.java
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/
      - copied from r399117, geronimo/branches/1.1/modules/deployment/src/java/org/apache/geronimo/deployment/util/
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/ClassLoaderUtil.java   (with props)
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/UnionEnumeration.java
Removed:
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/GenericClassLoader.java
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/ResourceLoader.java
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/ResourceUtils.java
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/URIClassLoader.java
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/jar/
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/jarcache/
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/DeploymentUtil.java
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/URLInfo.java
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/URLType.java
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/UnclosableInputStream.java
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/UnclosableOutputStream.java
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/XMLUtil.java
Modified:
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/ResourceFinder.java
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/NestedJarEntry.java
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/NestedJarFile.java
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/UnpackedJarEntry.java
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/UnpackedJarFile.java
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/Configuration.java
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/MultiParentClassLoader.java

Added: geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/AbstractResourceHandle.java
URL: http://svn.apache.org/viewcvs/geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/AbstractResourceHandle.java?rev=399522&view=auto
==============================================================================
--- geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/AbstractResourceHandle.java (added)
+++ geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/AbstractResourceHandle.java Wed May  3 19:53:50 2006
@@ -0,0 +1,65 @@
+/**
+ *
+ * Copyright 2005 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.geronimo.kernel.classloader;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.cert.Certificate;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+
+import org.apache.geronimo.kernel.classloader.util.ClassLoaderUtil;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public abstract class AbstractResourceHandle implements ResourceHandle {
+    public byte[] getBytes() throws IOException {
+        InputStream in = getInputStream();
+        try {
+            byte[] bytes = ClassLoaderUtil.getBytes(in);
+            return bytes;
+        } finally {
+            ClassLoaderUtil.close(in);
+        }
+    }
+
+    public Manifest getManifest() throws IOException {
+        return null;
+    }
+
+    public Certificate[] getCertificates() {
+        return null;
+    }
+
+    public Attributes getAttributes() throws IOException {
+        Manifest m = getManifest();
+        if (m == null) {
+            return null;
+        }
+
+        String entry = getURL().getFile();
+        return m.getAttributes(entry);
+    }
+
+    public void close() {
+    }
+
+    public String toString() {
+        return "[" + getName() + ": " + getURL() + "; code source: " + getCodeSourceURL() + "]";
+    }
+}

Copied: geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarFileClassLoader.java (from r380988, geronimo/xbean/trunk/xbean-server/src/main/java/org/apache/xbean/server/classloader/JarFileClassLoader.java)
URL: http://svn.apache.org/viewcvs/geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarFileClassLoader.java?p2=geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarFileClassLoader.java&p1=geronimo/xbean/trunk/xbean-server/src/main/java/org/apache/xbean/server/classloader/JarFileClassLoader.java&r1=380988&r2=399522&rev=399522&view=diff
==============================================================================
--- geronimo/xbean/trunk/xbean-server/src/main/java/org/apache/xbean/server/classloader/JarFileClassLoader.java (original)
+++ geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarFileClassLoader.java Wed May  3 19:53:50 2006
@@ -14,32 +14,28 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-package org.apache.xbean.server.classloader;
+package org.apache.geronimo.kernel.classloader;
 
-import java.io.ByteArrayOutputStream;
-import java.io.File;
 import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
+import java.io.File;
 import java.net.URL;
-import java.net.URLStreamHandlerFactory;
+import java.net.URI;
+import java.security.AccessControlContext;
+import java.security.AccessController;
 import java.security.CodeSource;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
+import java.security.PrivilegedActionException;
 import java.security.cert.Certificate;
-import java.util.Collections;
+import java.util.Collection;
 import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.StringTokenizer;
-import java.util.Arrays;
-import java.util.ArrayList;
 import java.util.jar.Attributes;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
 import java.util.jar.Manifest;
 
+import org.apache.geronimo.kernel.classloader.util.UnionEnumeration;
+import org.apache.geronimo.kernel.config.MultiParentClassLoader;
+import org.apache.geronimo.kernel.repository.Artifact;
+
 /**
  * The JarFileClassLoader that loads classes and resources from a list of JarFiles.  This method is simmilar to URLClassLoader
  * except it properly closes JarFiles when the classloader is destroyed so that the file read lock will be released, and
@@ -55,63 +51,60 @@
  */
 public class JarFileClassLoader extends MultiParentClassLoader {
     private static final URL[] EMPTY_URLS = new URL[0];
-    private final Object lock = new Object();
-    private final LinkedHashMap classPath = new LinkedHashMap();
-    private boolean destroyed = false;
+
+    private final JarFileResourceFinder resourceFinder = new JarFileResourceFinder();
+    private final AccessControlContext acc;
 
     /**
      * Creates a JarFileClassLoader that is a child of the system class loader.
-     * @param name the name of this class loader
+     * @param id the name of this class loader
      * @param urls a list of URLs from which classes and resources should be loaded
      */
-    public JarFileClassLoader(String name, URL[] urls) {
-        super(name, EMPTY_URLS);
+    public JarFileClassLoader(Artifact id, URL[] urls) {
+        super(id, EMPTY_URLS);
+        this.acc = AccessController.getContext();
         addURLs(urls);
     }
 
     /**
      * Creates a JarFileClassLoader that is a child of the specified class loader.
-     * @param name the name of this class loader
+     * @param id the name of this class loader
      * @param urls a list of URLs from which classes and resources should be loaded
      * @param parent the parent of this class loader
      */
-    public JarFileClassLoader(String name, URL[] urls, ClassLoader parent) {
-        this(name, urls, new ClassLoader[] {parent});
+    public JarFileClassLoader(Artifact id, URL[] urls, ClassLoader parent) {
+        super(id, EMPTY_URLS, parent);
+        this.acc = AccessController.getContext();
+        addURLs(urls);
     }
 
-    /**
-     * Creates a named class loader as a child of the specified parent and using the specified URLStreamHandlerFactory
-     * for accessing the urls..
-     * @param name the name of this class loader
-     * @param urls the urls from which this class loader will classes and resources
-     * @param parent the parent of this class loader
-     * @param factory the URLStreamHandlerFactory used to access the urls
-     */
-    public JarFileClassLoader(String name, URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory) {
-        this(name, urls, new ClassLoader[] {parent}, factory);
+    public JarFileClassLoader(Artifact id, URL[] urls, ClassLoader parent, boolean inverseClassLoading, String[] hiddenClasses, String[] nonOverridableClasses) {
+        super(id, EMPTY_URLS, parent, inverseClassLoading, hiddenClasses, nonOverridableClasses);
+        this.acc = AccessController.getContext();
+        addURLs(urls);
     }
 
     /**
      * Creates a named class loader as a child of the specified parents.
-     * @param name the name of this class loader
+     * @param id the name of this class loader
      * @param urls the urls from which this class loader will classes and resources
      * @param parents the parents of this class loader
      */
-    public JarFileClassLoader(String name, URL[] urls, ClassLoader[] parents) {
-        super(name, EMPTY_URLS, parents);
+    public JarFileClassLoader(Artifact id, URL[] urls, ClassLoader[] parents) {
+        super(id, EMPTY_URLS, parents);
+        this.acc = AccessController.getContext();
         addURLs(urls);
     }
 
-    /**
-     * Creates a named class loader as a child of the specified parents and using the specified URLStreamHandlerFactory
-     * for accessing the urls..
-     * @param name the name of this class loader
-     * @param urls the urls from which this class loader will classes and resources
-     * @param parents the parents of this class loader
-     * @param factory the URLStreamHandlerFactory used to access the urls
-     */
-    public JarFileClassLoader(String name, URL[] urls, ClassLoader[] parents, URLStreamHandlerFactory factory) {
-        super(name, EMPTY_URLS, parents, factory);
+    public JarFileClassLoader(Artifact id, URL[] urls, ClassLoader[] parents, boolean inverseClassLoading, Collection hiddenClasses, Collection nonOverridableClasses) {
+        super(id, EMPTY_URLS, parents, inverseClassLoading, hiddenClasses, nonOverridableClasses);
+        this.acc = AccessController.getContext();
+        addURLs(urls);
+    }
+
+    public JarFileClassLoader(Artifact id, URL[] urls, ClassLoader[] parents, boolean inverseClassLoading, String[] hiddenClasses, String[] nonOverridableClasses) {
+        super(id, EMPTY_URLS, parents, inverseClassLoading, hiddenClasses, nonOverridableClasses);
+        this.acc = AccessController.getContext();
         addURLs(urls);
     }
 
@@ -119,230 +112,174 @@
      * {@inheritDoc}
      */
     public URL[] getURLs() {
-        return (URL[]) classPath.keySet().toArray(new URL[classPath.keySet().size()]);
+        return resourceFinder.getUrls();
     }
 
     /**
      * {@inheritDoc}
      */
-    protected void addURL(URL url) {
-        addURLs(Collections.singletonList(url));
+    public void addURL(final URL url) {
+        AccessController.doPrivileged(new PrivilegedAction() {
+            public Object run() {
+                resourceFinder.addUrl(url);
+                return null;
+            }
+        }, acc);
     }
 
     /**
      * Adds an array of urls to the end of this class loader.
      * @param urls the URLs to add
      */
-    protected void addURLs(URL[] urls) {
-        addURLs(Arrays.asList(urls));
+    protected void addURLs(final URL[] urls) {
+        AccessController.doPrivileged(new PrivilegedAction() {
+            public Object run() {
+                resourceFinder.addUrls(urls);
+                return null;
+            }
+        }, acc);
     }
 
     /**
-     * Adds a list of urls to the end of this class loader.
-     * @param urls the URLs to add
+     * {@inheritDoc}
      */
-    protected void addURLs(List urls) {
-        LinkedList locationStack = new LinkedList(urls);
-        try {
-            while (!locationStack.isEmpty()) {
-                URL url = (URL) locationStack.removeFirst();
-
-                if (!"file".equals(url.getProtocol())) {
-                    // download the jar
-                    throw new Error("Only local file jars are supported " + url);
-                }
-
-                String path = url.getPath();
-                if (classPath.containsKey(path)) {
-                    continue;
-                }
-
-                File file = new File(path);
-                if (!file.canRead()) {
-                    // can't read file...
-                    continue;
-                }
-
-                // open the jar file
-                JarFile jarFile;
-                try {
-                    jarFile = new JarFile(file);
-                } catch (IOException e) {
-                    // can't seem to open the file
-                    continue;
-                }
-                classPath.put(url, jarFile);
-
-                // push the manifest classpath on the stack (make sure to maintain the order)
-                Manifest manifest = null;
-                try {
-                    manifest = jarFile.getManifest();
-                } catch (IOException ignored) {
-                }
-
-                if (manifest != null) {
-                    Attributes mainAttributes = manifest.getMainAttributes();
-                    String manifestClassPath = mainAttributes.getValue(Attributes.Name.CLASS_PATH);
-                    if (manifestClassPath != null) {
-                        LinkedList classPathUrls = new LinkedList();
-                        for (StringTokenizer tokenizer = new StringTokenizer(manifestClassPath, " "); tokenizer.hasMoreTokens();) {
-                            String entry = tokenizer.nextToken();
-                            File parentDir = file.getParentFile();
-                            File entryFile = new File(parentDir, entry);
-                            // manifest entries are optional... if they aren't there it is ok
-                            if (entryFile.canRead()) {
-                                classPathUrls.addLast(entryFile.getAbsolutePath());
-                            }
-                        }
-                        locationStack.addAll(0, classPathUrls);
-                    }
-                }
-            }
-        } catch (Error e) {
-            destroy();
-            throw e;
-        }
+    public void destroy() {
+        resourceFinder.destroy();
+        super.destroy();
     }
 
     /**
      * {@inheritDoc}
      */
-    public void destroy() {
-        synchronized (lock) {
-            if (destroyed) {
-                return;
+    public URL findResource(final String resourceName) {
+        return (URL) AccessController.doPrivileged(new PrivilegedAction() {
+            public Object run() {
+                return resourceFinder.findResource(resourceName);
             }
-            destroyed = true;
-            for (Iterator iterator = classPath.values().iterator(); iterator.hasNext();) {
-                JarFile jarFile = (JarFile) iterator.next();
-                try {
-                    jarFile.close();
-                } catch (IOException ignored) {
-                }
-            }
-            classPath.clear();
-        }
-        super.destroy();
+        }, acc);
     }
 
     /**
      * {@inheritDoc}
      */
-    public URL findResource(String resourceName) {
-        URL jarUrl = null;
-        synchronized (lock) {
-            if (destroyed) {
-                return null;
+    public Enumeration findResources(final String resourceName) throws IOException {
+        // todo this is not right
+        // first get the resources from the parent classloaders
+        Enumeration parentResources = super.findResources(resourceName);
+
+        // get the classes from my urls
+        Enumeration myResources = (Enumeration) AccessController.doPrivileged(new PrivilegedAction() {
+            public Object run() {
+                return resourceFinder.findResources(resourceName);
             }
-            for (Iterator iterator = classPath.entrySet().iterator(); iterator.hasNext() && jarUrl == null;) {
-                Map.Entry entry = (Map.Entry) iterator.next();
-                JarFile jarFile = (JarFile) entry.getValue();
-                JarEntry jarEntry = jarFile.getJarEntry(resourceName);
-                if (jarEntry != null && !jarEntry.isDirectory()) {
-                    jarUrl = (URL) entry.getKey();
-                }
-            }
-        }
-
+        }, acc);
 
-        try {
-            String urlString = "jar:" + jarUrl + "!/" + resourceName;
-            return new URL(jarUrl, urlString);
-        } catch (MalformedURLException e) {
-            return null;
-        }
+        // join the two together
+        Enumeration resources = new UnionEnumeration(parentResources, myResources);
+        return resources;
     }
 
     /**
      * {@inheritDoc}
      */
-    public Enumeration findResources(String resourceName) throws IOException {
-        List resources = new ArrayList();
-        List superResources = Collections.list(super.findResources(resourceName));
-        resources.addAll(superResources);
-
-        synchronized (lock) {
-            if (destroyed) {
-                return Collections.enumeration(Collections.EMPTY_LIST);
-            }
-            for (Iterator iterator = classPath.entrySet().iterator(); iterator.hasNext();) {
-                Map.Entry entry = (Map.Entry) iterator.next();
-                JarFile jarFile = (JarFile) entry.getValue();
-                JarEntry jarEntry = jarFile.getJarEntry(resourceName);
-                if (jarEntry != null && !jarEntry.isDirectory()) {
-                    try {
-                        URL url = (URL) entry.getKey();
-                        String urlString = "jar:" + url + "!/" + resourceName;
-                        resources.add(new URL(url, urlString));
-                    } catch (MalformedURLException e) {
-                    }
-                }
+    protected String findLibrary(String libraryName) {
+        // if the libraryName is actually a directory it is invalid
+        int pathEnd = libraryName.lastIndexOf('/');
+        if (pathEnd == libraryName.length() - 1) {
+            throw new IllegalArgumentException("libraryName ends with a '/' character: " + libraryName);
+        }
+
+        // get the name if the library file
+        final String resourceName;
+        if (pathEnd < 0) {
+            resourceName = System.mapLibraryName(libraryName);
+        } else {
+            String path = libraryName.substring(0, pathEnd + 1);
+            String file = libraryName.substring(pathEnd + 1);
+            resourceName = path + System.mapLibraryName(file);
+        }
+
+        // get a resource handle to the library
+        ResourceHandle resourceHandle = (ResourceHandle) AccessController.doPrivileged(new PrivilegedAction() {
+            public Object run() {
+                return resourceFinder.getResource(resourceName);
             }
+        }, acc);
+
+        if (resourceHandle == null) {
+            return null;
         }
 
-        return Collections.enumeration(resources);
+        // the library must be accessable on the file system
+        URL url = resourceHandle.getURL();
+        if (!"file".equals(url.getProtocol())) {
+            return null;
+        }
+
+        String path = new File(URI.create(url.toString())).getPath();
+        return path;
     }
 
     /**
      * {@inheritDoc}
      */
-    protected Class findClass(String className) throws ClassNotFoundException {
-        SecurityManager securityManager = System.getSecurityManager();
-        if (securityManager != null) {
-            String packageName;
-            int packageEnd = className.lastIndexOf('.');
-            if (packageEnd >= 0) {
-                packageName = className.substring(0, packageEnd);
-                securityManager.checkPackageDefinition(packageName);
-            }
-        }
+    protected Class findClass(final String className) throws ClassNotFoundException {
+        try {
+            return (Class) AccessController.doPrivileged(new PrivilegedExceptionAction() {
+                public Object run() throws ClassNotFoundException {
+                    // first think check if we are allowed to define the package
+                    SecurityManager securityManager = System.getSecurityManager();
+                    if (securityManager != null) {
+                        String packageName;
+                        int packageEnd = className.lastIndexOf('.');
+                        if (packageEnd >= 0) {
+                            packageName = className.substring(0, packageEnd);
+                            securityManager.checkPackageDefinition(packageName);
+                        }
+                    }
 
-        Certificate[] certificates = null;
-        URL jarUrl = null;
-        Manifest manifest = null;
-        byte[] bytes;
-        synchronized (lock) {
-            if (destroyed) {
-                throw new ClassNotFoundException("Class loader has been destroyed: " + className);
-            }
 
-            try {
-                String entryName = className.replace('.', '/') + ".class";
-                InputStream inputStream = null;
-                for (Iterator iterator = classPath.entrySet().iterator(); iterator.hasNext() && inputStream == null;) {
-                    Map.Entry entry = (Map.Entry) iterator.next();
-                    jarUrl = (URL) entry.getKey();
-                    JarFile jarFile = (JarFile) entry.getValue();
-                    JarEntry jarEntry = jarFile.getJarEntry(entryName);
-                    if (jarEntry != null && !jarEntry.isDirectory()) {
-                        inputStream = jarFile.getInputStream(jarEntry);
-                        certificates = jarEntry.getCertificates();
-                        manifest = jarFile.getManifest();
+                    // convert the class name to a file name
+                    String resourceName = className.replace('.', '/') + ".class";
+
+                    // find the class file resource
+                    ResourceHandle resourceHandle = resourceFinder.getResource(resourceName);
+                    if (resourceHandle == null) {
+                        throw new ClassNotFoundException(className);
                     }
-                }
-                if (inputStream == null) {
-                    throw new ClassNotFoundException(className);
-                }
 
-                try {
-                    byte[] buffer = new byte[4096];
-                    ByteArrayOutputStream out = new ByteArrayOutputStream();
-                    for (int count = inputStream.read(buffer); count >= 0; count = inputStream.read(buffer)) {
-                        out.write(buffer, 0, count);
+                    byte[] bytes;
+                    Manifest manifest;
+                    try {
+                        // get the bytes from the class file
+                        bytes = resourceHandle.getBytes();
+
+                        // get the manifest for defining the packages
+                        manifest = resourceHandle.getManifest();
+                    } catch (IOException e) {
+                        throw new ClassNotFoundException(className, e);
                     }
-                    bytes = out.toByteArray();
-                } finally {
-                    inputStream.close();
+
+                    // get the certificates for the code source
+                    Certificate[] certificates = resourceHandle.getCertificates();
+
+                    // the code source url is used to define the package and as the security context for the class
+                    URL codeSourceUrl = resourceHandle.getCodeSourceURL();
+
+                    // define the package (required for security)
+                    definePackage(className, codeSourceUrl, manifest);
+
+                    // this is the security context of the class
+                    CodeSource codeSource = new CodeSource(codeSourceUrl, certificates);
+
+                    // load the class into the vm
+                    Class clazz = defineClass(className, bytes, 0, bytes.length, codeSource);
+                    return clazz;
                 }
-            } catch (IOException e) {
-                throw new ClassNotFoundException(className, e);
-            }
+            }, acc);
+        } catch (PrivilegedActionException e) {
+            throw (ClassNotFoundException) e.getException();
         }
-
-        definePackage(className, jarUrl, manifest);
-        CodeSource codeSource = new CodeSource(jarUrl, certificates);
-        Class clazz = defineClass(className, bytes, 0, bytes.length, codeSource);
-        return clazz;
     }
 
     private void definePackage(String className, URL jarUrl, Manifest manifest) {

Added: geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarFileResourceFinder.java
URL: http://svn.apache.org/viewcvs/geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarFileResourceFinder.java?rev=399522&view=auto
==============================================================================
--- geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarFileResourceFinder.java (added)
+++ geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarFileResourceFinder.java Wed May  3 19:53:50 2006
@@ -0,0 +1,310 @@
+/**
+ *
+ * Copyright 2005 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.geronimo.kernel.classloader;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+import org.apache.geronimo.kernel.classloader.util.ClassLoaderUtil;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class JarFileResourceFinder implements ResourceFinder {
+    private final Object lock = new Object();
+
+    private final LinkedHashSet urls = new LinkedHashSet();
+    private final LinkedHashMap classPath = new LinkedHashMap();
+    private final LinkedHashSet watchedFiles = new LinkedHashSet();
+
+    private boolean destroyed = false;
+
+    public JarFileResourceFinder() {
+    }
+
+    public JarFileResourceFinder(URL[] urls) {
+        addUrls(urls);
+    }
+
+    public void destroy() {
+        synchronized (lock) {
+            if (destroyed) {
+                return;
+            }
+            destroyed = true;
+            urls.clear();
+            for (Iterator iterator = classPath.values().iterator(); iterator.hasNext();) {
+                JarFile jarFile = (JarFile) iterator.next();
+                ClassLoaderUtil.close(jarFile);
+            }
+            classPath.clear();
+        }
+    }
+
+    public void addUrl(URL url) {
+        addUrls(Collections.singletonList(url));
+    }
+
+    public URL[] getUrls() {
+        synchronized (lock) {
+            return (URL[]) urls.toArray(new URL[urls.size()]);
+        }
+    }
+
+    /**
+     * Adds an array of urls to the end of this class loader.
+     * @param urls the URLs to add
+     */
+    protected void addUrls(URL[] urls) {
+        addUrls(Arrays.asList(urls));
+    }
+
+    /**
+     * Adds a list of urls to the end of this class loader.
+     * @param urls the URLs to add
+     */
+    protected void addUrls(List urls) {
+        synchronized (lock) {
+            boolean shouldRebuild = this.urls.addAll(urls);
+            if (shouldRebuild) {
+                rebuildClassPath();
+            }
+        }
+    }
+
+    private LinkedHashMap getClassPath() {
+        assert Thread.holdsLock(lock): "This method can only be called while holding the lock";
+
+        for (Iterator iterator = watchedFiles.iterator(); iterator.hasNext();) {
+            File file = (File) iterator.next();
+            if (file.canRead()) {
+                rebuildClassPath();
+                break;
+            }
+        }
+
+        return classPath;
+    }
+
+    private void rebuildClassPath() {
+        assert Thread.holdsLock(lock): "This method can only be called while holding the lock";
+
+        Map existingJarFiles = new LinkedHashMap(classPath);
+        classPath.clear();
+
+        LinkedList locationStack = new LinkedList(urls);
+        try {
+            while (!locationStack.isEmpty()) {
+                URL url = (URL) locationStack.removeFirst();
+
+                if (!"file".equals(url.getProtocol())) {
+                    // download the jar
+                    throw new Error("Only local file jars are supported " + url);
+                }
+
+                if (classPath.containsKey(url)) {
+                    continue;
+                }
+
+                File file = new File(url.getPath());
+                if (!file.canRead()) {
+                    // file most likely doesn't exist yet... watch to see if it appears later
+                    watchedFiles.add(file);
+                    continue;
+                }
+
+                // open the jar file
+                JarFile jarFile = (JarFile) existingJarFiles.remove(url);
+                if (jarFile == null) {
+                    try {
+                        jarFile = ClassLoaderUtil.createJarFile(file);
+                    } catch (IOException ignored) {
+                        // can't seem to open the file... this is most likely a bad jar file
+                        // so don't keep a watch out for it because that would require lots of checking
+                        // Dain: We may want to review this decision later
+                        continue;
+                    }
+                }
+
+                // add the jar to our class path
+                classPath.put(url, jarFile);
+
+                // push the manifest classpath on the stack (make sure to maintain the order)
+                Manifest manifest = null;
+                try {
+                    manifest = jarFile.getManifest();
+                } catch (IOException ignored) {
+                }
+
+                if (manifest != null) {
+                    Attributes mainAttributes = manifest.getMainAttributes();
+                    String manifestClassPath = mainAttributes.getValue(Attributes.Name.CLASS_PATH);
+                    if (manifestClassPath != null) {
+                        LinkedList classPathUrls = new LinkedList();
+                        for (StringTokenizer tokenizer = new StringTokenizer(manifestClassPath, " "); tokenizer.hasMoreTokens();) {
+                            String entry = tokenizer.nextToken();
+                            File parentDir = file.getParentFile();
+                            File entryFile = new File(parentDir, entry);
+
+                            try {
+                                classPathUrls.addLast(entryFile.toURL());
+                            } catch (MalformedURLException ignored) {
+                                // most likely a poorly named entry
+                            }
+                        }
+                        locationStack.addAll(0, classPathUrls);
+                    }
+                }
+            }
+        } catch (Error e) {
+            destroy();
+            throw e;
+        }
+
+        for (Iterator iterator = existingJarFiles.values().iterator(); iterator.hasNext();) {
+            JarFile jarFile = (JarFile) iterator.next();
+            ClassLoaderUtil.close(jarFile);
+        }
+    }
+
+    public ResourceHandle getResource(String resourceName) {
+        synchronized (lock) {
+            if (destroyed) {
+                return null;
+            }
+            for (Iterator iterator = getClassPath().entrySet().iterator(); iterator.hasNext();) {
+                Map.Entry entry = (Map.Entry) iterator.next();
+                JarFile jarFile = (JarFile) entry.getValue();
+                JarEntry jarEntry = jarFile.getJarEntry(resourceName);
+                if (jarEntry != null && !jarEntry.isDirectory()) {
+                    URL codeSource = (URL) entry.getKey();
+                    try {
+                        URL url = JarFileUrlStreamHandler.createUrl(jarFile, jarEntry);
+                        return new JarResourceHandle(jarFile, jarEntry, url, codeSource);
+                    } catch (MalformedURLException e) {
+                        return null;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    public URL findResource(String resourceName) {
+        synchronized (lock) {
+            if (destroyed) {
+                return null;
+            }
+            for (Iterator iterator = getClassPath().entrySet().iterator(); iterator.hasNext();) {
+                Map.Entry entry = (Map.Entry) iterator.next();
+                JarFile jarFile = (JarFile) entry.getValue();
+                JarEntry jarEntry = jarFile.getJarEntry(resourceName);
+                if (jarEntry != null) {
+                    try {
+                        return JarFileUrlStreamHandler.createUrl(jarFile, jarEntry);
+                    } catch (MalformedURLException e) {
+                        return null;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    public Enumeration findResources(String resourceName) {
+        synchronized (lock) {
+            return new ResourceEnumeration(new ArrayList(getClassPath().values()), resourceName);
+        }
+    }
+
+    private static class ResourceEnumeration implements Enumeration {
+        private Iterator iterator;
+        private final String resourceName;
+        private Object next;
+
+        public ResourceEnumeration(Collection jarFiles, String resourceName) {
+            this.iterator = jarFiles.iterator();
+            this.resourceName = resourceName;
+        }
+
+        public boolean hasMoreElements() {
+            fetchNext();
+            return (next != null);
+        }
+
+        public Object nextElement() {
+            fetchNext();
+
+            // save next into a local variable and clear the next field
+            Object next = this.next;
+            this.next = null;
+
+            // if we didn't have a next throw an exception
+            if (next == null) {
+                throw new NoSuchElementException();
+            }
+            return next;
+        }
+
+        private void fetchNext() {
+            if (iterator == null) {
+                return;
+            }
+
+            try {
+                while (iterator.hasNext()) {
+                    JarFile jarFile = (JarFile) iterator.next();
+                    JarEntry jarEntry = jarFile.getJarEntry(resourceName);
+                    if (jarEntry != null) {
+                        try {
+                            next = JarFileUrlStreamHandler.createUrl(jarFile, jarEntry);
+                            return;
+                        } catch (MalformedURLException e) {
+                        }
+                    }
+                }
+                // no more elements
+                // clear the iterator so it can be GCed
+                iterator = null;
+            } catch (IllegalStateException e) {
+                // Jar file was closed... this means the resource finder was destroyed
+                // clear the iterator so it can be GCed
+                iterator = null;
+                throw e;
+            }
+        }
+    }
+}

Added: geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarFileUrlConnection.java
URL: http://svn.apache.org/viewcvs/geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarFileUrlConnection.java?rev=399522&view=auto
==============================================================================
--- geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarFileUrlConnection.java (added)
+++ geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarFileUrlConnection.java Wed May  3 19:53:50 2006
@@ -0,0 +1,119 @@
+/**
+ *
+ * Copyright 2005 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.geronimo.kernel.classloader;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.JarURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.Permission;
+import java.security.cert.Certificate;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+import org.apache.geronimo.kernel.classloader.util.ClassLoaderUtil;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class JarFileUrlConnection extends JarURLConnection {
+    private final URL url;
+    private final JarFile jarFile;
+    private final JarEntry jarEntry;
+    private final URL jarFileUrl;
+
+    public JarFileUrlConnection(URL url, JarFile jarFile, JarEntry jarEntry) throws MalformedURLException {
+        super(ClassLoaderUtil.DUMMY_JAR_URL);
+
+        if (url == null) throw new NullPointerException("url is null");
+        if (jarFile == null) throw new NullPointerException("jarFile is null");
+        if (jarEntry == null) throw new NullPointerException("jarEntry is null");
+
+        this.url = url;
+        this.jarFile = jarFile;
+        this.jarEntry = jarEntry;
+        jarFileUrl = new File(jarFile.getName()).toURL();
+    }
+
+    public JarFile getJarFile() throws IOException {
+        return jarFile;
+    }
+
+    public synchronized void connect() {
+    }
+
+    public URL getJarFileURL() {
+        return jarFileUrl;
+    }
+
+    public String getEntryName() {
+        return getJarEntry().getName();
+    }
+
+    public Manifest getManifest() throws IOException {
+        return jarFile.getManifest();
+    }
+
+    public JarEntry getJarEntry() {
+        return jarEntry;
+    }
+
+    public Attributes getAttributes() throws IOException {
+        return getJarEntry().getAttributes();
+    }
+
+    public Attributes getMainAttributes() throws IOException {
+        return getManifest().getMainAttributes();
+    }
+
+    public Certificate[] getCertificates() throws IOException {
+        return getJarEntry().getCertificates();
+    }
+
+    public URL getURL() {
+        return url;
+    }
+
+    public int getContentLength() {
+        long size = getJarEntry().getSize();
+        if (size > Integer.MAX_VALUE) {
+            return -1;
+        }
+        return (int) size;
+    }
+
+    public long getLastModified() {
+        return getJarEntry().getTime();
+    }
+
+    public synchronized InputStream getInputStream() throws IOException {
+        return jarFile.getInputStream(jarEntry);
+    }
+
+    public Permission getPermission() throws IOException {
+        URL jarFileUrl = new File(jarFile.getName()).toURL();
+        return jarFileUrl.openConnection().getPermission();
+    }
+
+    public String toString() {
+        return JarFileUrlConnection.class.getName() + ":" + url;
+    }
+}

Added: geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarFileUrlStreamHandler.java
URL: http://svn.apache.org/viewcvs/geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarFileUrlStreamHandler.java?rev=399522&view=auto
==============================================================================
--- geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarFileUrlStreamHandler.java (added)
+++ geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarFileUrlStreamHandler.java Wed May  3 19:53:50 2006
@@ -0,0 +1,62 @@
+/**
+ *
+ * Copyright 2005 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.geronimo.kernel.classloader;
+
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+import java.net.MalformedURLException;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class JarFileUrlStreamHandler extends URLStreamHandler {
+    public static URL createUrl(JarFile jarFile, JarEntry jarEntry) throws MalformedURLException {
+        JarFileUrlStreamHandler handler = new JarFileUrlStreamHandler(jarFile, jarEntry);
+        URL url = new URL("jar", "", -1, jarFile.getName() + "!/" + jarEntry.getName(), handler);
+        handler.setExpectedUrl(url);
+        return url;
+    }
+
+    private URL expectedUrl;
+    private final JarFile jarFile;
+    private final JarEntry jarEntry;
+
+    public JarFileUrlStreamHandler(JarFile jarFile, JarEntry jarEntry) {
+        if (jarFile == null) throw new NullPointerException("jarFile is null");
+        if (jarEntry == null) throw new NullPointerException("jarEntry is null");
+
+        this.jarFile = jarFile;
+        this.jarEntry = jarEntry;
+    }
+
+    public void setExpectedUrl(URL expectedUrl) {
+        if (expectedUrl == null) throw new NullPointerException("expectedUrl is null");
+        this.expectedUrl = expectedUrl;
+    }
+
+    public URLConnection openConnection(URL url) throws MalformedURLException {
+        if (expectedUrl == null) throw new IllegalStateException("expectedUrl was not set");
+
+        // alternatively we could return a connection using the normal jar url connection
+        if (!expectedUrl.equals(url)) throw new IllegalArgumentException("Expected url [" + expectedUrl + "], but was [" + url + "]");
+
+        return new JarFileUrlConnection(url, jarFile, jarEntry);
+    }
+}

Added: geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarResourceHandle.java
URL: http://svn.apache.org/viewcvs/geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarResourceHandle.java?rev=399522&view=auto
==============================================================================
--- geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarResourceHandle.java (added)
+++ geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarResourceHandle.java Wed May  3 19:53:50 2006
@@ -0,0 +1,75 @@
+/**
+ *
+ * Copyright 2005 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.geronimo.kernel.classloader;
+
+import java.util.jar.JarFile;
+import java.util.jar.JarEntry;
+import java.util.jar.Manifest;
+import java.util.jar.Attributes;
+import java.net.URL;
+import java.io.InputStream;
+import java.io.IOException;
+import java.security.cert.Certificate;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class JarResourceHandle extends AbstractResourceHandle {
+    private final JarFile jarFile;
+    private final JarEntry jarEntry;
+    private final URL url;
+    private final URL codeSource;
+
+    public JarResourceHandle(JarFile jarFile, JarEntry jarEntry, URL url, URL codeSource) {
+        this.jarFile = jarFile;
+        this.jarEntry = jarEntry;
+        this.url = url;
+        this.codeSource = codeSource;
+    }
+
+    public String getName() {
+        return jarEntry.getName();
+    }
+
+    public URL getURL() {
+        return url;
+    }
+
+    public URL getCodeSourceURL() {
+        return codeSource;
+    }
+
+    public InputStream getInputStream() throws IOException {
+        return jarFile.getInputStream(jarEntry);
+    }
+
+    public int getContentLength() {
+        return (int) jarEntry.getSize();
+    }
+
+    public Manifest getManifest() throws IOException {
+        return jarFile.getManifest();
+    }
+
+    public Attributes getAttributes() throws IOException {
+        return jarEntry.getAttributes();
+    }
+
+    public Certificate[] getCertificates() {
+        return jarEntry.getCertificates();
+    }
+}

Modified: geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/ResourceFinder.java
URL: http://svn.apache.org/viewcvs/geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/ResourceFinder.java?rev=399522&r1=393370&r2=399522&view=diff
==============================================================================
--- geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/ResourceFinder.java (original)
+++ geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/ResourceFinder.java Wed May  3 19:53:50 2006
@@ -22,7 +22,7 @@
 /**
  * Abstraction of resource searching policy. Given resource name, the resource
  * finder performs implementation-specific lookup, and, if it is able to locate
- * the resource, returns the {@link ResourceHandle handle(s)} or URL(s) of it.
+ * the resource, returns the {@link AbstractResourceHandle handle(s)} or URL(s) of it.
  *
  * @version $Rev$ $Date$
  */
@@ -45,19 +45,11 @@
 
     /**
      * Get the resource by name and, if found, open connection to it and return
-     * the {@link ResourceHandle handle} of it.
+     * the {@link AbstractResourceHandle handle} of it.
      *
      * @param name the resource name
      * @return resource handle or null if resource was not found
      */
     public ResourceHandle getResource(String name);
 
-    /**
-     * Get all resources with given name and return enumeration of their
-     * {@link ResourceHandle resource handles}.
-     *
-     * @param name the resource name
-     * @return enumeration of resource handles (possibly empty).
-     */
-    public Enumeration getResources(String name);
 }

Added: geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/ResourceHandle.java
URL: http://svn.apache.org/viewcvs/geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/ResourceHandle.java?rev=399522&view=auto
==============================================================================
--- geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/ResourceHandle.java (added)
+++ geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/ResourceHandle.java Wed May  3 19:53:50 2006
@@ -0,0 +1,91 @@
+/**
+ *
+ * Copyright 2005 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.geronimo.kernel.classloader;
+
+import java.net.URL;
+import java.io.InputStream;
+import java.io.IOException;
+import java.util.jar.Manifest;
+import java.util.jar.Attributes;
+import java.security.cert.Certificate;
+
+/**
+ * This is a handle (a connection) to some resource, which may
+ * be a class, native library, text file, image, etc. Handles are returned
+ * by a ResourceFinder. A resource handle allows easy access to the resource data
+ * (using methods {@link #getInputStream} or {@link #getBytes}) as well as
+ * access resource metadata, such as attributes, certificates, etc.
+ * <p/>
+ * As soon as the handle is no longer in use, it should be explicitly
+ * {@link #close}d, similarly to I/O streams.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ResourceHandle {
+    /**
+     * Return the name of the resource. The name is a "/"-separated path
+     * name that identifies the resource.
+     */
+    String getName();
+
+    /**
+     * Returns the URL of the resource.
+     */
+    URL getURL();
+
+    /**
+     * Returns the CodeSource URL for the class or resource.
+     */
+    URL getCodeSourceURL();
+
+    /**
+     * Returns and InputStream for reading this resource data.
+     */
+    InputStream getInputStream() throws IOException;
+
+    /**
+     * Returns the length of this resource data, or -1 if unknown.
+     */
+    int getContentLength();
+
+    /**
+     * Returns this resource data as an array of bytes.
+     */
+    byte[] getBytes() throws IOException;
+
+    /**
+     * Returns the Manifest of the JAR file from which this resource
+     * was loaded, or null if none.
+     */
+    Manifest getManifest() throws IOException;
+
+    /**
+     * Return the Certificates of the resource, or null if none.
+     */
+    Certificate[] getCertificates();
+
+    /**
+     * Return the Attributes of the resource, or null if none.
+     */
+    Attributes getAttributes() throws IOException;
+
+    /**
+     * Closes a connection to the resource indentified by this handle. Releases
+     * any I/O objects associated with the handle.
+     */
+    void close();
+}

Added: geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/ClassLoaderUtil.java
URL: http://svn.apache.org/viewcvs/geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/ClassLoaderUtil.java?rev=399522&view=auto
==============================================================================
--- geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/ClassLoaderUtil.java (added)
+++ geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/ClassLoaderUtil.java Wed May  3 19:53:50 2006
@@ -0,0 +1,442 @@
+/**
+ *
+ * Copyright 2004 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.geronimo.kernel.classloader.util;
+
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLStreamHandler;
+import java.net.URLConnection;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.LinkedList;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public final class ClassLoaderUtil {
+    private ClassLoaderUtil() {
+    }
+
+    public static final File DUMMY_JAR_FILE;
+    public static final URL DUMMY_JAR_URL;
+    static {
+        try {
+            DUMMY_JAR_FILE = ClassLoaderUtil.createTempFile();
+            new JarOutputStream(new FileOutputStream(ClassLoaderUtil.DUMMY_JAR_FILE), new Manifest()).close();
+
+            DUMMY_JAR_URL = new URL("jar", "", -1, "file:dummy!/", new URLStreamHandler() {
+                protected URLConnection openConnection(URL u) {
+                    throw new UnsupportedOperationException();
+                }
+            });
+        } catch (Exception e) {
+            throw new ExceptionInInitializerError(e);
+        }
+    }
+
+    // be careful to clean up the temp directory
+    public static File createTempDir() throws IOException {
+        File tempDir = File.createTempFile("geronimo-deploymentUtil", ".tmpdir");
+        tempDir.delete();
+        tempDir.mkdirs();
+        return tempDir;
+    }
+
+    // be careful to clean up the temp file... we tell the vm to delete this on exit
+    // but VMs can't be trusted to acutally delete the file
+    public static File createTempFile() throws IOException {
+        File tempFile = File.createTempFile("geronimo-deploymentUtil", ".tmpdir");
+        tempFile.deleteOnExit();
+        return tempFile;
+    }
+
+    public static void copyFile(File source, File destination) throws IOException {
+        File destinationDir = destination.getParentFile();
+        if (!destinationDir.exists() && !destinationDir.mkdirs()) {
+            throw new java.io.IOException("Cannot create directory : " + destinationDir);
+        }
+        
+        InputStream in = null;
+        OutputStream out = null;
+        try {
+            in = new FileInputStream(source);
+            out = new FileOutputStream(destination);
+            writeAll(in, out);
+        } finally {
+            close(in);
+            close(out);
+        }
+    }
+
+    private static void writeAll(InputStream in, OutputStream out) throws IOException {
+        byte[] buffer = new byte[4096];
+        int count;
+        while ((count = in.read(buffer)) > 0) {
+            out.write(buffer, 0, count);
+        }
+        out.flush();
+    }
+    public static File toTempFile(JarFile jarFile, String path) throws IOException {
+        return toTempFile(createJarURL(jarFile, path));
+    }
+
+    public static File toTempFile(URL url) throws IOException {
+        InputStream in = null;
+        OutputStream out = null;
+        try {
+            in = url.openStream();
+
+            File tempFile = createTempFile();
+            out = new FileOutputStream(tempFile);
+
+            writeAll(in, out);
+            return tempFile;
+        } finally {
+            close(out);
+            close(in);
+        }
+    }
+
+    public static String readAll(URL url) throws IOException {
+        Reader reader = null;
+        try {
+            reader = new InputStreamReader(url.openStream());
+
+            char[] buffer = new char[4096];
+            StringBuffer out = new StringBuffer();
+            for(int count = reader.read(buffer); count >= 0; count = reader.read(buffer)) {
+                out.append(buffer, 0, count);
+            }
+            return out.toString();
+        } finally {
+            close(reader);
+        }
+    }
+
+    public static byte[] getBytes(InputStream inputStream) throws IOException {
+        try {
+            byte[] buffer = new byte[4096];
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            for (int count = inputStream.read(buffer); count >= 0; count = inputStream.read(buffer)) {
+                out.write(buffer, 0, count);
+            }
+            byte[] bytes = out.toByteArray();
+            return bytes;
+        } finally {
+            close(inputStream);
+        }
+    }
+
+    public static File toFile(JarFile jarFile) throws IOException {
+        if (jarFile instanceof UnpackedJarFile) {
+            return ((UnpackedJarFile) jarFile).getBaseDir();
+        } else {
+        	throw new IOException("jarFile is not a directory");
+        }
+    }
+
+    // be careful with this method as it can leave a temp lying around
+    public static File toFile(JarFile jarFile, String path) throws IOException {
+        if (jarFile instanceof UnpackedJarFile) {
+            File baseDir = ((UnpackedJarFile) jarFile).getBaseDir();
+            File file = new File(baseDir, path);
+            if (!file.isFile()) {
+                throw new IOException("No such file: " + file.getAbsolutePath());
+            }
+            return file;
+        } else {
+            String urlString = "jar:" + new File(jarFile.getName()).toURL() + "!/" + path;
+            return toTempFile(new URL(urlString));
+        }
+    }
+
+    public static URL createJarURL(JarFile jarFile, String path) throws MalformedURLException {
+        if (jarFile instanceof NestedJarFile) {
+            NestedJarFile nestedJar = (NestedJarFile) jarFile;
+            if (nestedJar.isUnpacked()) {
+                JarFile baseJar = nestedJar.getBaseJar();
+                String basePath = nestedJar.getBasePath();
+                if (baseJar instanceof UnpackedJarFile) {
+                    File baseDir = ((UnpackedJarFile) baseJar).getBaseDir();
+                    baseDir = new File(baseDir, basePath);
+                    return new File(baseDir, path).toURL();
+                }
+            }
+        }
+        
+        if (jarFile instanceof UnpackedJarFile) {
+            File baseDir = ((UnpackedJarFile) jarFile).getBaseDir();
+            return new File(baseDir, path).toURL();
+        } else {
+            String urlString = "jar:" + new File(jarFile.getName()).toURL() + "!/" + path;
+            return new URL(urlString);
+        }
+    }
+
+    public static JarFile createJarFile(File jarFile) throws IOException {
+        if (jarFile.isDirectory()) {
+            return new UnpackedJarFile(jarFile);
+        } else {
+            return new JarFile(jarFile);
+        }
+    }
+
+    public static void copyToPackedJar(JarFile inputJar, File outputFile) throws IOException {
+        if (inputJar.getClass() == JarFile.class) {
+            // this is a plain old jar... nothign special
+            copyFile(new File(inputJar.getName()), outputFile);
+        } else if (inputJar instanceof NestedJarFile && ((NestedJarFile)inputJar).isPacked()) {
+            NestedJarFile nestedJarFile = (NestedJarFile)inputJar;
+            JarFile baseJar = nestedJarFile.getBaseJar();
+            String basePath = nestedJarFile.getBasePath();
+            if (baseJar instanceof UnpackedJarFile) {
+                // our target jar is just a file in upacked jar (a plain old directory)... now
+                // we just need to find where it is and copy it to the outptu
+                copyFile(((UnpackedJarFile)baseJar).getFile(basePath), outputFile);
+            } else {
+                // out target is just a plain old jar file directly accessabel from the file system
+                copyFile(new File(baseJar.getName()), outputFile);
+            }
+        } else {
+            // copy out the module contents to a standalone jar file (entry by entry)
+            JarOutputStream out = null;
+            try {
+                out = new JarOutputStream(new FileOutputStream(outputFile));
+                byte[] buffer = new byte[4096];
+                Enumeration entries = inputJar.entries();
+                while (entries.hasMoreElements()) {
+                    ZipEntry entry = (ZipEntry) entries.nextElement();
+                    InputStream in = inputJar.getInputStream(entry);
+                    try {
+                        out.putNextEntry(new ZipEntry(entry.getName()));
+                        try {
+                            int count;
+                            while ((count = in.read(buffer)) > 0) {
+                                out.write(buffer, 0, count);
+                            }
+                        } finally {
+                            out.closeEntry();
+                        }
+                    } finally {
+                        close(in);
+                    }
+                }
+            } finally {
+                close(out);
+            }
+        }
+    }
+
+    public static void jarDirectory(File sourceDirecotry, File destinationFile) throws IOException {
+        JarFile inputJar = new UnpackedJarFile(sourceDirecotry);
+        try {
+            copyToPackedJar(inputJar, destinationFile);
+        } finally {
+            close(inputJar);
+        }
+    }
+
+    public static void unzipToDirectory(ZipFile zipFile, File destDir) throws IOException {
+        Enumeration entries = zipFile.entries();
+        try {
+            while (entries.hasMoreElements()) {
+                ZipEntry entry = (ZipEntry) entries.nextElement();
+                if (entry.isDirectory()) {
+                    File dir = new File(destDir, entry.getName());
+                    boolean success = dir.mkdirs();
+                    if (!success) {
+                        throw new IOException("Cannot create directory " + dir.getAbsolutePath());
+                    }
+                } else {
+                    File file = new File(destDir, entry.getName());
+                    OutputStream out = null;
+                    InputStream in = null;
+                    try {
+                        out = new BufferedOutputStream(new FileOutputStream(file));
+                        in = zipFile.getInputStream(entry);
+                        writeAll(in, out);
+                    } finally {
+                        if (null != out) {
+                            out.close();
+                        }
+                        if (null != in) {
+                            in.close();
+                        }
+                    }
+                }
+            }
+        } finally {
+            zipFile.close();
+        }
+    }
+    
+    public static boolean recursiveDelete(File root) {
+        if (root == null) {
+            return true;
+        }
+
+        if (root.isDirectory()) {
+            File[] files = root.listFiles();
+            if (files != null) {
+                for (int i = 0; i < files.length; i++) {
+                    File file = files[i];
+                    if (file.isDirectory()) {
+                        recursiveDelete(file);
+                    } else {
+                        file.delete();
+                    }
+                }
+            }
+        }
+        return root.delete();
+    }
+
+    public static Collection listRecursiveFiles(File file) {
+        LinkedList list = new LinkedList();
+        listRecursiveFiles(file, list);
+        return Collections.unmodifiableCollection(list);
+    }
+
+    public static void listRecursiveFiles(File file, Collection collection) {
+        File[] files = file.listFiles();
+        if ( null == files ) {
+            return;
+        }
+        for (int i = 0; i < files.length; i++) {
+            collection.add(files[i]);
+            if (files[i].isDirectory()) {
+                listRecursiveFiles(files[i], collection);
+            }
+        }
+    }
+
+    public static void flush(OutputStream thing) {
+        if (thing != null) {
+            try {
+                thing.flush();
+            } catch(Exception ignored) {
+            }
+        }
+    }
+
+    public static void flush(Writer thing) {
+        if (thing != null) {
+            try {
+                thing.flush();
+            } catch(Exception ignored) {
+            }
+        }
+    }
+
+    public static void close(JarFile thing) {
+        if (thing != null) {
+            try {
+                thing.close();
+            } catch(Exception ignored) {
+            }
+        }
+    }
+
+    public static void close(InputStream thing) {
+        if (thing != null) {
+            try {
+                thing.close();
+            } catch(Exception ignored) {
+            }
+        }
+    }
+
+    public static void close(OutputStream thing) {
+        if (thing != null) {
+            try {
+                thing.close();
+            } catch(Exception ignored) {
+            }
+        }
+    }
+
+    public static void close(Reader thing) {
+        if (thing != null) {
+            try {
+                thing.close();
+            } catch(Exception ignored) {
+            }
+        }
+    }
+
+    public static void close(Writer thing) {
+        if (thing != null) {
+            try {
+                thing.close();
+            } catch(Exception ignored) {
+            }
+        }
+    }
+
+    public static final class EmptyInputStream extends InputStream {
+        public int read() {
+            return -1;
+        }
+
+        public int read(byte b[])  {
+            return -1;
+        }
+
+        public int read(byte b[], int off, int len) {
+            return -1;
+        }
+
+        public long skip(long n) {
+            return 0;
+        }
+
+        public int available() {
+            return 0;
+        }
+
+        public void close() {
+        }
+
+        public synchronized void mark(int readlimit) {
+        }
+
+        public synchronized void reset() {
+        }
+
+        public boolean markSupported() {
+            return false;
+        }
+    }
+
+}

Propchange: geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/ClassLoaderUtil.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/ClassLoaderUtil.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/ClassLoaderUtil.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/NestedJarEntry.java
URL: http://svn.apache.org/viewcvs/geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/NestedJarEntry.java?rev=399522&r1=399117&r2=399522&view=diff
==============================================================================
--- geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/NestedJarEntry.java (original)
+++ geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/NestedJarEntry.java Wed May  3 19:53:50 2006
@@ -14,7 +14,7 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-package org.apache.geronimo.deployment.util;
+package org.apache.geronimo.kernel.classloader.util;
 
 import java.io.IOException;
 import java.security.cert.Certificate;

Modified: geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/NestedJarFile.java
URL: http://svn.apache.org/viewcvs/geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/NestedJarFile.java?rev=399522&r1=399117&r2=399522&view=diff
==============================================================================
--- geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/NestedJarFile.java (original)
+++ geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/NestedJarFile.java Wed May  3 19:53:50 2006
@@ -14,7 +14,7 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-package org.apache.geronimo.deployment.util;
+package org.apache.geronimo.kernel.classloader.util;
 
 import java.io.File;
 import java.io.IOException;
@@ -41,7 +41,7 @@
     private File tempFile;
 
     public NestedJarFile(JarFile jarFile, String path) throws IOException {
-        super(DeploymentUtil.DUMMY_JAR_FILE);
+        super(ClassLoaderUtil.DUMMY_JAR_FILE);
 
         // verify that the jar actually contains that path
         JarEntry targetEntry = jarFile.getJarEntry(path + "/");
@@ -67,7 +67,7 @@
                 baseJar = new JarFile(targetFile);
                 basePath = "";
             } else {
-                tempFile = DeploymentUtil.toFile(jarFile, targetEntry.getName());
+                tempFile = ClassLoaderUtil.toFile(jarFile, targetEntry.getName());
                 baseJar = new JarFile(tempFile);
                 basePath = "";
             }
@@ -190,7 +190,7 @@
         if (baseEntry == null) {
             throw new IOException("Entry not found: name=" + baseEntry.getName());
         } else if (baseEntry.isDirectory()) {
-            return new DeploymentUtil.EmptyInputStream();
+            return new ClassLoaderUtil.EmptyInputStream();
         }
         return baseJar.getInputStream(baseEntry);
     }

Added: geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/UnionEnumeration.java
URL: http://svn.apache.org/viewcvs/geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/UnionEnumeration.java?rev=399522&view=auto
==============================================================================
--- geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/UnionEnumeration.java (added)
+++ geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/UnionEnumeration.java Wed May  3 19:53:50 2006
@@ -0,0 +1,63 @@
+/**
+ *
+ * Copyright 2005 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.geronimo.kernel.classloader.util;
+
+import java.util.Enumeration;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public final class UnionEnumeration implements Enumeration {
+    private final LinkedList enumerations = new LinkedList();
+
+    public UnionEnumeration(List enumerations) {
+        this.enumerations.addAll(enumerations);
+    }
+
+    public UnionEnumeration(Enumeration first, Enumeration second) {
+        if (first == null) throw new NullPointerException("first is null");
+        if (second == null) throw new NullPointerException("second is null");
+
+        enumerations.add(first);
+        enumerations.add(second);
+    }
+
+    public boolean hasMoreElements() {
+        while (!enumerations.isEmpty()) {
+            Enumeration enumeration = (Enumeration) enumerations.getFirst();
+            if (enumeration.hasMoreElements()) {
+                return true;
+            }
+            enumerations.removeFirst();
+        }
+        return false;
+    }
+
+    public Object nextElement() {
+        while (!enumerations.isEmpty()) {
+            Enumeration enumeration = (Enumeration) enumerations.getFirst();
+            if (enumeration.hasMoreElements()) {
+                return enumeration.nextElement();
+            }
+            enumerations.removeFirst();
+        }
+        throw new NoSuchElementException();
+    }
+}

Modified: geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/UnpackedJarEntry.java
URL: http://svn.apache.org/viewcvs/geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/UnpackedJarEntry.java?rev=399522&r1=399117&r2=399522&view=diff
==============================================================================
--- geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/UnpackedJarEntry.java (original)
+++ geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/UnpackedJarEntry.java Wed May  3 19:53:50 2006
@@ -14,7 +14,7 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-package org.apache.geronimo.deployment.util;
+package org.apache.geronimo.kernel.classloader.util;
 
 import java.util.jar.JarEntry;
 import java.util.jar.Attributes;
@@ -106,7 +106,7 @@
     }
 
     public long getCrc() {
-        return super.getCrc();    //To change body of overridden methods use File | Settings | File Templates.
+        return super.getCrc();
     }
 
     /**

Modified: geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/UnpackedJarFile.java
URL: http://svn.apache.org/viewcvs/geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/UnpackedJarFile.java?rev=399522&r1=399117&r2=399522&view=diff
==============================================================================
--- geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/UnpackedJarFile.java (original)
+++ geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/util/UnpackedJarFile.java Wed May  3 19:53:50 2006
@@ -14,7 +14,7 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-package org.apache.geronimo.deployment.util;
+package org.apache.geronimo.kernel.classloader.util;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -40,7 +40,7 @@
     private Manifest manifest;
 
     public UnpackedJarFile(File baseDir) throws IOException {
-        super(DeploymentUtil.DUMMY_JAR_FILE);
+        super(ClassLoaderUtil.DUMMY_JAR_FILE);
         this.baseDir = baseDir;
         if (!baseDir.isDirectory()) {
             throw new IOException("File must be a directory: file=" + baseDir.getAbsolutePath());
@@ -92,7 +92,7 @@
     }
 
     public Enumeration entries() {
-        Collection files = DeploymentUtil.listRecursiveFiles(baseDir);
+        Collection files = ClassLoaderUtil.listRecursiveFiles(baseDir);
 
         Manifest manifest = getManifestSafe();
         LinkedList entries = new LinkedList();
@@ -117,7 +117,7 @@
         if (file == null) {
             throw new IOException("Entry not found: name=" + file.getAbsolutePath());
         } else if (file.isDirectory()) {
-            return new DeploymentUtil.EmptyInputStream();
+            return new ClassLoaderUtil.EmptyInputStream();
         }
         return new FileInputStream(file);
     }

Modified: geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/Configuration.java
URL: http://svn.apache.org/viewcvs/geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/Configuration.java?rev=399522&r1=399521&r2=399522&view=diff
==============================================================================
--- geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/Configuration.java (original)
+++ geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/Configuration.java Wed May  3 19:53:50 2006
@@ -47,6 +47,7 @@
 import org.apache.geronimo.kernel.GBeanAlreadyExistsException;
 import org.apache.geronimo.kernel.GBeanNotFoundException;
 import org.apache.geronimo.kernel.Naming;
+import org.apache.geronimo.kernel.classloader.JarFileClassLoader;
 import org.apache.geronimo.kernel.repository.Artifact;
 import org.apache.geronimo.kernel.repository.Dependency;
 import org.apache.geronimo.kernel.repository.Environment;
@@ -352,12 +353,21 @@
 
         log.debug("ClassPath for " + id + " resolved to " + Arrays.asList(urls));
 
-        return new MultiParentClassLoader(environment.getConfigId(),
-                urls,
-                parentClassLoaders,
-                environment.isInverseClassLoading(),
-                hiddenClasses,
-                nonOverridableClasses);
+        if (Boolean.getBoolean("Xorg.apache.geronimo.NewClassLoader")) {
+            return new JarFileClassLoader(environment.getConfigId(),
+                    urls,
+                    parentClassLoaders,
+                    environment.isInverseClassLoading(),
+                    hiddenClasses,
+                    nonOverridableClasses);
+        } else {
+            return new MultiParentClassLoader(environment.getConfigId(),
+                    urls,
+                    parentClassLoaders,
+                    environment.isInverseClassLoading(),
+                    hiddenClasses,
+                    nonOverridableClasses);
+        }
     }
 
     private void addDepthFirstServiceParents(Configuration configuration, List ancestors) {

Modified: geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/MultiParentClassLoader.java
URL: http://svn.apache.org/viewcvs/geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/MultiParentClassLoader.java?rev=399522&r1=399521&r2=399522&view=diff
==============================================================================
--- geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/MultiParentClassLoader.java (original)
+++ geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/MultiParentClassLoader.java Wed May  3 19:53:50 2006
@@ -34,7 +34,6 @@
 
 import org.apache.commons.logging.LogFactory;
 import org.apache.geronimo.kernel.repository.Artifact;
-import org.apache.geronimo.kernel.repository.Environment;
 
 /**
  * A MultiParentClassLoader is a simple extension of the URLClassLoader that simply changes the single parent class
@@ -86,24 +85,6 @@
 
     public MultiParentClassLoader(Artifact id, URL[] urls, ClassLoader parent, boolean inverseClassLoading, String[] hiddenClasses, String[] nonOverridableClasses) {
         this(id, urls, new ClassLoader[]{parent}, inverseClassLoading, hiddenClasses, nonOverridableClasses);
-    }
-
-    public MultiParentClassLoader(Environment environment, URL[] urls, ClassLoader parent) {
-        this(environment.getConfigId(),
-                urls,
-                new ClassLoader[]{parent},
-                environment.isInverseClassLoading(),
-                environment.getHiddenClasses(),
-                environment.getNonOverrideableClasses());
-    }
-
-    public MultiParentClassLoader(Environment environment, URL[] urls, ClassLoader[] parents) {
-        this(environment.getConfigId(),
-                urls,
-                parents,
-                environment.isInverseClassLoading(),
-                environment.getHiddenClasses(),
-                environment.getNonOverrideableClasses());
     }
 
     /**