Return-Path: Delivered-To: apmail-cocoon-cvs-archive@www.apache.org Received: (qmail 49364 invoked from network); 3 Dec 2004 10:09:40 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur-2.apache.org with SMTP; 3 Dec 2004 10:09:40 -0000 Received: (qmail 76012 invoked by uid 500); 3 Dec 2004 10:09:38 -0000 Delivered-To: apmail-cocoon-cvs-archive@cocoon.apache.org Received: (qmail 75955 invoked by uid 500); 3 Dec 2004 10:09:37 -0000 Mailing-List: contact cvs-help@cocoon.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@cocoon.apache.org list-help: list-unsubscribe: list-post: Delivered-To: mailing list cvs@cocoon.apache.org Received: (qmail 75934 invoked by uid 99); 3 Dec 2004 10:09:37 -0000 X-ASF-Spam-Status: No, hits=-10.0 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from minotaur.apache.org (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.28) with SMTP; Fri, 03 Dec 2004 02:09:33 -0800 Received: (qmail 49112 invoked by uid 65534); 3 Dec 2004 10:09:31 -0000 Date: 3 Dec 2004 10:09:31 -0000 Message-ID: <20041203100931.49107.qmail@minotaur.apache.org> From: tcurdt@apache.org To: cvs@cocoon.apache.org Subject: svn commit: r109661 - /cocoon/branches/BRANCH_2_1_X/src/blocks/paranoid/java/org/apache/cocoon/servlet/ParanoidClassLoader.java /cocoon/branches/BRANCH_2_1_X/src/blocks/paranoid/java/org/apache/cocoon/servlet/ParanoidCocoonServlet.java /cocoon/branches/BRANCH_2_1_X/status.xml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 X-Virus-Checked: Checked X-Spam-Rating: minotaur-2.apache.org 1.6.2 0/1000/N Author: tcurdt Date: Fri Dec 3 02:09:30 2004 New Revision: 109661 URL: http://svn.apache.org/viewcvs?view=rev&rev=109661 Log: make the classloader implementation configurable inside the web.xml Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/paranoid/java/org/apache/cocoon/servlet/ParanoidClassLoader.java cocoon/branches/BRANCH_2_1_X/src/blocks/paranoid/java/org/apache/cocoon/servlet/ParanoidCocoonServlet.java cocoon/branches/BRANCH_2_1_X/status.xml Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/paranoid/java/org/apache/cocoon/servlet/ParanoidClassLoader.java Url: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/paranoid/java/org/apache/cocoon/servlet/ParanoidClassLoader.java?view=diff&rev=109661&p1=cocoon/branches/BRANCH_2_1_X/src/blocks/paranoid/java/org/apache/cocoon/servlet/ParanoidClassLoader.java&r1=109660&p2=cocoon/branches/BRANCH_2_1_X/src/blocks/paranoid/java/org/apache/cocoon/servlet/ParanoidClassLoader.java&r2=109661 ============================================================================== --- cocoon/branches/BRANCH_2_1_X/src/blocks/paranoid/java/org/apache/cocoon/servlet/ParanoidClassLoader.java (original) +++ cocoon/branches/BRANCH_2_1_X/src/blocks/paranoid/java/org/apache/cocoon/servlet/ParanoidClassLoader.java Fri Dec 3 02:09:30 2004 @@ -22,12 +22,13 @@ import java.net.URLStreamHandlerFactory; /** - * The ParanoidClassLoader reverses the search order for - * classes. It checks this classloader before it checks its parent. - * - * @author Berin Loritsch - * @author Sylvain Wallez - * @version CVS $Id: ParanoidClassLoader.java,v 1.2 2004/03/05 13:02:02 bdelacretaz Exp $ + * The ParanoidClassLoader reverses the search order for classes. + * It checks this classloader before it checks its parent. + * + * @author Berin Loritsch + * @author Sylvain Wallez + * @version CVS $Id: ParanoidClassLoader.java 30932 2004-07-29 17:35:38Z + * vgritsenko $ */ public class ParanoidClassLoader extends URLClassLoader { @@ -54,33 +55,32 @@ } /** - * Alternate constructor to define a parent and initial - * URLs. + * Alternate constructor to define a parent and initial URL + * s. */ public ParanoidClassLoader(final URL[] urls, final ClassLoader parent) { this(urls, parent, null); } /** - * Alternate constructor to define a parent, initial - * URLs, and a default - * URLStreamHandlerFactory. + * Alternate constructor to define a parent, initial URLs, + * and a default URLStreamHandlerFactory. */ public ParanoidClassLoader(final URL[] urls, final ClassLoader parent, final URLStreamHandlerFactory factory) { super(urls, parent, factory); } /** - * Extends URLClassLoader's initialization methods so - * we return a ParanoidClassLoad instead. + * Extends URLClassLoader's initialization methods so we + * return a ParanoidClassLoad instead. */ public static final URLClassLoader newInstance(final URL[] urls) { return new ParanoidClassLoader(urls); } /** - * Extends URLClassLoader's initialization methods so - * we return a ParanoidClassLoad instead. + * Extends URLClassLoader's initialization methods so we + * return a ParanoidClassLoad instead. */ public static final URLClassLoader newInstance(final URL[] urls, final ClassLoader parent) { return new ParanoidClassLoader(urls, parent); @@ -98,21 +98,19 @@ * @return the resulting Class object * @exception ClassNotFoundException if the class could not be found */ - public final Class loadClass(String name, boolean resolve) - throws ClassNotFoundException - { + public final Class loadClass(String name, boolean resolve) throws ClassNotFoundException { // First check if it's already loaded Class clazz = findLoadedClass(name); - + if (clazz == null) { - + try { clazz = findClass(name); //System.err.println("Paranoid load : " + name); } catch (ClassNotFoundException cnfe) { ClassLoader parent = getParent(); if (parent != null) { - // Ask to parent ClassLoader (can also throw a CNFE). + // Ask to parent ClassLoader (can also throw a CNFE). clazz = parent.loadClass(name); } else { // Propagate exception @@ -120,14 +118,14 @@ } } } - + if (resolve) { resolveClass(clazz); } - + return clazz; } - + /** * Gets a resource from this ClassLoader. If the * resource does not exist in this one, we check the parent. @@ -150,19 +148,20 @@ /** * Adds a new directory of class files. - * - * @param file for jar or directory + * + * @param file + * for jar or directory * @throws IOException */ public final void addDirectory(File file) throws IOException { this.addURL(file.getCanonicalFile().toURL()); } - + /** * Adds a new URL */ - + public void addURL(URL url) { - super.addURL(url); + super.addURL(url); } -} +} \ No newline at end of file Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/paranoid/java/org/apache/cocoon/servlet/ParanoidCocoonServlet.java Url: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/paranoid/java/org/apache/cocoon/servlet/ParanoidCocoonServlet.java?view=diff&rev=109661&p1=cocoon/branches/BRANCH_2_1_X/src/blocks/paranoid/java/org/apache/cocoon/servlet/ParanoidCocoonServlet.java&r1=109660&p2=cocoon/branches/BRANCH_2_1_X/src/blocks/paranoid/java/org/apache/cocoon/servlet/ParanoidCocoonServlet.java&r2=109661 ============================================================================== --- cocoon/branches/BRANCH_2_1_X/src/blocks/paranoid/java/org/apache/cocoon/servlet/ParanoidCocoonServlet.java (original) +++ cocoon/branches/BRANCH_2_1_X/src/blocks/paranoid/java/org/apache/cocoon/servlet/ParanoidCocoonServlet.java Fri Dec 3 02:09:30 2004 @@ -20,6 +20,8 @@ import java.io.FilenameFilter; import java.io.IOException; import java.io.LineNumberReader; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; @@ -33,18 +35,20 @@ import javax.servlet.http.HttpServlet; /** - * This servlet builds a classloading sandbox and runs another servlet inside that - * sandbox. The purpose is to shield the libraries and classes shipped with the web - * application from any other classes with the same name that may exist in the system, - * such as Xerces and Xalan versions included in JDK 1.4. + * This servlet builds a classloading sandbox and runs another servlet inside + * that sandbox. The purpose is to shield the libraries and classes shipped with + * the web application from any other classes with the same name that may exist + * in the system, such as Xerces and Xalan versions included in JDK 1.4. *

- * This servlet propagates all initialisation parameters to the sandboxed servlet, and - * accepts the parameters servlet-class and paranoid-classpath. + * This servlet propagates all initialisation parameters to the sandboxed + * servlet, and accepts the parameters servlet-class and + * paranoid-classpath. *

    - *
  • servlet-class defines the sandboxed servlet class, the default is - * {@link CocoonServlet} - *
  • paranoid-classpath expects the name of a text file that can contain - * lines begining with class-dir: (directory containing classes), + *
  • servlet-class defines the sandboxed servlet class, the + * default is {@link CocoonServlet} + *
  • paranoid-classpath expects the name of a text file that + * can contain lines begining with + * class-dir: (directory containing classes), * lib-dir: (directory containing JAR or ZIP libraries) and # * (for comments).
    * All other lines are considered as URLs. @@ -55,166 +59,167 @@ * * @author Berin Loritsch * @author Sylvain Wallez + * @author Torsten Curdt * @version CVS $Id$ */ public class ParanoidCocoonServlet extends HttpServlet { - /** - * The name of the actual servlet class. - */ - public static final String DEFAULT_SERVLET_CLASS = "org.apache.cocoon.servlet.CocoonServlet"; - + /** + * The name of the actual servlet class. + */ + public static final String DEFAULT_SERVLET_CLASS = "org.apache.cocoon.servlet.CocoonServlet"; + protected static final String CONTEXT_PREFIX = "context:"; - + protected static final String FILE_PREFIX = "file:"; - - protected Servlet servlet; - + + protected Servlet servlet; + protected ClassLoader classloader; - - public void init(ServletConfig config) throws ServletException { - - super.init(config); - // Create the classloader in which we will load the servlet + public void init(ServletConfig config) throws ServletException { + + super.init(config); + + // Create the classloader in which we will load the servlet // this can either be specified by an external file configured - // as a parameter in web.xml or (the default) all jars and + // as a parameter in web.xml or (the default) all jars and // classes from WEB-INF/lib and WEB-INF/classes are used. final String externalClasspath = config.getInitParameter("paranoid-classpath"); - if ( externalClasspath == null ) { - this.classloader = this.getClassLoader(this.getContextDir()); - } else { - this.classloader = this.getClassLoader(externalClasspath, this.getContextDir()); + final URL[] classPath = (externalClasspath == null) + ? getClassPath(getContextDir()) + : getClassPath(externalClasspath, getContextDir()); + + + final String classLoaderName = config.getInitParameter("classloader-class"); + if (classLoaderName != null) { + log("Using classloader " + classLoaderName); } + this.classloader = createClassLoader(classLoaderName, classPath); + String servletName = config.getInitParameter("servlet-class"); if (servletName == null) { servletName = DEFAULT_SERVLET_CLASS; } + log("Loading servlet class " + servletName); + // Create the servlet - try { - Class servletClass = this.classloader.loadClass(servletName); - - this.servlet = (Servlet)servletClass.newInstance(); + try { - } catch(Exception e) { - throw new ServletException("Cannot load servlet " + servletName, e); - } - - // Always set the context classloader. JAXP uses it to find a ParserFactory, - // and thus fails if it's not set to the webapp classloader. + Class servletClass = this.classloader.loadClass(servletName); + this.servlet = (Servlet) servletClass.newInstance(); + + } catch (Exception e) { + throw new ServletException("Cannot load servlet " + servletName, e); + } + + // Always set the context classloader. JAXP uses it to find a + // ParserFactory, + // and thus fails if it's not set to the webapp classloader. final ClassLoader old = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(this.classloader); - + // Inlitialize the actual servlet this.initServlet(); } finally { Thread.currentThread().setContextClassLoader(old); } - - } - - /** - * Initialize the wrapped servlet. Subclasses (see {@link BootstrapServlet} change the - * ServletConfig given to the servlet. - * - * @throws ServletException - */ - protected void initServlet() throws ServletException { - this.servlet.init(this.getServletConfig()); - } - - /** - * Get the web application context directory. - * - * @return the context dir - * @throws ServletException - */ - protected File getContextDir() throws ServletException { - String result = getServletContext().getRealPath("/"); - if (result == null) { - throw new ServletException(this.getClass().getName() + " cannot run in an undeployed WAR file"); - } - return new File(result); - } - - /** - * Get the classloader that will be used to create the actual servlet. Its classpath is defined - * by the WEB-INF/classes and WEB-INF/lib directories in the context dir. - */ - protected ClassLoader getClassLoader(File contextDir) throws ServletException { - List urlList = new ArrayList(); - - try { - File classDir = new File(contextDir + "/WEB-INF/classes"); - if (classDir.exists()) { - if (!classDir.isDirectory()) { - throw new ServletException(classDir + " exists but is not a directory"); - } - - URL classURL = classDir.toURL(); - log("Adding class directory " + classURL); - urlList.add(classURL); - - } - - // List all .jar and .zip - File libDir = new File(contextDir + "/WEB-INF/lib"); - File[] libraries = libDir.listFiles(new JarFileFilter()); - for (int i = 0; i < libraries.length; i++) { - URL lib = libraries[i].toURL(); - log("Adding class library " + lib); - urlList.add(lib); - } - } catch (MalformedURLException mue) { - throw new ServletException(mue); - } - - URL[] urls = (URL[])urlList.toArray(new URL[urlList.size()]); - - return ParanoidClassLoader.newInstance(urls, this.getClass().getClassLoader()); - } - + } + /** - * Get the classloader that will be used to create the actual servlet. Its classpath is defined - * by an external file. + * Initialize the wrapped servlet. Subclasses (see {@link BootstrapServlet} + * change the ServletConfig given to the servlet. + * + * @throws ServletException */ - protected ClassLoader getClassLoader(String externalClasspath, File contextDir) - throws ServletException { + protected void initServlet() throws ServletException { + this.servlet.init(this.getServletConfig()); + } + + /** + * Get the web application context directory. + * + * @return the context dir + * @throws ServletException + */ + protected File getContextDir() throws ServletException { + String result = getServletContext().getRealPath("/"); + if (result == null) { + throw new ServletException(this.getClass().getName() + " cannot run in an undeployed WAR file"); + } + return new File(result); + } + + protected URL[] getClassPath(final File contextDir) throws ServletException { + List urlList = new ArrayList(); + + try { + File classDir = new File(contextDir + "/WEB-INF/classes"); + if (classDir.exists()) { + if (!classDir.isDirectory()) { + throw new ServletException(classDir + " exists but is not a directory"); + } + + URL classURL = classDir.toURL(); + log("Adding class directory " + classURL); + urlList.add(classURL); + + } + + // List all .jar and .zip + File libDir = new File(contextDir + "/WEB-INF/lib"); + File[] libraries = libDir.listFiles(new JarFileFilter()); + + for (int i = 0; i < libraries.length; i++) { + URL lib = libraries[i].toURL(); + log("Adding class library " + lib); + urlList.add(lib); + } + } catch (MalformedURLException mue) { + throw new ServletException(mue); + } + + URL[] urls = (URL[]) urlList.toArray(new URL[urlList.size()]); + + return urls; + } + + protected URL[] getClassPath(final String externalClasspath, final File contextDir) throws ServletException { final List urlList = new ArrayList(); File file = new File(externalClasspath); if (!file.isAbsolute()) { - file = new File(contextDir,externalClasspath); + file = new File(contextDir, externalClasspath); } log("Adding classpath from " + file); try { FileReader fileReader = new FileReader(file); LineNumberReader lineReader = new LineNumberReader(fileReader); - + String line; do { - line = lineReader.readLine(); - if ( line != null ) { + line = lineReader.readLine(); + if (line != null) { if (line.startsWith("class-dir:")) { line = line.substring("class-dir:".length()).trim(); - if( line.startsWith(CONTEXT_PREFIX)) { + if (line.startsWith(CONTEXT_PREFIX)) { line = contextDir + line.substring(CONTEXT_PREFIX.length()); } URL url = new File(line).toURL(); log("Adding class directory " + url); urlList.add(url); - + } else if (line.startsWith("lib-dir:")) { line = line.substring("lib-dir:".length()).trim(); - if( line.startsWith(CONTEXT_PREFIX)) { - line = contextDir + line.substring(CONTEXT_PREFIX.length()); - } + if (line.startsWith(CONTEXT_PREFIX)) { + line = contextDir + line.substring(CONTEXT_PREFIX.length()); + } File dir = new File(line); File[] libraries = dir.listFiles(new JarFileFilter()); log("Adding " + libraries.length + " libraries from " + dir.toURL()); @@ -222,74 +227,121 @@ URL url = libraries[i].toURL(); urlList.add(url); } - } else if(line.startsWith("#")) { + } else if (line.startsWith("#")) { // skip it (consider it as comment) } else { // Consider it as a URL final URL lib; - if( line.startsWith(CONTEXT_PREFIX)) { - line = FILE_PREFIX + "/" + contextDir + - line.substring(CONTEXT_PREFIX.length()).trim(); - } - if ( line.indexOf(':') == -1) { - File entry = new File(line); - lib = entry.toURL(); + if (line.startsWith(CONTEXT_PREFIX)) { + line = FILE_PREFIX + "/" + contextDir + line.substring(CONTEXT_PREFIX.length()).trim(); + } + if (line.indexOf(':') == -1) { + File entry = new File(line); + lib = entry.toURL(); } else { lib = new URL(line); - } + } log("Adding class URL " + lib); urlList.add(lib); } } - } while ( line != null ); + } while (line != null); lineReader.close(); } catch (IOException io) { throw new ServletException(io); } - - URL[] urls = (URL[])urlList.toArray(new URL[urlList.size()]); - - return ParanoidClassLoader.newInstance(urls, this.getClass().getClassLoader()); + + URL[] urls = (URL[]) urlList.toArray(new URL[urlList.size()]); + + return urls; + } + + protected ClassLoader createClassLoader(final String className, final URL[] classPath) throws ServletException { + if (className != null) { + try { + final Class classLoaderClass = Class.forName(className); + final Class[] parameterClasses = new Class[] { ClassLoader.class }; + final Constructor constructor = classLoaderClass.getConstructor(parameterClasses); + final Object[] parameters = new Object[] { this.getClass().getClassLoader() }; + final ClassLoader classloader = (ClassLoader) constructor.newInstance(parameters); + return classloader; + } catch (InstantiationException e) { + throw new ServletException("", e); + } catch (IllegalAccessException e) { + throw new ServletException("", e); + } catch (ClassNotFoundException e) { + throw new ServletException("", e); + } catch (SecurityException e) { + throw new ServletException("", e); + } catch (NoSuchMethodException e) { + throw new ServletException("", e); + } catch (IllegalArgumentException e) { + throw new ServletException("", e); + } catch (InvocationTargetException e) { + throw new ServletException("", e); + } + } else { + return ParanoidClassLoader.newInstance(classPath, this.getClass().getClassLoader()); + } + } + + + /** + * Get the classloader that will be used to create the actual servlet. Its + * classpath is defined by the WEB-INF/classes and WEB-INF/lib directories + * in the context dir. + * @deprecated + */ + protected ClassLoader getClassLoader(File contextDir) throws ServletException { + return createClassLoader(null, getClassPath(contextDir)); + } + + /** + * Get the classloader that will be used to create the actual servlet. Its + * classpath is defined by an external file. + * @deprecated + */ + protected ClassLoader getClassLoader(final String externalClasspath, final File contextDir) throws ServletException { + return createClassLoader(null, getClassPath(externalClasspath, contextDir)); } - /** - * Service the request by delegating the call to the real servlet - */ - public void service(ServletRequest request, ServletResponse response) - throws ServletException, IOException { + /** + * Service the request by delegating the call to the real servlet + */ + public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException { final ClassLoader old = Thread.currentThread().getContextClassLoader(); try { - Thread.currentThread().setContextClassLoader(this.classloader); - this.servlet.service(request, response); + Thread.currentThread().setContextClassLoader(this.classloader); + this.servlet.service(request, response); } finally { - Thread.currentThread().setContextClassLoader(old); + Thread.currentThread().setContextClassLoader(old); } - } - - /** - * Destroy the actual servlet - */ - public void destroy() { + } + + /** + * Destroy the actual servlet + */ + public void destroy() { - if ( this.servlet != null ) { + if (this.servlet != null) { final ClassLoader old = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(this.classloader); this.servlet.destroy(); } finally { - Thread.currentThread().setContextClassLoader(old); + Thread.currentThread().setContextClassLoader(old); } } - super.destroy(); - } - + super.destroy(); + } + private class JarFileFilter implements FilenameFilter { public boolean accept(File dir, String name) { return name.endsWith(".zip") || name.endsWith(".jar"); } } - + } Modified: cocoon/branches/BRANCH_2_1_X/status.xml Url: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/status.xml?view=diff&rev=109661&p1=cocoon/branches/BRANCH_2_1_X/status.xml&r1=109660&p2=cocoon/branches/BRANCH_2_1_X/status.xml&r2=109661 ============================================================================== --- cocoon/branches/BRANCH_2_1_X/status.xml (original) +++ cocoon/branches/BRANCH_2_1_X/status.xml Fri Dec 3 02:09:30 2004 @@ -202,6 +202,9 @@ + + paranoid: make the classloader implementation configurable + typo on the date-selector doc.