You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2001/01/13 06:27:54 UTC

cvs commit: jakarta-tomcat-4.1/catalina/src/share/org/apache/catalina/loader StandardClassLoader.java StandardLoader.java

remm        01/01/12 21:27:54

  Modified:    catalina/src/share/org/apache/catalina/loader
                        StandardClassLoader.java StandardLoader.java
  Log:
  - "Fixes" webapp classloading.
  - Class files in /WEB-INF/classes are loaded through a URL to a DirContext
    (good :).
  - JAR files couldn't work that way, so it uses direct filesystem access :(
  - You can read the comments about my failed attempt in StandardLoader.
    I left the commented code which tries to register JNDI URL repositories.
    Unfortunately, it appears that the URLClassLoader (and its hidden helper
    classes) don't like my URLs. Any explanation / solution would be greatly
    appreciated.
  
  Revision  Changes    Path
  1.6       +116 -18   jakarta-tomcat-4.1/catalina/src/share/org/apache/catalina/loader/StandardClassLoader.java
  
  Index: StandardClassLoader.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-4.1/catalina/src/share/org/apache/catalina/loader/StandardClassLoader.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- StandardClassLoader.java	2000/10/09 21:04:02	1.5
  +++ StandardClassLoader.java	2001/01/13 05:27:54	1.6
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat-4.1/catalina/src/share/org/apache/catalina/loader/StandardClassLoader.java,v 1.5 2000/10/09 21:04:02 craigmcc Exp $
  - * $Revision: 1.5 $
  - * $Date: 2000/10/09 21:04:02 $
  + * $Header: /home/cvs/jakarta-tomcat-4.1/catalina/src/share/org/apache/catalina/loader/StandardClassLoader.java,v 1.6 2001/01/13 05:27:54 remm Exp $
  + * $Revision: 1.6 $
  + * $Date: 2001/01/13 05:27:54 $
    *
    * ====================================================================
    *
  @@ -71,11 +71,16 @@
   import java.net.MalformedURLException;
   import java.net.URL;
   import java.net.URLClassLoader;
  +import java.net.URLConnection;
  +import java.net.URLStreamHandlerFactory;
  +import java.net.URLStreamHandler;
   import java.util.ArrayList;
   import java.util.Enumeration;
   import java.util.HashMap;
   import java.util.Iterator;
   import java.util.jar.JarFile;
  +import java.util.jar.JarEntry;
  +import java.util.jar.JarInputStream;
   import java.util.jar.Manifest;
   
   
  @@ -99,7 +104,8 @@
    * independently.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.5 $ $Date: 2000/10/09 21:04:02 $
  + * @author Remy Maucherat
  + * @version $Revision: 1.6 $ $Date: 2001/01/13 05:27:54 $
    */
   
   public class StandardClassLoader
  @@ -122,6 +128,20 @@
   
   
       /**
  +     * Construct a new ClassLoader with no defined repositories and no
  +     * parent ClassLoader, but with a stream handler factory.
  +     * 
  +     * @param factory the URLStreamHandlerFactory to use when creating URLs
  +     */
  +    public StandardClassLoader(URLStreamHandlerFactory factory) {
  +
  +        super(new URL[0], null, factory);
  +        this.factory = factory;
  +
  +    }
  +
  +
  +    /**
        * Construct a new ClassLoader with no defined repositories and the
        * specified parent ClassLoader.
        *
  @@ -135,6 +155,22 @@
   
   
       /**
  +     * Construct a new ClassLoader with no defined repositories and the
  +     * specified parent ClassLoader.
  +     *
  +     * @param parent The parent ClassLoader
  +     * @param factory the URLStreamHandlerFactory to use when creating URLs
  +     */
  +    public StandardClassLoader(ClassLoader parent, 
  +                               URLStreamHandlerFactory factory) {
  +
  +        super((new URL[0]), parent, factory);
  +        this.factory = factory;
  +
  +    }
  +
  +
  +    /**
        * Construct a new ClassLoader with the specified repositories and
        * no parent ClassLoader.
        *
  @@ -263,6 +299,12 @@
       protected String systems[] = { "java." };
   
   
  +    /**
  +     * URL stream handler for additional protocols.
  +     */
  +    protected URLStreamHandlerFactory factory = null;
  +
  +
       // ------------------------------------------------------------- Properties
   
   
  @@ -352,7 +394,12 @@
   
           // Add this repository to our underlying class loader
           try {
  -            super.addURL(new URL(repository));
  +            URLStreamHandler streamHandler = null;
  +            String protocol = parseProtocol(repository);
  +            if (factory != null)
  +                streamHandler = factory.createURLStreamHandler(protocol);
  +            URL url = new URL(null, repository, streamHandler);
  +            super.addURL(url);
           } catch (MalformedURLException e) {
               throw new IllegalArgumentException(e.toString());
           }
  @@ -1028,6 +1075,21 @@
   
   
       /**
  +     * Parse URL protocol.
  +     * 
  +     * @return String protocol
  +     */
  +    protected static String parseProtocol(String spec) {
  +        if (spec == null)
  +            return "";
  +        int pos = spec.indexOf(':');
  +        if (pos <= 0)
  +            return "";
  +        return spec.substring(0, pos).trim();
  +    }
  +
  +
  +    /**
        * Add a repository to our internal array only.
        *
        * @param repository The new repository
  @@ -1037,12 +1099,18 @@
        */
       protected void addRepositoryInternal(String repository) {
   
  +        URLStreamHandler streamHandler = null;
  +        String protocol = parseProtocol(repository);
  +        if (factory != null)
  +            streamHandler = factory.createURLStreamHandler(protocol);
  +
           // Validate the manifest of a JAR file repository
           if (!repository.endsWith("/")) {
               try {
                   JarFile jarFile = null;
  +                Manifest manifest = null;
                   if (repository.startsWith("jar:")) {
  -                    URL url = new URL(repository);
  +                    URL url = new URL(null, repository, streamHandler);
                       JarURLConnection conn =
                           (JarURLConnection) url.openConnection();
                       conn.setAllowUserInteraction(false);
  @@ -1054,23 +1122,34 @@
                       jarFile = new JarFile(repository.substring(7));
                   } else if (repository.startsWith("file:")) {
                       jarFile = new JarFile(repository.substring(5));
  +                } else if (repository.endsWith(".jar")) {
  +                    URL url = new URL(null, repository, streamHandler);
  +                    URLConnection conn = url.openConnection();
  +                    JarInputStream jis = 
  +                        new JarInputStream(conn.getInputStream());
  +                    manifest = jis.getManifest();
                   } else {
                       throw new IllegalArgumentException
                           ("addRepositoryInternal:  Invalid URL '" +
                            repository + "'");
  +                }
  +                if (!((manifest == null) && (jarFile == null))) {
  +                    if ((manifest == null) && (jarFile != null))
  +                        manifest = jarFile.getManifest();
  +                    Iterator extensions =
  +                        Extension.getAvailable(manifest).iterator();
  +                    while (extensions.hasNext())
  +                        available.add(extensions.next());
  +                    extensions =
  +                        Extension.getRequired(manifest).iterator();
  +                    while (extensions.hasNext())
  +                        required.add(extensions.next());
  +                    jarFile.close();
                   }
  -                Manifest manifest = jarFile.getManifest();
  -                Iterator extensions =
  -                    Extension.getAvailable(manifest).iterator();
  -                while (extensions.hasNext())
  -                    available.add(extensions.next());
  -                extensions =
  -                    Extension.getRequired(manifest).iterator();
  -                while (extensions.hasNext())
  -                    required.add(extensions.next());
  -                jarFile.close();
               } catch (Throwable t) {
  -                throw new IllegalArgumentException("addRepositoryInternal: " + t);
  +                t.printStackTrace();
  +                throw new IllegalArgumentException
  +                    ("addRepositoryInternal: " + t);
               }
           }
   
  @@ -1091,11 +1170,30 @@
        * @param input The array of String to be converted
        */
       protected static URL[] convert(String input[]) {
  +        return convert(input, null);
  +    }
  +
  +
  +    /**
  +     * Convert an array of String to an array of URL and return it.
  +     *
  +     * @param input The array of String to be converted
  +     * @param factory Handler factory to use to generate the URLs
  +     */
  +    protected static URL[] convert(String input[], 
  +                                   URLStreamHandlerFactory factory) {
  +
  +        URLStreamHandler streamHandler = null;
   
           URL url[] = new URL[input.length];
           for (int i = 0; i < url.length; i++) {
               try {
  -                url[i] = new URL(input[i]);
  +                String protocol = parseProtocol(input[i]);
  +                if (factory != null)
  +                    streamHandler = factory.createURLStreamHandler(protocol);
  +                else
  +                    streamHandler = null;
  +                url[i] = new URL(null, input[i], streamHandler);
               } catch (MalformedURLException e) {
                   url[i] = null;
               }
  
  
  
  1.15      +78 -29    jakarta-tomcat-4.1/catalina/src/share/org/apache/catalina/loader/StandardLoader.java
  
  Index: StandardLoader.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-4.1/catalina/src/share/org/apache/catalina/loader/StandardLoader.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- StandardLoader.java	2001/01/12 06:46:54	1.14
  +++ StandardLoader.java	2001/01/13 05:27:54	1.15
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat-4.1/catalina/src/share/org/apache/catalina/loader/StandardLoader.java,v 1.14 2001/01/12 06:46:54 remm Exp $
  - * $Revision: 1.14 $
  - * $Date: 2001/01/12 06:46:54 $
  + * $Header: /home/cvs/jakarta-tomcat-4.1/catalina/src/share/org/apache/catalina/loader/StandardLoader.java,v 1.15 2001/01/13 05:27:54 remm Exp $
  + * $Revision: 1.15 $
  + * $Date: 2001/01/13 05:27:54 $
    *
    * ====================================================================
    *
  @@ -73,7 +73,13 @@
   import java.net.MalformedURLException;
   import java.net.URL;
   import java.net.URLClassLoader;
  +import java.net.URLStreamHandlerFactory;
   import javax.servlet.ServletContext;
  +import javax.naming.NamingException;
  +import javax.naming.NameClassPair;
  +import javax.naming.NamingEnumeration;
  +import javax.naming.directory.DirContext;
  +import org.apache.naming.resources.DirContextURLStreamHandlerFactory;
   import org.apache.catalina.Container;
   import org.apache.catalina.Context;
   import org.apache.catalina.Globals;
  @@ -100,7 +106,8 @@
    * is not present, the system class loader will be used instead.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.14 $ $Date: 2001/01/12 06:46:54 $
  + * @author Remy Maucherat
  + * @version $Revision: 1.15 $ $Date: 2001/01/13 05:27:54 $
    */
   
   public final class StandardLoader
  @@ -580,10 +587,16 @@
   
   	// Construct a class loader based on our current repositories list
   	try {
  +            URLStreamHandlerFactory shFactory = null;
  +            if ((this.container != null) && 
  +                (this.container.getResources() != null))
  +                shFactory = new DirContextURLStreamHandlerFactory
  +                    (this.container.getResources());
   	    if (parentClassLoader == null)
  -	        classLoader = new StandardClassLoader();
  +	        classLoader = new StandardClassLoader(shFactory);
   	    else
  -	        classLoader = new StandardClassLoader(parentClassLoader);
  +	        classLoader = new StandardClassLoader
  +                    (parentClassLoader, shFactory);
   	    for (int i = 0; i < repositories.length; i++)
   		classLoader.addRepository(repositories[i]);
   	    classLoader.addRestricted("org.apache.catalina.");
  @@ -858,34 +871,70 @@
           }
   
   	// Add the WEB-INF/lib/*.jar files
  -	URL libURL = null;
  -	try {
  -	    libURL = servletContext.getResource("/WEB-INF/lib");
  -	} catch (MalformedURLException e) {
  -	    libURL = null;
  -	}
           // FIXME - This still requires disk directory!  Scan JARs if present
  -        if ((libURL != null) && "file".equals(libURL.getProtocol())) {
  -	    File libFile = new File(libURL.getFile());
  -	    if (libFile.exists() && libFile.canRead() &&
  -	        libFile.isDirectory()) {
  -		String filenames[] = libFile.list();
  -		for (int i = 0; i < filenames.length; i++) {
  -		    if (!filenames[i].endsWith(".jar"))
  +        File libFile = new File(((Context) container).getDocBase(), 
  +                                "/WEB-INF/lib");
  +        if (libFile.exists() && libFile.canRead() &&
  +            libFile.isDirectory()) {
  +            String filenames[] = libFile.list();
  +            for (int i = 0; i < filenames.length; i++) {
  +                if (!filenames[i].endsWith(".jar"))
  +                    continue;
  +                File jarFile = new File(libFile, filenames[i]);
  +                try {
  +                    if (debug > 0)
  +                        log(" Adding '" + "file: " +
  +                            jarFile.getCanonicalPath() + "'");
  +                    addRepository("file:" + jarFile.getCanonicalPath());
  +                } catch (IOException e) {
  +                    log(jarFile.getAbsolutePath(), e);
  +                }
  +            }
  +        }
  +        
  +        // FIXME: The code below is the elegant version of the ten lines of 
  +        // code above. The problem is that it doesn't work due to some 
  +        // classloading issues (the URL classloader doesn't seem to like my
  +        // URL objects when they point to JAR files, although loading of
  +        // individual classes work fine).
  +        
  +/*
  +        DirContext resources = container.getResources();
  +        String libName = "/WEB-INF/lib";
  +        DirContext libDir = null;
  +        // Looking up directory /WEB-INF/lib in the context
  +        try {
  +            Object object = resources.lookup(libName);
  +            if (object instanceof DirContext)
  +                libDir = (DirContext) object;
  +        } catch(NamingException e) {
  +            // Silent catch: it's valid that no /WEB-INF/lib directory exists
  +        }
  +
  +	// Add the WEB-INF/lib/*.jar files
  +        if (libDir != null) {
  +            // Enumerate children
  +            try {
  +                NamingEnumeration enum = resources.list(libName);
  +                while (enum.hasMoreElements()) {
  +                    NameClassPair ncPair = (NameClassPair) enum.nextElement();
  +                    String filename = ncPair.getName();
  +                    if (!filename.endsWith(".jar"))
   		        continue;
  -		    File jarFile = new File(libFile, filenames[i]);
                       try {
  -                        if (debug > 0)
  -                            log(" Adding '" + "file: " +
  -                                jarFile.getCanonicalPath() + "'");
  -                        addRepository("file:" + jarFile.getCanonicalPath());
  -                    } catch (IOException e) {
  -                        log(jarFile.getAbsolutePath(), e);
  +                        URL fileURL = servletContext.getResource
  +                            (libName + "/" + filename);
  +                        log(" Adding '" + "file: " +
  +                            libName + "/" + filename + "'");
  +                        addRepository(fileURL.toString());
  +                    } catch (MalformedURLException e) {
                       }
  -		}
  -	    }
  +                }
  +            } catch(NamingException e) {
  +            }
           }
  -        
  +*/
  +
       }