sylvain 2002/06/11 06:45:37 Modified: . Tag: cocoon_2_0_3_branch changes.xml src/java/org/apache/cocoon/servlet Tag: cocoon_2_0_3_branch CocoonServlet.java ParanoidCocoonServlet.java src/webapp/WEB-INF Tag: cocoon_2_0_3_branch web.xml Log: Solve some classloader issues Revision Changes Path No revision No revision 1.138.2.19 +6 -1 xml-cocoon2/changes.xml Index: changes.xml =================================================================== RCS file: /home/cvs/xml-cocoon2/changes.xml,v retrieving revision 1.138.2.18 retrieving revision 1.138.2.19 diff -u -r1.138.2.18 -r1.138.2.19 --- changes.xml 6 Jun 2002 08:47:40 -0000 1.138.2.18 +++ changes.xml 11 Jun 2002 13:45:36 -0000 1.138.2.19 @@ -39,6 +39,11 @@ <release version="@version@" date="@date@"> + <action dev="SW" type="update"> + CocoonServlet no longer builds its own classloader. Also, it no more sets the thread's context + classloader unless the "init-classloader" parameter is true. To have Cocoon use its own classloader, + use the ParanoidCocoonServlet. + </action> <action dev="VG" type="fix" fixes-bug="9539" due-to="Stuart Roebuck" due-to-email="[EMAIL PROTECTED]"> ResourceReader incorrectly advertised byte ranges support. </action> No revision No revision 1.19.2.5 +112 -146 xml-cocoon2/src/java/org/apache/cocoon/servlet/CocoonServlet.java Index: CocoonServlet.java =================================================================== RCS file: /home/cvs/xml-cocoon2/src/java/org/apache/cocoon/servlet/CocoonServlet.java,v retrieving revision 1.19.2.4 retrieving revision 1.19.2.5 diff -u -r1.19.2.4 -r1.19.2.5 --- CocoonServlet.java 6 Jun 2002 20:49:00 -0000 1.19.2.4 +++ CocoonServlet.java 11 Jun 2002 13:45:37 -0000 1.19.2.5 @@ -68,7 +68,6 @@ import org.apache.cocoon.ResourceNotFoundException; import org.apache.cocoon.ConnectionResetException; import org.apache.cocoon.Cocoon; -import org.apache.cocoon.components.classloader.RepositoryClassLoader; import org.apache.cocoon.environment.Environment; import org.apache.cocoon.environment.http.HttpContext; import org.apache.cocoon.environment.http.HttpEnvironment; @@ -161,14 +160,16 @@ private String defaultFormEncoding; protected ServletContext servletContext; - protected RepositoryClassLoader classLoader; + + /** The classloader that will be set as the context classloader if init-classloader is true */ + protected ClassLoader classLoader = this.getClass().getClassLoader(); + protected boolean initClassLoader = false; private String parentComponentManagerClass; private String requestFactoryClass; protected String forceLoadParameter; protected String forceSystemProperty; - private boolean addClassDirs; /** * If true or not set, this class will try to catch and handle all Cocoon exceptions. @@ -204,16 +205,22 @@ throws ServletException { super.init(conf); - - // Force context classloader so that JAXP can work correctly - // (see javax.xml.parsers.FactoryFinder.findClassLoader()) - try { - Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); - } catch (Exception e){} + + final String initClassLoaderParam = conf.getInitParameter("init-classloader"); + this.initClassLoader = "true".equalsIgnoreCase(initClassLoaderParam) || + "yes".equalsIgnoreCase(initClassLoaderParam); + + if (this.initClassLoader) { + // Force context classloader so that JAXP can work correctly + // (see javax.xml.parsers.FactoryFinder.findClassLoader()) + try { + Thread.currentThread().setContextClassLoader(this.classLoader); + } catch (Exception e){} + } String value; - // FIXME (VG): We shouldn't have to specify these. Need to override + // FIXME (VG): We shouldn't have to specify these. Need to override // jaxp implementation of weblogic before initializing logger. // This piece of code is also required in the Cocoon class. value = System.getProperty("javax.xml.parsers.SAXParserFactory"); @@ -302,14 +309,6 @@ this.forceSystemProperty = conf.getInitParameter("force-property"); - value = conf.getInitParameter("init-classloader"); - this.addClassDirs = "true".equalsIgnoreCase(value) || "yes".equalsIgnoreCase(value); - if (value == null) { - if (log.isDebugEnabled()) { - log.debug("init-classloader was not set - defaulting to false"); - } - } - // add work directory if ((workDirParam != null) && (!workDirParam.trim().equals(""))) { if (log.isDebugEnabled()) { @@ -425,14 +424,14 @@ } } - value = conf.getInitParameter("manage-exceptions"); + value = conf.getInitParameter("manage-exceptions"); this.manageExceptions = (value == null || value.equalsIgnoreCase("yes") || value.equalsIgnoreCase("true")); if (value == null) { if (log.isDebugEnabled()) { log.debug("Parameter manageExceptions was not set - defaulting to true."); } } - + this.createCocoon(); } @@ -441,9 +440,12 @@ */ public void destroy() { - try { - Thread.currentThread().setContextClassLoader(classLoader); - } catch (Exception e){} + if (this.initClassLoader) + { + try { + Thread.currentThread().setContextClassLoader(this.classLoader); + } catch (Exception e){} + } if (this.cocoon != null) { @@ -453,13 +455,22 @@ this.disposeCocoon(); } } + + /** + * Adds an URL to the classloader. Does nothing here, but is + * overriden in {@link ParanoidCocoonServlet}. + */ + protected void addClassLoaderURL(URL URL) { + // Nothing + } - /** - * get the classloader to use for Cocoon instantiation - */ - protected RepositoryClassLoader buildInitClassLoader() { - return new RepositoryClassLoader(new URL[] {}, this.getClass().getClassLoader()); - } + /** + * Adds a directory to the classloader. Does nothing here, but is + * overriden in {@link ParanoidCocoonServlet}. + */ + protected void addClassLoaderDirectory(String dir) { + // Nothing + } /** * This builds the important ClassPath used by this Servlet. It @@ -494,15 +505,7 @@ if (classDir != null) { buildClassPath.append(classDir); - if (this.addClassDirs) { - try { - classLoader.addDirectory(new File(classDir)); - } catch (Exception e) { - if (log.isDebugEnabled()) { - log.debug("Could not add directory" + classDir, e); - } - } - } + addClassLoaderDirectory(classDir); } } else { // New(ish) method for war'd deployments @@ -532,15 +535,7 @@ if (classDirURL != null) { buildClassPath.append(classDirURL.toExternalForm()); - if (this.addClassDirs) { - try { - classLoader.addURL(classDirURL); - } catch (Exception e) { - if (log.isDebugEnabled()) { - log.debug("Could not add directory " + classDirURL, e); - } - } - } + addClassLoaderURL(classDirURL); } } @@ -553,18 +548,10 @@ File[] libraries = root.listFiles(); Arrays.sort(libraries); for (int i = 0; i < libraries.length; i++) { - buildClassPath.append(File.pathSeparatorChar) - .append(IOUtils.getFullFilename(libraries[i])); + String fullName = IOUtils.getFullFilename(libraries[i]); + buildClassPath.append(File.pathSeparatorChar).append(fullName); - if (this.addClassDirs) { - try { - classLoader.addDirectory(libraries[i]); - } catch (Exception e) { - if (log.isDebugEnabled()) { - log.debug("Could not add file" + IOUtils.getFullFilename(libraries[i])); - } - } - } + addClassLoaderDirectory(fullName); } } @@ -683,15 +670,7 @@ } sb.append(s); - if (this.addClassDirs) { - try { - classLoader.addDirectory(s.toString()); - } catch (Exception e) { - if (log.isDebugEnabled()) { - log.debug("Could not add " + s.toString()); - } - } - } + addClassLoaderDirectory(s); } else { if (s.indexOf("${") != -1) { String path = StringUtils.replaceToken(s); @@ -699,15 +678,7 @@ if (log.isDebugEnabled()) { log.debug ("extraClassPath is not absolute replacing using token: [" + s + "] : " + path); } - if (this.addClassDirs) { - try { - classLoader.addDirectory(path); - } catch (Exception e) { - if (log.isDebugEnabled()) { - log.debug("Could not add " + path); - } - } - } + addClassLoaderDirectory(path); } else { String path = null; if (this.servletContextPath != null) { @@ -722,15 +693,7 @@ } } sb.append(path); - if (this.addClassDirs) { - try { - classLoader.addDirectory(path); - } catch (Exception e) { - if (log.isDebugEnabled()) { - log.debug("Could not add " + path); - } - } - } + addClassLoaderDirectory(path); } } } @@ -845,7 +808,7 @@ log.error(msg, mue); throw new ServletException(msg, mue); } - + if (result == null) { String msg = "Init parameter 'configuration' doesn't name an existing resource : " + usedFileName; log.error(msg); @@ -935,9 +898,11 @@ /* HACK for reducing class loader problems. */ /* example: xalan extensions fail if someone adds xalan jars in tomcat3.2.1/lib */ - try { - Thread.currentThread().setContextClassLoader(classLoader); - } catch (Exception e){} + if (this.initClassLoader) { + try { + Thread.currentThread().setContextClassLoader(this.classLoader); + } catch (Exception e){} + } // This is more scalable long start = System.currentTimeMillis(); @@ -953,10 +918,10 @@ // Check if cocoon was initialized if (this.cocoon == null) { - if(manageExceptions){ + if(manageExceptions){ res.reset(); - SimpleNotifyingBean n= new SimpleNotifyingBean(this); + SimpleNotifyingBean n = new SimpleNotifyingBean(this); n.setType("fatal"); n.setTitle("Internal servlet error"); n.setSource("Cocoon servlet"); @@ -970,11 +935,11 @@ } else{ res.sendError - (HttpServletResponse.SC_INTERNAL_SERVER_ERROR, + (HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "The Cocoon engine said it failed to process the request for an unknown reason." ); res.flushBuffer(); return; - } + } } @@ -1036,51 +1001,51 @@ } else { //NKB Should not get here? log.fatalError("The Cocoon engine said it failed to process the request for an unknown reason."); - - if(manageExceptions){ - res.reset(); - SimpleNotifyingBean n = new SimpleNotifyingBean(this); - n.setType("error"); + if(manageExceptions){ + res.reset(); + + SimpleNotifyingBean n = new SimpleNotifyingBean(this); + n.setType("error"); n.setTitle("Cocoon confusion"); - n.setSource("Cocoon servlet"); + n.setSource("Cocoon servlet"); n.setMessage("Cocoon engine failed in process."); n.setDescription("The Cocoon engine said it failed to process the request for an unknown reason."); - n.addExtraDescription("request-uri", request.getRequestURI()); - n.addExtraDescription("path-info", uri); - + n.addExtraDescription("request-uri", request.getRequestURI()); + n.addExtraDescription("path-info", uri); + res.setContentType("text/html"); res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); Notifier.notify(n, res.getOutputStream(), "text/html"); } else{ res.sendError - (HttpServletResponse.SC_INTERNAL_SERVER_ERROR, + (HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "The Cocoon engine said it failed to process the request for an unknown reason." ); res.flushBuffer(); - return; + return; } - + } } catch (ResourceNotFoundException rse) { if (log.isWarnEnabled()) { log.warn("The resource was not found", rse); } - if(manageExceptions){ - res.reset(); + if(manageExceptions){ + res.reset(); + + SimpleNotifyingBean n = new SimpleNotifyingBean(this); + n.setType("resource-not-found"); + n.setTitle("Resource not found"); + n.setSource("Cocoon servlet"); + n.setMessage("Resource not found"); + n.setDescription("The requested URI \"" + + request.getRequestURI() + + "\" was not found."); + n.addExtraDescription("request-uri", request.getRequestURI()); + n.addExtraDescription("path-info", uri); - SimpleNotifyingBean n = new SimpleNotifyingBean(this); - n.setType("resource-not-found"); - n.setTitle("Resource not found"); - n.setSource("Cocoon servlet"); - n.setMessage("Resource not found"); - n.setDescription("The requested URI \"" - + request.getRequestURI() - + "\" was not found."); - n.addExtraDescription("request-uri", request.getRequestURI()); - n.addExtraDescription("path-info", uri); - res.setContentType("text/html"); res.setStatus(HttpServletResponse.SC_NOT_FOUND); Notifier.notify(n, res.getOutputStream(), "text/html"); @@ -1089,7 +1054,7 @@ res.sendError (HttpServletResponse.SC_NOT_FOUND, "Resource not found." ); res.flushBuffer(); - return; + return; } } catch (ConnectionResetException cre) { @@ -1104,19 +1069,19 @@ if (log.isErrorEnabled()) { log.error("Problem with Cocoon servlet", e); } - - if(manageExceptions){ - res.reset(); - - HashMap extraDescriptions = new HashMap(3); - extraDescriptions.put("request-uri", request.getRequestURI()); - extraDescriptions.put("path-info", uri); - StringWriter writer = new StringWriter(); - e.printStackTrace(new PrintWriter(writer)); - extraDescriptions.put("stack-trace",writer.toString()); - Notifying n=new DefaultNotifyingBuilder().build( - this, e, "fatal","Internal server error","Cocoon servlet",null,null,extraDescriptions); + if(manageExceptions){ + res.reset(); + + HashMap extraDescriptions = new HashMap(3); + extraDescriptions.put("request-uri", request.getRequestURI()); + extraDescriptions.put("path-info", uri); + StringWriter writer = new StringWriter(); + e.printStackTrace(new PrintWriter(writer)); + extraDescriptions.put("stack-trace",writer.toString()); + + Notifying n=new DefaultNotifyingBuilder().build( + this, e, "fatal","Internal server error","Cocoon servlet",null,null,extraDescriptions); res.setContentType("text/html"); res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); @@ -1124,11 +1089,11 @@ } else{ res.sendError - (HttpServletResponse.SC_INTERNAL_SERVER_ERROR, + (HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Internal server error."); res.flushBuffer(); - return; - } + return; + } } long end = System.currentTimeMillis(); @@ -1157,14 +1122,14 @@ } finally { if (ctxMap != null) ctxMap.clear(); try{ - ServletOutputStream out = res.getOutputStream(); - out.flush(); - out.close(); - } + ServletOutputStream out = res.getOutputStream(); + out.flush(); + out.close(); + } catch(Exception e){ - log.error("Cocoon servlet threw an Exception while trying to close stream.", e); + log.error("Cocoon servlet threw an Exception while trying to close stream.", e); } - + } } @@ -1241,13 +1206,14 @@ */ private synchronized void createCocoon() throws ServletException { - this.classLoader = this.buildInitClassLoader(); /* HACK for reducing class loader problems. */ /* example: xalan extensions fail if someone adds xalan jars in tomcat3.2.1/lib */ - try { - Thread.currentThread().setContextClassLoader(this.classLoader); - } catch (Exception e){} + if (this.initClassLoader) { + try { + Thread.currentThread().setContextClassLoader(this.classLoader); + } catch (Exception e){} + } this.updateEnvironment(); this.forceLoad(); @@ -1319,7 +1285,7 @@ * Gets the current cocoon object. Reload cocoon if configuration * changed or we are reloading. * - * @returns Cocoon + * @return Cocoon */ private Cocoon getCocoon(final String pathInfo, final String reloadParam) throws ServletException { 1.5.2.1 +42 -13 xml-cocoon2/src/java/org/apache/cocoon/servlet/ParanoidCocoonServlet.java Index: ParanoidCocoonServlet.java =================================================================== RCS file: /home/cvs/xml-cocoon2/src/java/org/apache/cocoon/servlet/ParanoidCocoonServlet.java,v retrieving revision 1.5 retrieving revision 1.5.2.1 diff -u -r1.5 -r1.5.2.1 --- ParanoidCocoonServlet.java 22 Feb 2002 07:03:55 -0000 1.5 +++ ParanoidCocoonServlet.java 11 Jun 2002 13:45:37 -0000 1.5.2.1 @@ -50,10 +50,12 @@ */ package org.apache.cocoon.servlet; +import org.apache.cocoon.components.classloader.RepositoryClassLoader; import org.apache.cocoon.util.IOUtils; import javax.servlet.ServletException; import java.io.File; +import java.net.URL; /** * This is the entry point for Cocoon execution as an HTTP Servlet. @@ -69,6 +71,15 @@ public class ParanoidCocoonServlet extends CocoonServlet { + protected RepositoryClassLoader repositoryLoader; + + public ParanoidCocoonServlet() { + super(); + // Override the parent class classloader + this.repositoryLoader = new RepositoryClassLoader(new URL[] {}, this.getClass().getClassLoader()); + super.classLoader = this.repositoryLoader; + } + /** * This builds the important ClassPath used by this Servlet. It * does so in a Servlet Engine neutral way. It uses the @@ -106,11 +117,7 @@ root = new File(this.servletContext.getRealPath("/WEB-INF/lib")); } - try { - classLoader.addDirectory(new File(classDir)); - } catch (Exception e) { - log.debug("Could not add directory" + classDir, e); - } + addClassLoaderDirectory(classDir); buildClassPath.append(classDir); @@ -118,14 +125,10 @@ File[] libraries = root.listFiles(); for (int i = 0; i < libraries.length; i++) { - buildClassPath.append(File.pathSeparatorChar) - .append(IOUtils.getFullFilename(libraries[i])); + String fullName = IOUtils.getFullFilename(libraries[i]); + buildClassPath.append(File.pathSeparatorChar).append(fullName); - try { - classLoader.addDirectory(libraries[i]); - } catch (Exception e) { - log.debug("Could not add file" + IOUtils.getFullFilename(libraries[i])); - } + addClassLoaderDirectory(fullName); } } @@ -137,5 +140,31 @@ return buildClassPath.toString(); } + + /** + * Adds an URL to the classloader. + */ + protected void addClassLoaderURL(URL url) { + try { + this.repositoryLoader.addURL(url); + } catch (Exception e) { + if (log.isDebugEnabled()) { + log.debug("Could not add URL" + url, e); + } + } + } + + /** + * Adds a directory to the classloader. + */ + protected void addClassLoaderDirectory(String dir) { + try { + this.repositoryLoader.addDirectory(new File(dir)); + } catch (Exception e) { + if (log.isDebugEnabled()) { + log.debug("Could not add directory" + dir, e); + } + } + } } No revision No revision 1.8.2.3 +3 -4 xml-cocoon2/src/webapp/WEB-INF/web.xml Index: web.xml =================================================================== RCS file: /home/cvs/xml-cocoon2/src/webapp/WEB-INF/web.xml,v retrieving revision 1.8.2.2 retrieving revision 1.8.2.3 diff -u -r1.8.2.2 -r1.8.2.3 --- web.xml 6 Jun 2002 08:47:40 -0000 1.8.2.2 +++ web.xml 11 Jun 2002 13:45:37 -0000 1.8.2.3 @@ -38,10 +38,9 @@ </init-param> <!-- - This parameter tells cocoon to load all the required libraries into - it's own classloader instead of trusting the Servlet Vendor's - classloader. If you experience strange classloader issues, - try setting this parameter to "true". + This parameter tells cocoon to set the thread's context classloader to + its own classloader. If you experience strange classloader issues, + try setting this parameter to "true" or using ParanoidCocoonServlet. --> <init-param> <param-name>init-classloader</param-name>
---------------------------------------------------------------------- In case of troubles, e-mail: [EMAIL PROTECTED] To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]