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) { + } } - +*/ + } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]