remm        02/02/07 11:20:36

  Modified:    catalina/src/share/org/apache/catalina/loader Tag:
                        tomcat_40_branch WebappClassLoader.java
                        WebappLoader.java
  Log:
  - Port to the 4.0.x branch the modification to the classloader made in the HEAD
    branch. This includes fixes for a variety of problems, including:
    - 4830: Catalina class loader throws exception while getting
            a directory's URL using Class.getResource()
    - 6248: Using xerces in webapp causes class cast exception
    - Cleanup of source URLs generation
    - Add support for external repositories, so that the CL fully emulates the
      URLClassLoader
  
  Revision  Changes    Path
  No                   revision
  
  
  No                   revision
  
  
  1.15.2.9  +229 -67   
jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/loader/WebappClassLoader.java
  
  Index: WebappClassLoader.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/loader/WebappClassLoader.java,v
  retrieving revision 1.15.2.8
  retrieving revision 1.15.2.9
  diff -u -r1.15.2.8 -r1.15.2.9
  --- WebappClassLoader.java    20 Nov 2001 05:06:34 -0000      1.15.2.8
  +++ WebappClassLoader.java    7 Feb 2002 19:20:35 -0000       1.15.2.9
  @@ -1,7 +1,7 @@
   /*
  - * $Header: 
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/loader/WebappClassLoader.java,v
 1.15.2.8 2001/11/20 05:06:34 remm Exp $
  - * $Revision: 1.15.2.8 $
  - * $Date: 2001/11/20 05:06:34 $
  + * $Header: 
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/loader/WebappClassLoader.java,v
 1.15.2.9 2002/02/07 19:20:35 remm Exp $
  + * $Revision: 1.15.2.9 $
  + * $Date: 2002/02/07 19:20:35 $
    *
    * ====================================================================
    *
  @@ -122,7 +122,7 @@
    *
    * @author Remy Maucherat
    * @author Craig R. McClanahan
  - * @version $Revision: 1.15.2.8 $ $Date: 2001/11/20 05:06:34 $
  + * @version $Revision: 1.15.2.9 $ $Date: 2002/02/07 19:20:35 $
    */
   public class WebappClassLoader
       extends URLClassLoader
  @@ -146,6 +146,49 @@
       }
   
   
  +    // ------------------------------------------------------- Static Variables
  +
  +
  +    /**
  +     * The set of trigger classes that will cause a proposed repository not
  +     * to be added if this class is visible to the class loader that loaded
  +     * this factory class.  Typically, trigger classes will be listed for
  +     * components that have been integrated into the JDK for later versions,
  +     * but where the corresponding JAR files are required to run on
  +     * earlier versions.
  +     */
  +    private static final String[] triggers = {
  +        "com.sun.jndi.ldap.LdapCtxFactory",      // LDAP      added in 1.3
  +        "com.sun.net.ssl.internal.ssl.Provider", // JSSE      added in 1.4
  +        "javax.security.auth.Subject",           // JAAS      added in 1.4
  +        //"javax.net.SocketFactory",               // JSSE      added in 1.4
  +        //"javax.security.cert.X509Certificate",   // JSSE      added in 1.4
  +        //"javax.sql.DataSource",                  // JDBC ext. added in 1.4
  +        //"javax.xml.parsers.DocumentBuilder",     // JAXP      added in 1.4
  +        "javax.servlet.Servlet",                 // Servlet API
  +        // "org.apache.crimson.jaxp.DocumentBuilderImpl",
  +                                                 // Crimson   added in 1.4
  +    };
  +
  +
  +    /**
  +     * The set of trigger classes that will cause a proposed repository not
  +     * to be added if this class is visible to the class loader that loaded
  +     * this factory class.  Typically, trigger classes will be listed for
  +     * components that have been integrated into the JDK for later versions,
  +     * but where the corresponding JAR files are required to run on
  +     * earlier versions.
  +     */
  +    private static final String[] classTriggers = {
  +        "javax.net.",                                // JSSE      added in 1.4
  +        "javax.security.cert.",                      // JSSE      added in 1.4
  +        "javax.naming.",                             // JNDI      added in 1.3
  +        "javax.xml.",                                // JAXP      added in 1.4
  +        "org.xml.sax.",
  +        "org.w3c.dom."
  +    };
  +
  +
       // ----------------------------------------------------------- Constructors
   
   
  @@ -340,6 +383,12 @@
   
   
       /**
  +     * Has external repositories.
  +     */
  +    protected boolean hasExternalRepositories = false;
  +
  +
  +    /**
        * All permission.
        */
       private Permission allPermission = new java.security.AllPermission();
  @@ -398,13 +447,15 @@
        *
        * @param path file directory path
        */
  -    public void setPermissions(String path) {
  +    public void addPermission(String path) {
           if (securityManager != null) {
  +            Permission permission = null;
               if( path.startsWith("jndi:") || path.startsWith("jar:jndi:") ) {
  -                permissionList.add(new JndiPermission(path + "*"));
  +                permission = new JndiPermission(path + "*");
               } else {
  -                permissionList.add(new FilePermission(path + "-","read"));
  +                permission = new FilePermission(path + "-","read");
               }
  +            addPermission(permission);
           }
       }
   
  @@ -415,8 +466,20 @@
        *
        * @param url URL for a file or directory on local system
        */
  -    public void setPermissions(URL url) {
  -        setPermissions(url.toString());
  +    public void addPermission(URL url) {
  +        addPermission(url.toString());
  +    }
  +
  +
  +    /**
  +     * If there is a Java SecurityManager create a Permission.
  +     *
  +     * @param url URL for a file or directory on local system
  +     */
  +    public void addPermission(Permission permission) {
  +        if ((securityManager != null) && (permission != null)) {
  +            permissionList.add(permission);
  +        }
       }
   
   
  @@ -465,6 +528,7 @@
           try {
               URL url = new URL(repository);
               super.addURL(url);
  +            hasExternalRepositories = true;
           } catch (MalformedURLException e) {
               throw new IllegalArgumentException(e.toString());
           }
  @@ -544,13 +608,6 @@
   
           }
   
  -        JarFile[] result2 = new JarFile[jarFiles.length + 1];
  -        for (i = 0; i < jarFiles.length; i++) {
  -            result2[i] = jarFiles[i];
  -        }
  -        result2[jarFiles.length] = jarFile;
  -        jarFiles = result2;
  -
           try {
   
               // Register the JAR for tracking
  @@ -574,8 +631,21 @@
               lastModifiedDates = result3;
   
           } catch (NamingException e) {
  +            // Ignore
           }
   
  +        // If the JAR currently contains invalid classes, don't actually use it
  +        // for classloading
  +        if (!validateJarFile(file))
  +            return;
  +
  +        JarFile[] result2 = new JarFile[jarFiles.length + 1];
  +        for (i = 0; i < jarFiles.length; i++) {
  +            result2[i] = jarFiles[i];
  +        }
  +        result2[jarFiles.length] = jarFile;
  +        jarFiles = result2;
  +
           // Add the file to the list
           File[] result4 = new File[jarRealFiles.length + 1];
           for (i = 0; i < jarRealFiles.length; i++) {
  @@ -862,7 +932,7 @@
                       log("      -->RuntimeException Rethrown", e);
                   throw e;
               }
  -            if (clazz == null) {
  +            if ((clazz == null) && hasExternalRepositories) {
                   try {
                       clazz = super.findClass(name);
                   } catch(AccessControlException ace) {
  @@ -922,7 +992,7 @@
               url = entry.source;
           }
   
  -        if (url == null)
  +        if ((url == null) && hasExternalRepositories)
               url = super.findResource(name);
   
           if (debug >= 3) {
  @@ -965,7 +1035,7 @@
                   // Note : Not getting an exception here means the resource was
                   // found
                   try {
  -                    result.addElement(new File(files[i], name).toURL());
  +                    result.addElement(getURL(new File(files[i], name)));
                   } catch (MalformedURLException e) {
                       // Ignore
                   }
  @@ -978,7 +1048,7 @@
               JarEntry jarEntry = jarFiles[i].getJarEntry(name);
               if (jarEntry != null) {
                   try {
  -                    String jarFakeUrl = jarRealFiles[i].toURL().toString();
  +                    String jarFakeUrl = getURL(jarRealFiles[i]).toString();
                       jarFakeUrl = "jar:" + jarFakeUrl + "!/" + name;
                       result.addElement(new URL(jarFakeUrl));
                   } catch (MalformedURLException e) {
  @@ -988,10 +1058,14 @@
           }
   
           // Adding the results of a call to the superclass
  -        Enumeration otherResourcePaths = super.findResources(name);
  +        if (hasExternalRepositories) {
  +
  +            Enumeration otherResourcePaths = super.findResources(name);
  +
  +            while (otherResourcePaths.hasMoreElements()) {
  +                result.addElement(otherResourcePaths.nextElement());
  +            }
   
  -        while (otherResourcePaths.hasMoreElements()) {
  -            result.addElement(otherResourcePaths.nextElement());
           }
   
           return result.elements();
  @@ -1122,7 +1196,7 @@
                   log("  --> Returning stream from local");
               stream = findLoadedResource(name);
               try {
  -                if (stream == null)
  +                if (hasExternalRepositories && (stream == null))
                       stream = url.openStream();
               } catch (IOException e) {
                   ; // Ignore
  @@ -1372,9 +1446,9 @@
               URL[] urls = new URL[length];
               for (i = 0; i < length; i++) {
                   if (i < filesLength) {
  -                    urls[i] = files[i].toURL();
  +                    urls[i] = getURL(files[i]);
                   } else if (i < filesLength + jarFilesLength) {
  -                    urls[i] = jarRealFiles[i - filesLength].toURL();
  +                    urls[i] = getURL(jarRealFiles[i - filesLength]);
                   } else {
                       urls[i] = external[i - filesLength - jarFilesLength];
                   }
  @@ -1402,6 +1476,15 @@
   
   
       /**
  +     * Get the lifecycle listeners associated with this lifecycle. If this 
  +     * Lifecycle has no listeners registered, a zero-length array is returned.
  +     */
  +    public LifecycleListener[] findLifecycleListeners() {
  +        return new LifecycleListener[0];
  +    }
  +
  +
  +    /**
        * Remove a lifecycle event listener from this component.
        *
        * @param listener The listener to remove
  @@ -1451,6 +1534,7 @@
           jarNames = new String[0];
           lastModifiedDates = new long[0];
           paths = new String[0];
  +        hasExternalRepositories = false;
   
           required.clear();
           permissionList.clear();
  @@ -1486,7 +1570,7 @@
               entry = findResourceInternal(name, classPath);
           }
   
  -        if (entry == null)
  +        if ((entry == null) || (entry.binaryContent == null))
               throw new ClassNotFoundException(name);
   
           Class clazz = entry.loadedClass;
  @@ -1592,14 +1676,17 @@
   
                   String fullPath = repositories[i] + path;
   
  -                resource = (Resource) resources.lookup(fullPath);
  +                Object lookupResult = resources.lookup(fullPath);
  +                if (lookupResult instanceof Resource) {
  +                    resource = (Resource) lookupResult;
  +                }
   
                   // Note : Not getting an exception here means the resource was
                   // found
   
                   entry = new ResourceEntry();
                   try {
  -                    entry.source = new File(files[i], path).toURL();
  +                    entry.source = getURL(new File(files[i], path));
                   } catch (MalformedURLException e) {
                       return null;
                   }
  @@ -1607,30 +1694,36 @@
                       (ResourceAttributes) resources.getAttributes(fullPath);
                   contentLength = (int) attributes.getContentLength();
                   entry.lastModified = attributes.getLastModified();
  -                try {
  -                    binaryStream = resource.streamContent();
  -                } catch (IOException e) {
  -                    return null;
  -                }
   
  -                // Register the full path for modification checking
  -                synchronized (paths) {
  +                if (resource != null) {
   
  -                    int j;
  -
  -                    long[] result2 = new long[lastModifiedDates.length + 1];
  -                    for (j = 0; j < lastModifiedDates.length; j++) {
  -                        result2[j] = lastModifiedDates[j];
  +                    try {
  +                        binaryStream = resource.streamContent();
  +                    } catch (IOException e) {
  +                        return null;
                       }
  -                    result2[lastModifiedDates.length] = entry.lastModified;
  -                    lastModifiedDates = result2;
   
  -                    String[] result = new String[paths.length + 1];
  -                    for (j = 0; j < paths.length; j++) {
  -                        result[j] = paths[j];
  +                    // Register the full path for modification checking
  +                    synchronized (paths) {
  +
  +                        int j;
  +
  +                        long[] result2 = 
  +                            new long[lastModifiedDates.length + 1];
  +                        for (j = 0; j < lastModifiedDates.length; j++) {
  +                            result2[j] = lastModifiedDates[j];
  +                        }
  +                        result2[lastModifiedDates.length] = entry.lastModified;
  +                        lastModifiedDates = result2;
  +
  +                        String[] result = new String[paths.length + 1];
  +                        for (j = 0; j < paths.length; j++) {
  +                            result[j] = paths[j];
  +                        }
  +                        result[paths.length] = fullPath;
  +                        paths = result;
  +
                       }
  -                    result[paths.length] = fullPath;
  -                    paths = result;
   
                   }
   
  @@ -1651,7 +1744,7 @@
   
                   entry = new ResourceEntry();
                   try {
  -                    String jarFakeUrl = jarRealFiles[i].toURL().toString();
  +                    String jarFakeUrl = getURL(jarRealFiles[i]).toString();
                       jarFakeUrl = "jar:" + jarFakeUrl + "!/" + path;
                       entry.source = new URL(jarFakeUrl);
                   } catch (MalformedURLException e) {
  @@ -1677,27 +1770,31 @@
               return null;
           }
   
  -        byte[] binaryContent = new byte[contentLength];
  +        if (binaryStream != null) {
   
  -        try {
  -            int pos = 0;
  -            while (true) {
  -                int n = binaryStream.read(binaryContent, pos,
  -                                          binaryContent.length - pos);
  -                if (n <= 0)
  -                    break;
  -                pos += n;
  +            byte[] binaryContent = new byte[contentLength];
  +
  +            try {
  +                int pos = 0;
  +                while (true) {
  +                    int n = binaryStream.read(binaryContent, pos,
  +                                              binaryContent.length - pos);
  +                    if (n <= 0)
  +                        break;
  +                    pos += n;
  +                }
  +                binaryStream.close();
  +            } catch (IOException e) {
  +                e.printStackTrace();
  +                return null;
  +            } catch (Exception e) {
  +                e.printStackTrace();
  +                return null;
               }
  -            binaryStream.close();
  -        } catch (IOException e) {
  -            e.printStackTrace();
  -            return null;
  -        } catch (Exception e) {
  -            e.printStackTrace();
  -            return null;
  -        }
   
  -        entry.binaryContent = binaryContent;
  +            entry.binaryContent = binaryContent;
  +
  +        }
   
           // Add the entry in the local resource repository
           synchronized (this) {
  @@ -1814,6 +1911,7 @@
               return false;
   
           // Looking up the package
  +        /*
           String packageName = null;
           int pos = name.lastIndexOf('.');
           if (pos != -1)
  @@ -1829,8 +1927,72 @@
               return false;
           if (packageName.equals("javax.servlet.jsp.tagext"))
               return false;
  +        */
  +        for (int i = 0; i < classTriggers.length; i++) {
  +            if (name.startsWith(classTriggers[i]))
  +                return false;
  +        }
   
           return true;
  +
  +    }
  +
  +
  +    /**
  +     * Check the specified JAR file, and return <code>true</code> if it does
  +     * not contain any of the trigger classes.
  +     *
  +     * @param jarFile The JAR file to be checked
  +     *
  +     * @exception IOException if an input/output error occurs
  +     */
  +    private boolean validateJarFile(File jarfile)
  +        throws IOException {
  +
  +        if (triggers == null)
  +            return (true);
  +        JarFile jarFile = new JarFile(jarfile);
  +        for (int i = 0; i < triggers.length; i++) {
  +            Class clazz = null;
  +            try {
  +                if (parent != null) {
  +                    clazz = parent.loadClass(triggers[i]);
  +                } else {
  +                    clazz = Class.forName(triggers[i]);
  +                }
  +            } catch (Throwable t) {
  +                clazz = null;
  +            }
  +            if (clazz == null)
  +                continue;
  +            String name = triggers[i].replace('.', '/') + ".class";
  +            if (debug >= 2)
  +                log(" Checking for " + name);
  +            JarEntry jarEntry = jarFile.getJarEntry(name);
  +            if (jarEntry != null) {
  +                jarFile.close();
  +                return (false);
  +            }
  +        }
  +        jarFile.close();
  +        return (true);
  +
  +    }
  +
  +
  +    /**
  +     * Get URL.
  +     */
  +    protected URL getURL(File file)
  +        throws MalformedURLException {
  +
  +        File realFile = file;
  +        try {
  +            realFile = realFile.getCanonicalFile();
  +        } catch (IOException e) {
  +            // Ignore
  +        }
  +        return new URL("file:" + realFile.getPath());
   
       }
   
  
  
  
  1.12.2.5  +11 -11    
jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/loader/WebappLoader.java
  
  Index: WebappLoader.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/loader/WebappLoader.java,v
  retrieving revision 1.12.2.4
  retrieving revision 1.12.2.5
  diff -u -r1.12.2.4 -r1.12.2.5
  --- WebappLoader.java 12 Dec 2001 20:54:27 -0000      1.12.2.4
  +++ WebappLoader.java 7 Feb 2002 19:20:35 -0000       1.12.2.5
  @@ -1,7 +1,7 @@
   /*
  - * $Header: 
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/loader/WebappLoader.java,v
 1.12.2.4 2001/12/12 20:54:27 craigmcc Exp $
  - * $Revision: 1.12.2.4 $
  - * $Date: 2001/12/12 20:54:27 $
  + * $Header: 
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/loader/WebappLoader.java,v
 1.12.2.5 2002/02/07 19:20:35 remm Exp $
  + * $Revision: 1.12.2.5 $
  + * $Date: 2002/02/07 19:20:35 $
    *
    * ====================================================================
    *
  @@ -119,7 +119,7 @@
    *
    * @author Craig R. McClanahan
    * @author Remy Maucherat
  - * @version $Revision: 1.12.2.4 $ $Date: 2001/12/12 20:54:27 $
  + * @version $Revision: 1.12.2.5 $ $Date: 2002/02/07 19:20:35 $
    */
   
   public class WebappLoader
  @@ -805,7 +805,7 @@
           try {
   
               URL rootURL = servletContext.getResource("/");
  -            classLoader.setPermissions(rootURL);
  +            classLoader.addPermission(rootURL);
   
               String contextRoot = servletContext.getRealPath("/");
               if (contextRoot != null) {
  @@ -813,7 +813,7 @@
                       contextRoot = 
                           (new File(contextRoot)).getCanonicalPath() 
                           + File.separator;
  -                    classLoader.setPermissions(contextRoot);
  +                    classLoader.addPermission(contextRoot);
                   } catch (IOException e) {
                       // Ignore
                   }
  @@ -822,11 +822,11 @@
               URL classesURL =
                   servletContext.getResource("/WEB-INF/classes/");
               if (classesURL != null)
  -                classLoader.setPermissions(classesURL);
  +                classLoader.addPermission(classesURL);
   
               URL libURL = servletContext.getResource("/WEB-INF/lib/");
               if (libURL != null) {
  -                classLoader.setPermissions(libURL);
  +                classLoader.addPermission(libURL);
               }
   
               if (contextRoot != null) {
  @@ -840,7 +840,7 @@
                       } catch (IOException e) {
                       }
                       if (path != null)
  -                        classLoader.setPermissions(path);
  +                        classLoader.addPermission(path);
                   }
   
               } else {
  @@ -856,7 +856,7 @@
                               path = libDir.getCanonicalPath() + File.separator;
                           } catch (IOException e) {
                           }
  -                        classLoader.setPermissions(path);
  +                        classLoader.addPermission(path);
                       }
                       if (classesURL != null) {
                           File classesDir =
  @@ -867,7 +867,7 @@
                                   + File.separator;
                           } catch (IOException e) {
                           }
  -                        classLoader.setPermissions(path);
  +                        classLoader.addPermission(path);
                       }
                   }
   
  
  
  

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to