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 <code>ParanoidClassLoader</code> reverses the search order for
- * classes. It checks this classloader before it checks its parent.
- *
- * @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
- * @author <a href="http://www.apache.org/~sylvain/">Sylvain Wallez</a>
- * @version CVS $Id: ParanoidClassLoader.java,v 1.2 2004/03/05 13:02:02 bdelacretaz Exp $
+ * The <code>ParanoidClassLoader</code> reverses the search order for classes.
+ * It checks this classloader before it checks its parent.
+ *
+ * @author <a href="mailto:bloritsch@apache.org">Berin Loritsch </a>
+ * @author <a href="http://www.apache.org/~sylvain/">Sylvain Wallez </a>
+ * @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
- * <code>URL</code>s.
+ * Alternate constructor to define a parent and initial <code>URL</code>
+ * s.
*/
public ParanoidClassLoader(final URL[] urls, final ClassLoader parent) {
this(urls, parent, null);
}
/**
- * Alternate constructor to define a parent, initial
- * <code>URL</code>s, and a default
- * <code>URLStreamHandlerFactory</code>.
+ * Alternate constructor to define a parent, initial <code>URL</code>s,
+ * and a default <code>URLStreamHandlerFactory</code>.
*/
public ParanoidClassLoader(final URL[] urls, final ClassLoader parent, final URLStreamHandlerFactory
factory) {
super(urls, parent, factory);
}
/**
- * Extends <code>URLClassLoader</code>'s initialization methods so
- * we return a <code>ParanoidClassLoad</code> instead.
+ * Extends <code>URLClassLoader</code>'s initialization methods so we
+ * return a <code>ParanoidClassLoad</code> instead.
*/
public static final URLClassLoader newInstance(final URL[] urls) {
return new ParanoidClassLoader(urls);
}
/**
- * Extends <code>URLClassLoader</code>'s initialization methods so
- * we return a <code>ParanoidClassLoad</code> instead.
+ * Extends <code>URLClassLoader</code>'s initialization methods so we
+ * return a <code>ParanoidClassLoad</code> instead.
*/
public static final URLClassLoader newInstance(final URL[] urls, final ClassLoader parent)
{
return new ParanoidClassLoader(urls, parent);
@@ -98,21 +98,19 @@
* @return the resulting <code>Class</code> 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 <code>ClassLoader</class>. 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.
* <p>
- * This servlet propagates all initialisation parameters to the sandboxed servlet, and
- * accepts the parameters <code>servlet-class</code> and <code>paranoid-classpath</code>.
+ * This servlet propagates all initialisation parameters to the sandboxed
+ * servlet, and accepts the parameters <code>servlet-class</code> and
+ * <code>paranoid-classpath</code>.
* <ul>
- * <li><code>servlet-class</code> defines the sandboxed servlet class,
the default is
- * {@link CocoonServlet}
- * <li><code>paranoid-classpath</code> expects the name of a text file
that can contain
- * lines begining with <code>class-dir:<code> (directory containing classes),
+ * <li><code>servlet-class</code> defines the sandboxed servlet class,
the
+ * default is {@link CocoonServlet}
+ * <li><code>paranoid-classpath</code> expects the name of a text file
that
+ * can contain lines begining with
+ * <code>class-dir:<code> (directory containing classes),
* <code>lib-dir:<code> (directory containing JAR or ZIP libraries) and
<code>#</code>
* (for comments). <br/>
* All other lines are considered as URLs.
@@ -55,166 +59,167 @@
*
* @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
* @author <a href="http://www.apache.org/~sylvain/">Sylvain Wallez</a>
+ * @author <a href="mailto:tcurdt@apache.org">Torsten Curdt</a>
* @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
- * <code>ServletConfig</code> 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 <code>ServletConfig</code> 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 @@
<changes>
<release version="@version@" date="@date@">
+ <action dev="TC" type="add">
+ paranoid: make the classloader implementation configurable
+ </action>
<action dev="AG" type="fix" fixes-bug="32408" due-to="Juan Jose Pablos" due-to-email="cheche@che-che.com">
typo on the date-selector doc.
</action>
|