You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by sy...@apache.org on 2003/06/03 15:25:43 UTC

cvs commit: cocoon-2.1/src/java/org/apache/cocoon/servlet BootstrapServlet.java CocoonServlet.java ParanoidClassLoader.java ParanoidCocoonServlet.java

sylvain     2003/06/03 06:25:43

  Modified:    src/java/org/apache/cocoon/servlet BootstrapServlet.java
                        CocoonServlet.java ParanoidClassLoader.java
                        ParanoidCocoonServlet.java
  Log:
  ParanoidCocoonServlet is now really paranoid
  
  Revision  Changes    Path
  1.2       +53 -139   cocoon-2.1/src/java/org/apache/cocoon/servlet/BootstrapServlet.java
  
  Index: BootstrapServlet.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/java/org/apache/cocoon/servlet/BootstrapServlet.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- BootstrapServlet.java	9 Mar 2003 00:09:37 -0000	1.1
  +++ BootstrapServlet.java	3 Jun 2003 13:25:42 -0000	1.2
  @@ -50,19 +50,19 @@
   */
   package org.apache.cocoon.servlet;
   
  -import javax.servlet.*;
  -import javax.servlet.http.HttpServlet;
  -
   import java.io.File;
  -import java.io.IOException;
   import java.io.InputStream;
   import java.net.MalformedURLException;
   import java.net.URL;
  -import java.util.ArrayList;
   import java.util.Enumeration;
  -import java.util.List;
   import java.util.Set;
   
  +import javax.servlet.RequestDispatcher;
  +import javax.servlet.Servlet;
  +import javax.servlet.ServletConfig;
  +import javax.servlet.ServletContext;
  +import javax.servlet.ServletException;
  +
   /**
    * A bootstrap servlet to allow Cocoon to run in servlet engines that aren't fully
    * compliant with the servlet 2.2 spec.
  @@ -81,141 +81,55 @@
    * @version CVS $Id$
    */
   
  -public class BootstrapServlet extends HttpServlet {
  -    
  -    /**
  -     * The name of the actual servlet class.
  -     */
  -    public static final String SERVLET_CLASS = "org.apache.cocoon.servlet.CocoonServlet";
  +public class BootstrapServlet extends ParanoidCocoonServlet {
       
  -    protected Servlet servlet;
  +    private File contextDir;
       
  -    protected ClassLoader classloader;
  -    
  -    protected ServletContext context;
  -    
  -    public void init(ServletConfig config) throws ServletException {
  -        this.context = config.getServletContext();
  -        
  -        this.context.log("getRealPath(\"/\") = " + context.getRealPath("/"));
  -
  -        String contextDirParam = config.getInitParameter("context-directory");
  -        if (contextDirParam == null) {
  -            // Check old form, not consistent with other parameter names
  -            contextDirParam = config.getInitParameter("context-dir");
  -            if (contextDirParam == null) {
  -                String msg = "The 'context-directory' parameter must be set to the root of the servlet context";
  -                this.context.log(msg);
  -                throw new ServletException(msg);
  -            } else {
  -                this.context.log("Parameter 'context-dir' is deprecated - use 'context-directory'");
  -            }
  -        }
  -        
  -        // Ensure context dir doesn't end with a "/" (servlet spec says that paths for
  -        // getResource() should start by a "/")
  -        if (contextDirParam.endsWith("/")) {
  -            contextDirParam = contextDirParam.substring(0, contextDirParam.length() - 1);
  -        }
  -        
  -        // Ensure context dir exists and is a directory
  -        File contextDir = new File(contextDirParam);
  -        if (!contextDir.exists()) {
  -            String msg = "Context dir '" + contextDir + "' doesn't exist";
  -            this.context.log(msg);
  -            throw new ServletException(msg);
  -        }
  +	protected File getContextDir() throws ServletException {
  +		
  +		ServletContext context = getServletContext();
  +		ServletConfig config = getServletConfig();
  +		
  +		log("getRealPath(\"/\") = " + context.getRealPath("/"));
  +
  +		String contextDirParam = config.getInitParameter("context-directory");
  +		
  +		if (contextDirParam == null) {
  +				throw new ServletException("The 'context-directory' parameter must be set to the root of the servlet context");
  +		}
  +        
  +		// Ensure context dir doesn't end with a "/" (servlet spec says that paths for
  +		// getResource() should start by a "/")
  +		if (contextDirParam.endsWith("/")) {
  +			contextDirParam = contextDirParam.substring(0, contextDirParam.length() - 1);
  +		}
  +        
  +		// Ensure context dir exists and is a directory
  +		this.contextDir = new File(contextDirParam);
  +		if (!this.contextDir.exists()) {
  +			String msg = "Context dir '" + this.contextDir + "' doesn't exist";
  +			log(msg);
  +			throw new ServletException(msg);
  +		}
  +
  +		if (!this.contextDir.isDirectory()) {
  +			String msg = "Context dir '" + this.contextDir + "' should be a directory";
  +			log(msg);
  +			throw new ServletException(msg);
  +		}
  +        
  +		context.log("Context dir set to " + this.contextDir);
  +		
  +		return this.contextDir;
  +	}
   
  -        if (!contextDir.isDirectory()) {
  -            String msg = "Context dir '" + contextDir + "' should be a directory";
  -            this.context.log(msg);
  -            throw new ServletException(msg);
  -        }
  -        
  -        context.log("Context dir set to " + contextDir);
   
  -        this.classloader = getClassLoader(contextDirParam);
  -        
  -        try {
  -            Class servletClass = this.classloader.loadClass(SERVLET_CLASS);
  -            
  -            this.servlet = (Servlet)servletClass.newInstance();
  -        } catch(Exception e) {
  -            context.log("Cannot load servlet", e);
  -            throw new ServletException(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.
  -        Thread.currentThread().setContextClassLoader(this.classloader);
  -        
  -        ServletContext newContext = new ContextWrapper(context, contextDirParam);
  -        ServletConfig newConfig = new ConfigWrapper(config, newContext);
  +    protected void initServlet(Servlet servlet) throws ServletException {
           
  -        super.init(newConfig);
  +        ServletContext newContext = new ContextWrapper(getServletContext(), this.contextDir);
  +        ServletConfig newConfig = new ConfigWrapper(getServletConfig(), newContext);
           
  -        // Inlitialize the actual servlet
  -        this.servlet.init(newConfig);
  -        
  -    }
  -    
  -    /**
  -     * Get the classloader that will be used to create the actual servlet.
  -     */
  -    protected ClassLoader getClassLoader(String contextDirParam) throws ServletException {
  -        List urlList = new ArrayList();
  -        
  -        try {
  -            File classDir = new File(contextDirParam + "/WEB-INF/classes");
  -            if (classDir.exists()) {
  -                if (!classDir.isDirectory()) {
  -                    String msg = classDir + " exists but is not a directory";
  -                    this.context.log(msg);
  -                    throw new ServletException(msg);
  -                }
  -            
  -                URL classURL = classDir.toURL();
  -                context.log("Adding class directory " + classURL);
  -                urlList.add(classURL);
  -                
  -            }
  -            
  -            File libDir = new File(contextDirParam + "/WEB-INF/lib");
  -            File[] libraries = libDir.listFiles();
  -
  -            for (int i = 0; i < libraries.length; i++) {
  -                URL lib = libraries[i].toURL();
  -                context.log("Adding class library " + lib);
  -                urlList.add(lib);
  -            }
  -        } catch (MalformedURLException mue) {
  -            context.log("Malformed url", mue);
  -            throw new ServletException(mue);
  -        }
  -        
  -        URL[] urls = (URL[])urlList.toArray(new URL[urlList.size()]);
  -        
  -        return ParanoidClassLoader.newInstance(urls, this.getClass().getClassLoader());
  -    }
  -    
  -    /**
  -     * Service the request by delegating the call to the real servlet
  -     */
  -    public void service(ServletRequest request, ServletResponse response)
  -      throws ServletException, IOException {
  -
  -        Thread.currentThread().setContextClassLoader(this.classloader);
  -        this.servlet.service(request, response);
  -    }
  -    
  -    /**
  -     * Destroy the actual servlet
  -     */
  -    public void destroy() {
  -
  -        super.destroy();
  -        Thread.currentThread().setContextClassLoader(this.classloader);
  -        this.servlet.destroy();
  +        servlet.init(newConfig);        
       }
   
       //-------------------------------------------------------------------------
  @@ -260,13 +174,13 @@
        */
       public static class ContextWrapper implements ServletContext {
           ServletContext context;
  -        String contextRoot;
  +        File contextRoot;
           
           /**
            * Builds a wrapper around an existing context, and handle all
            * resource resolution relatively to <code>contextRoot</code>
            */
  -        public ContextWrapper(ServletContext context, String contextRoot) {
  +        public ContextWrapper(ServletContext context, File contextRoot) {
               this.context = context;
               this.contextRoot = contextRoot;
           }
  @@ -293,7 +207,7 @@
            * returned.
            */
           public URL getResource(String path) throws MalformedURLException {
  -            File file = new File(this.contextRoot + path);
  +            File file = new File(this.contextRoot, path);
               if (file.exists()) {
                   URL result = file.toURL();
                   //this.context.log("getResource(" + path + ") = " + result);
  
  
  
  1.8       +83 -100   cocoon-2.1/src/java/org/apache/cocoon/servlet/CocoonServlet.java
  
  Index: CocoonServlet.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/java/org/apache/cocoon/servlet/CocoonServlet.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- CocoonServlet.java	20 May 2003 12:38:27 -0000	1.7
  +++ CocoonServlet.java	3 Jun 2003 13:25:42 -0000	1.8
  @@ -269,9 +269,12 @@
   
           super.init(conf);
   
  -        final String initClassLoaderParam = conf.getInitParameter("init-classloader");
  -        this.initClassLoader = "true".equalsIgnoreCase(initClassLoaderParam) ||
  -                               "yes".equalsIgnoreCase(initClassLoaderParam);
  +		// Check the init-classloader parameter only if it's not already true.
  +		// This is useful for subclasses of this servlet that override the value
  +		// initially set by this class (i.e. false).
  +		if (!this.initClassLoader) {
  +			this.initClassLoader = getInitParameterAsBoolean("init-classloader", false);
  +		}
   
           if (this.initClassLoader) {
               // Force context classloader so that JAXP can work correctly
  @@ -298,8 +301,8 @@
   
           // first init the work-directory for the logger.
           // this is required if we are running inside a war file!
  -        final String workDirParam = conf.getInitParameter("work-directory");
  -        if ((workDirParam != null) && (!workDirParam.trim().equals(""))) {
  +        final String workDirParam = getInitParameter("work-directory");
  +        if (workDirParam != null) {
               if (this.servletContextPath == null) {
                   // No context path : consider work-directory as absolute
                   this.workDir = new File(workDirParam);
  @@ -361,17 +364,12 @@
               log.debug("URL for Root: " + this.servletContextURL);
           }
   
  -        this.forceLoadParameter = conf.getInitParameter("load-class");
  -        if (conf.getInitParameter("load-class") == null) {
  -            if (log.isDebugEnabled()) {
  -                log.debug("load-class was not set - defaulting to false?");
  -            }
  -        }
  +        this.forceLoadParameter = getInitParameter("load-class", null);
   
  -        this.forceSystemProperty = conf.getInitParameter("force-property");
  +        this.forceSystemProperty = getInitParameter("force-property", null);
   
           // add work directory
  -        if ((workDirParam != null) && (!workDirParam.trim().equals(""))) {
  +        if (workDirParam != null) {
               if (log.isDebugEnabled()) {
                   log.debug("Using work-directory " + this.workDir);
               }
  @@ -383,7 +381,7 @@
           this.appContext.put(Constants.CONTEXT_WORK_DIR, workDir);
   
           final String uploadDirParam = conf.getInitParameter("upload-directory");
  -        if ((uploadDirParam != null) && (!uploadDirParam.trim().equals(""))) {
  +        if (uploadDirParam != null) {
               if (this.servletContextPath == null) {
                   this.uploadDir = new File(uploadDirParam);
               } else {
  @@ -409,33 +407,12 @@
           this.uploadDir.mkdirs();
           this.appContext.put(Constants.CONTEXT_UPLOAD_DIR, this.uploadDir);
   
  -        value = conf.getInitParameter("enable-uploads");
  -        if (value != null) {
  -            this.enableUploads = ("yes".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value));
  -        } else {
  -            this.enableUploads = ENABLE_UPLOADS;
  -            if (log.isDebugEnabled()) {
  -               log.debug("enable-uploads was not set - defaulting to " + this.enableUploads);
  -            }
  -        }
  +        this.enableUploads = getInitParameterAsBoolean("enable-uploads", ENABLE_UPLOADS);
           
  -        value = conf.getInitParameter("autosave-uploads");
  -        if (value != null) {
  -            this.autoSaveUploads = ("yes".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value));
  -        } else {
  -            this.autoSaveUploads = SAVE_UPLOADS_TO_DISK;
  -            if (log.isDebugEnabled()) {
  -               log.debug("autosave-uploads was not set - defaulting to " + this.autoSaveUploads);
  -            }
  -        }
  +        this.autoSaveUploads = getInitParameterAsBoolean("autosave-uploads", SAVE_UPLOADS_TO_DISK);
   
  -        String overwriteParam = conf.getInitParameter("overwrite-uploads");
  +        String overwriteParam = getInitParameter("overwrite-uploads", "rename");
           // accepted values are deny|allow|rename - rename is default.
  -        if (overwriteParam == null) {
  -            if (log.isDebugEnabled()) {
  -               log.debug("overwrite-uploads was not set - defaulting to rename");
  -            }
  -        }
           if ("deny".equalsIgnoreCase(overwriteParam)) {
               this.allowOverwrite = false;
               this.silentlyRename = false;
  @@ -448,14 +425,10 @@
              this.silentlyRename = true;
           }
   
  -        this.maxUploadSize = MAX_UPLOAD_SIZE;
  -        String maxSizeParam = conf.getInitParameter("upload-max-size");
  -        if ((maxSizeParam != null) && (!maxSizeParam.trim().equals(""))) {
  -            this.maxUploadSize = Integer.parseInt(maxSizeParam);
  -        }
  +        this.maxUploadSize = getInitParameterAsInteger("upload-max-size", MAX_UPLOAD_SIZE);
   
           String cacheDirParam = conf.getInitParameter("cache-directory");
  -        if ((cacheDirParam != null) && (!cacheDirParam.trim().equals(""))) {
  +        if (cacheDirParam != null) {
               if (this.servletContextPath == null) {
                   this.cacheDir = new File(cacheDirParam);
               } else {
  @@ -490,15 +463,7 @@
           }
   
           // get allow reload parameter, default is true
  -        value = conf.getInitParameter("allow-reload");
  -        if (value != null) {
  -            this.allowReload = value.equalsIgnoreCase("yes") || value.equalsIgnoreCase("true");
  -        } else {
  -            this.allowReload = ALLOW_RELOAD;
  -            if (log.isDebugEnabled()) {
  -                log.debug("allow-reload was not set - defaulting to " + ALLOW_RELOAD);
  -            }
  -        }
  +		this.allowReload = getInitParameterAsBoolean("allow-reload", ALLOW_RELOAD);
   
           value = conf.getInitParameter("show-time");
           this.showTime = "yes".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value)
  @@ -509,12 +474,8 @@
               }
           }
   
  -        parentComponentManagerClass = conf.getInitParameter("parent-component-manager");
  -        if (parentComponentManagerClass == null) {
  -            if (log.isDebugEnabled()) {
  -                log.debug("parent-component-manager was not set - defaulting to null.");
  -            }
  -        } else {
  +        parentComponentManagerClass = getInitParameter("parent-component-manager", null);
  +        if (parentComponentManagerClass != null) {
               int dividerPos = parentComponentManagerClass.indexOf('/');
               if (dividerPos != -1) {
                   parentComponentManagerInitParam = parentComponentManagerClass.substring(dividerPos + 1);
  @@ -522,38 +483,12 @@
               }
           }
   
  -        this.containerEncoding = conf.getInitParameter("container-encoding");
  -        if (containerEncoding == null) {
  -            this.containerEncoding = "ISO-8859-1";
  -            if (log.isDebugEnabled()) {
  -                log.debug("container-encoding was not set - defaulting to ISO-8859-1.");
  -            }
  -        }
  -
  -        this.defaultFormEncoding = conf.getInitParameter("form-encoding");
  -        if (defaultFormEncoding == null) {
  -            this.defaultFormEncoding = "ISO-8859-1";
  -            if (log.isDebugEnabled()) {
  -                log.debug("form-encoding was not set - defaulting to ISO-8859-1.");
  -            }
  -        }
  +        this.containerEncoding = getInitParameter("container-encoding", "ISO-8859-1");
  +        this.defaultFormEncoding = getInitParameter("form-encoding","ISO-8859-1");
   
  -        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.manageExceptions = getInitParameterAsBoolean("manage-exceptions", true);
   
  -        value = conf.getInitParameter("enable-instrumentation");
  -        this.enableInstrumentation =
  -            "yes".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value);
  -        if (value == null) {
  -            if (log.isDebugEnabled()) {
  -                log.debug("enable-instrumentation was not set - defaulting to false.");
  -            }
  -        }
  +		this.enableInstrumentation = getInitParameterAsBoolean("enable-instrumentation", false);
   
           this.requestFactory = new RequestFactory(this.autoSaveUploads,
                                                    this.uploadDir,
  @@ -790,7 +725,7 @@
        protected String getExtraClassPath()
        throws ServletException {
            String extraClassPath = this.getInitParameter("extra-classpath");
  -         if ((extraClassPath != null) && !extraClassPath.trim().equals("")) {
  +         if (extraClassPath != null) {
                StringBuffer sb = new StringBuffer();
                StringTokenizer st = new StringTokenizer(extraClassPath, System.getProperty("path.separator"), false);
                int i = 0;
  @@ -849,14 +784,11 @@
        * file.
        */
       private void initLogger() {
  -        String logLevel = getInitParameter("log-level");
  -        if (logLevel == null) {
  -            logLevel = "INFO";
  -        }
  +        String logLevel = getInitParameter("log-level", "INFO");
   
           final String accesslogger = getInitParameter("servlet-logger");
   
  -        final Priority logPriority = Priority.getPriorityForName(logLevel.trim());
  +        final Priority logPriority = Priority.getPriorityForName(logLevel);
   
           final ServletOutputLogTarget servTarget = new ServletOutputLogTarget(this.servletContext);
   
  @@ -888,10 +820,7 @@
               this.logKitManager = logKitManager;
   
               //Configure the logkit management
  -            String logkitConfig = getInitParameter("logkit-config");
  -            if (logkitConfig == null) {
  -                logkitConfig = "/WEB-INF/logkit.xconf";
  -            }
  +            String logkitConfig = getInitParameter("logkit-config", "/WEB-INF/logkit.xconf");
   
               InputStream is = this.servletContext.getResourceAsStream(logkitConfig);
               if (is == null) is = new FileInputStream(logkitConfig);
  @@ -1511,5 +1440,59 @@
               this.cocoon.dispose();
               this.cocoon = null;
           }
  +    }
  +    
  +    /**
  +     * Get an initialisation parameter. The value is trimmed, and null is returned if the trimmed value 
  +     * is empty.
  +     */
  +    public String getInitParameter(String name) {
  +    	String result = super.getInitParameter(name);
  +    	if (result != null) {
  +    		result = result.trim();
  +    		if (result.length() == 0) {
  +    			result = null;
  +    		}
  +    	}
  +    	
  +    	return result;
  +    }
  +    
  +    /** Convenience method to access servlet parameters */
  +    protected String getInitParameter(String name, String defaultValue) {
  +    	String result = getInitParameter(name);
  +    	if (result == null) {
  +    		if (log != null && log.isDebugEnabled()) {
  +    			log.debug(name + " was not set - defaulting to '" + defaultValue + "'");
  +    		}
  +    		return defaultValue;
  +    	} else {
  +    		return result;
  +    	}
  +    }
  +    
  +    /** Convenience method to access boolean servlet parameters */
  +    protected boolean getInitParameterAsBoolean(String name, boolean defaultValue) {
  +    	String value = getInitParameter(name);
  +    	if (value == null) {
  +			if (log != null && log.isDebugEnabled()) {
  +				log.debug(name + " was not set - defaulting to '" + defaultValue + "'");
  +			}
  +    		return defaultValue;
  +    	} else {
  +    		return value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes");
  +    	}
  +    }
  +    
  +    protected int getInitParameterAsInteger(String name, int defaultValue) {
  +    	String value = getInitParameter(name);
  +    	if (value == null) {
  +			if (log != null && log.isDebugEnabled()) {
  +				log.debug(name + " was not set - defaulting to '" + defaultValue + "'");
  +			}
  +			return defaultValue;
  +    	} else {
  +    		return Integer.parseInt(value);
  +    	}
       }
   }
  
  
  
  1.2       +12 -3     cocoon-2.1/src/java/org/apache/cocoon/servlet/ParanoidClassLoader.java
  
  Index: ParanoidClassLoader.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/java/org/apache/cocoon/servlet/ParanoidClassLoader.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ParanoidClassLoader.java	9 Mar 2003 00:09:37 -0000	1.1
  +++ ParanoidClassLoader.java	3 Jun 2003 13:25:42 -0000	1.2
  @@ -64,7 +64,7 @@
    * classes.  It checks this classloader before it checks its parent.
    *
    * @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
  - * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
  + * @author <a href="http://www.apache.org/~sylvain/">Sylvain Wallez</a>
    * @version CVS $Id$
    */
   
  @@ -85,7 +85,7 @@
        * Alternate constructor to define a parent.
        */
       public ParanoidClassLoader(final ClassLoader parent) {
  -        this(null, parent, null);
  +        this(new URL[0], parent, null);
       }
   
       /**
  @@ -151,6 +151,7 @@
               
               try {
                   clazz = findClass(name);
  +                //System.err.println("Paranoid load : " + name);
               } catch (ClassNotFoundException cnfe) {
                   if (this.parent != null) {
                        // Ask to parent ClassLoader (can also throw a CNFE).
  @@ -201,5 +202,13 @@
           } catch (MalformedURLException mue) {
               throw new CascadingIOException("Could not add repository", mue);
           }
  +    }
  +    
  +    /**
  +     * Adds a new URL
  +     */
  +    
  +    public void addURL(URL url) {
  +    	super.addURL(url);
       }
   }
  
  
  
  1.2       +138 -100  cocoon-2.1/src/java/org/apache/cocoon/servlet/ParanoidCocoonServlet.java
  
  Index: ParanoidCocoonServlet.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/java/org/apache/cocoon/servlet/ParanoidCocoonServlet.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ParanoidCocoonServlet.java	9 Mar 2003 00:09:37 -0000	1.1
  +++ ParanoidCocoonServlet.java	3 Jun 2003 13:25:42 -0000	1.2
  @@ -50,12 +50,20 @@
   */
   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.io.FilenameFilter;
  +import java.io.IOException;
  +import java.net.MalformedURLException;
   import java.net.URL;
  +import java.util.ArrayList;
  +import java.util.List;
  +
  +import javax.servlet.Servlet;
  +import javax.servlet.ServletConfig;
  +import javax.servlet.ServletException;
  +import javax.servlet.ServletRequest;
  +import javax.servlet.ServletResponse;
  +import javax.servlet.http.HttpServlet;
   
   /**
    * This is the entry point for Cocoon execution as an HTTP Servlet.
  @@ -66,105 +74,135 @@
    * of it.
    *
    * @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
  + * @author <a href="http://www.apache.org/~sylvain/">Sylvain Wallez</a>
    * @version CVS $Id$
    */
   
  -public class ParanoidCocoonServlet extends CocoonServlet {
  +public class ParanoidCocoonServlet extends HttpServlet {
   
  -    protected RepositoryClassLoader repositoryLoader;
  +	/**
  +	 * The name of the actual servlet class.
  +	 */
  +	public static final String SERVLET_CLASS = "org.apache.cocoon.servlet.CocoonServlet";
  +    
  +	private Servlet servlet;
  +    
  +	private ClassLoader classloader;
       
  -    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
  -     * <code>ServletContext</code>'s <code>getRealPath</code> method
  -     * to get the Servlet 2.2 identified classes and lib directories.
  -     * It iterates through every file in the lib directory and adds
  -     * it to the classpath.
  -     *
  -     * Also, we add the files to the ClassLoader for the Cocoon system.
  -     * In order to protect ourselves from skitzofrantic classloaders,
  -     * we need to work with a known one.
  -     *
  -     * @param context  The ServletContext to perform the lookup.
  -     *
  -     * @throws ServletException
  -     */
  -     protected String getClassPath()
  -     throws ServletException {
  -
  -        StringBuffer buildClassPath = new StringBuffer();
  -        String classDirPath = getInitParameter("class-dir");
  -        String libDirPath = getInitParameter("lib-dir");
  -        String classDir;
  -        File root;
  -
  -        if ((classDirPath != null) && !classDirPath.trim().equals("")) {
  -            classDir = classDirPath;
  -        } else {
  -            classDir = this.servletContext.getRealPath("/WEB-INF/classes");
  -        }
  -
  -        if ((libDirPath != null) && !libDirPath.trim().equals("")) {
  -            root = new File(libDirPath);
  -        } else {
  -            root = new File(this.servletContext.getRealPath("/WEB-INF/lib"));
  -        }
  -
  -        addClassLoaderDirectory(classDir);
  -
  -        buildClassPath.append(classDir);
  -
  -        if (root.isDirectory()) {
  -            File[] libraries = root.listFiles();
  -
  -            for (int i = 0; i < libraries.length; i++) {
  -            	String fullName = IOUtils.getFullFilename(libraries[i]);
  -                buildClassPath.append(File.pathSeparatorChar).append(fullName);
  -
  -                addClassLoaderDirectory(fullName);
  -            }
  -        }
  -
  -        buildClassPath.append(File.pathSeparatorChar)
  -                      .append(System.getProperty("java.class.path"));
  -
  -        buildClassPath.append(File.pathSeparatorChar)
  -                      .append(getExtraClassPath());
  -
  -        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);
  -            }
  -        }
  -    }
  +	public void init(ServletConfig config) throws ServletException {
  +		
  +		super.init(config);
  +
  +		// Create the classloader in which we will load the servlet
  +		this.classloader = getClassLoader(this.getContextDir());
  +        
  +        // Create the servlet
  +		try {
  +			Class servletClass = this.classloader.loadClass(SERVLET_CLASS);
  +            
  +			this.servlet = (Servlet)servletClass.newInstance();
  +
  +		} catch(Exception e) {
  +			throw new ServletException("Cannot load servlet " + SERVLET_CLASS, 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.
  +		Thread.currentThread().setContextClassLoader(this.classloader);
  +        
  +		// Inlitialize the actual servlet
  +		initServlet(servlet);
  +        
  +	}
  +	
  +	/**
  +	 * Initialize the wrapped servlet. Subclasses (see {@link BootstrapServlet} change the
  +	 * <code>ServletConfig</code> given to the servlet.
  +	 * 
  +	 * @param servlet the servlet to initialize
  +	 * @throws ServletException
  +	 */
  +	protected void initServlet(Servlet servlet) throws ServletException {
  +		this.servlet.init(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.
  +	 */
  +	private 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 FilenameFilter() {
  +	                public boolean accept(File dir, String name) {
  +	                    return name.endsWith(".zip") || name.endsWith(".jar");
  +	                }
  +				}
  +			);
  +
  +			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());
  +	}
  +    
  +	/**
  +	 * Service the request by delegating the call to the real servlet
  +	 */
  +	public void service(ServletRequest request, ServletResponse response)
  +	  throws ServletException, IOException {
  +
  +		Thread.currentThread().setContextClassLoader(this.classloader);
  +		this.servlet.service(request, response);
  +	}
  +    
  +	/**
  +	 * Destroy the actual servlet
  +	 */
  +	public void destroy() {
  +
  +		Thread.currentThread().setContextClassLoader(this.classloader);
  +		this.servlet.destroy();
  +
  +		super.destroy();
  +	}
   }