You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by cz...@apache.org on 2005/04/04 15:27:43 UTC

svn commit: r160040 - in cocoon/trunk/src: core/java/org/apache/cocoon/core/Core.java core/java/org/apache/cocoon/core/CoreUtil.java java/org/apache/cocoon/servlet/CocoonServlet.java

Author: cziegeler
Date: Mon Apr  4 06:27:43 2005
New Revision: 160040

URL: http://svn.apache.org/viewcvs?view=rev&rev=160040
Log:
Finish first initialization phase

Modified:
    cocoon/trunk/src/core/java/org/apache/cocoon/core/Core.java
    cocoon/trunk/src/core/java/org/apache/cocoon/core/CoreUtil.java
    cocoon/trunk/src/java/org/apache/cocoon/servlet/CocoonServlet.java

Modified: cocoon/trunk/src/core/java/org/apache/cocoon/core/Core.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/core/java/org/apache/cocoon/core/Core.java?view=diff&r1=160039&r2=160040
==============================================================================
--- cocoon/trunk/src/core/java/org/apache/cocoon/core/Core.java (original)
+++ cocoon/trunk/src/core/java/org/apache/cocoon/core/Core.java Mon Apr  4 06:27:43 2005
@@ -20,6 +20,7 @@
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.URL;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
@@ -31,6 +32,7 @@
 import org.apache.avalon.framework.context.ContextException;
 import org.apache.avalon.framework.context.Contextualizable;
 import org.apache.avalon.framework.context.DefaultContext;
+import org.apache.avalon.framework.logger.Logger;
 import org.apache.cocoon.Constants;
 import org.apache.cocoon.components.ContextHelper;
 import org.apache.cocoon.configuration.Settings;
@@ -242,13 +244,35 @@
         void configure(Settings settings);
         void configureLoggingContext(DefaultContext context);
 
+        void configure(DefaultContext context);
+
         ClassLoader getInitClassLoader();
 
         org.apache.cocoon.environment.Context getEnvironmentContext();
         
-        String getContextPath();
-        
+        /**
+         * Returns the URL to the application context.
+         */
+        String getContextURL();
+
+        /**
+         * Returns a file to the application context.
+         * @return A file pointing to the context or null if the context is not
+         *         writeable.
+         */
+        File getContextForWriting();
+
         LogTarget getDefaultLogTarget();
+
+        /**
+         * Set the ConfigFile for the Cocoon object.
+         *
+         * @param configFileName The file location for the cocoon.xconf
+         *
+         * @throws Exception
+         */
+        public URL getConfigFile(final Logger logger, final String configFileName)
+        throws Exception;
     }
     
 }

Modified: cocoon/trunk/src/core/java/org/apache/cocoon/core/CoreUtil.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/core/java/org/apache/cocoon/core/CoreUtil.java?view=diff&r1=160039&r2=160040
==============================================================================
--- cocoon/trunk/src/core/java/org/apache/cocoon/core/CoreUtil.java (original)
+++ cocoon/trunk/src/core/java/org/apache/cocoon/core/CoreUtil.java Mon Apr  4 06:27:43 2005
@@ -17,21 +17,44 @@
 package org.apache.cocoon.core;
 
 import java.io.File;
+import java.io.IOException;
 import java.lang.reflect.Constructor;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
 
+import org.apache.avalon.excalibur.logger.Log4JLoggerManager;
+import org.apache.avalon.excalibur.logger.LogKitLoggerManager;
 import org.apache.avalon.excalibur.logger.LoggerManager;
+import org.apache.avalon.framework.CascadingRuntimeException;
+import org.apache.avalon.framework.configuration.Configurable;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.avalon.framework.configuration.DefaultConfiguration;
 import org.apache.avalon.framework.container.ContainerUtil;
+import org.apache.avalon.framework.context.ContextException;
 import org.apache.avalon.framework.context.DefaultContext;
+import org.apache.avalon.framework.logger.LogKitLogger;
 import org.apache.avalon.framework.logger.Logger;
 import org.apache.avalon.framework.service.ServiceException;
 import org.apache.avalon.framework.service.ServiceManager;
 import org.apache.cocoon.Constants;
 import org.apache.cocoon.components.ContextHelper;
+import org.apache.cocoon.configuration.ConfigurationBuilder;
 import org.apache.cocoon.configuration.Settings;
+import org.apache.cocoon.core.source.SimpleSourceResolver;
+import org.apache.cocoon.matching.helpers.WildcardHelper;
 import org.apache.cocoon.util.ClassUtils;
-import org.apache.cocoon.util.log.LoggingHelper;
+import org.apache.cocoon.util.log.Log4JConfigurator;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.TraversableSource;
+import org.apache.log.ErrorHandler;
+import org.apache.log.Hierarchy;
+import org.apache.log.Priority;
+import org.apache.log.util.DefaultErrorHandler;
+import org.apache.log4j.LogManager;
 
 /**
  *
@@ -40,6 +63,9 @@
  */
 public class CoreUtil {
 
+    /** Parameter map for the context protocol */
+    protected static final Map CONTEXT_PARAMETERS = Collections.singletonMap("force-traversable", Boolean.TRUE);
+
     /** The callback to the real environment */
     protected final Core.BootstrapEnvironment env;
 
@@ -58,17 +84,17 @@
 
         // create settings
         this.settings = Core.createSettings(this.env);
+        this.appContext.put(Core.CONTEXT_SETTINGS, this.settings);
 
         this.createRootServiceManager();
     }
 
     /**
-     * Bootstrap Cocoon Service Manager
+     * Bootstrap Cocoon Service Manager.
      */
-    public ServiceManager createRootServiceManager() 
+    public ServiceManager createRootServiceManager()
     throws Exception {
 
-        
         if (this.settings.isInitClassloader()) {
             // Force context classloader so that JAXP can work correctly
             // (see javax.xml.parsers.FactoryFinder.findClassLoader())
@@ -79,14 +105,27 @@
             }
         }
 
-        this.appContext.put(Constants.CONTEXT_ENVIRONMENT_CONTEXT, this.env.getEnvironmentContext());
+        // add root url
+        try {
+            appContext.put(ContextHelper.CONTEXT_ROOT_URL, 
+                           new URL(env.getContextURL()));            
+        } catch (MalformedURLException ignore) {
+            // we simply ignore this
+        }
+
+        // add environment context
+        this.appContext.put(Constants.CONTEXT_ENVIRONMENT_CONTEXT, 
+                            this.env.getEnvironmentContext());
+
+        // now add environment specific information
+        this.env.configure(appContext);
 
         // first init the work-directory for the logger.
         // this is required if we are running inside a war file!
         final String workDirParam = this.settings.getWorkDirectory();
         File workDir;
         if (workDirParam != null) {
-            if (this.env.getContextPath() == null) {
+            if (this.env.getContextForWriting() == null) {
                 // No context path : consider work-directory as absolute
                 workDir = new File(workDirParam);
             } else {
@@ -97,7 +136,7 @@
                     workDir = workDirParamFile;
                 } else {
                     // No : consider it relative to context path
-                    workDir = new File(this.env.getContextPath(), workDirParam);
+                    workDir = new File(this.env.getContextForWriting(), workDirParam);
                 }
             }
         } else {
@@ -107,62 +146,13 @@
         this.appContext.put(Constants.CONTEXT_WORK_DIR, workDir);
         this.settings.setWorkDirectory(workDir.getAbsolutePath());
 
-        // TODO we should move the following into the bootstrap env
-        String contextURL;
-        String path = env.getContextPath();
-        // these two variables are just for debugging. We can't log at this point
-        // as the logger isn't initialized yet.
-        String debugPathOne = null, debugPathTwo = null;
-        if (path == null) {
-            // Try to figure out the path of the root from that of WEB-INF
-            //try {
-                // TODO:
-                //path = this.servletContext.getResource("/WEB-INF").toString();
-            //} catch (MalformedURLException me) {
-            //    throw new ServletException("Unable to get resource 'WEB-INF'.", me);
-            //}
-            debugPathOne = path;
-            path = path.substring(0, path.length() - "WEB-INF".length());
-            debugPathTwo = path;
-        }
-        try {
-            if (path.indexOf(':') > 1) {
-                contextURL = path;
-            } else {
-                contextURL = new File(path).toURL().toExternalForm();
-            }
-        } catch (MalformedURLException me) {
-            // VG: Novell has absolute file names starting with the
-            // volume name which is easily more then one letter.
-            // Examples: sys:/apache/cocoon or sys:\apache\cocoon
-            try {
-                contextURL = new File(path).toURL().toExternalForm();
-            } catch (MalformedURLException ignored) {
-                throw new Exception("Unable to determine context URL.", me);
-            }
-        }
-
-        try {
-            appContext.put(ContextHelper.CONTEXT_ROOT_URL, new URL(contextURL));            
-        } catch (MalformedURLException ignore) {
-            // we simply ignore this
-        }
-
         // Init logger
         initLogger();
-        if (this.log.isDebugEnabled()) {
-            this.log.debug(this.settings.toString());
-            this.log.debug("getRealPath for /: " + this.env.getContextPath());
-            if ( this.env.getContextPath() == null ) {                
-                this.log.debug("getResource for /WEB-INF: " + debugPathOne);
-                this.log.debug("Path for Root: " + debugPathTwo);
-            }
-        }
-
 
         // Output some debug info
         if (this.log.isDebugEnabled()) {
-            this.log.debug("Context URL: " + contextURL);
+            this.log.debug("Context URL: " + env.getContextURL());
+            this.log.debug("Writeable Context: " + env.getContextForWriting());
             if (workDirParam != null) {
                 this.log.debug("Using work-directory " + workDir);
             } else {
@@ -173,7 +163,7 @@
         final String uploadDirParam = this.settings.getUploadDirectory();
         File uploadDir;
         if (uploadDirParam != null) {
-            if (env.getContextPath() == null) {
+            if (env.getContextForWriting() == null) {
                 uploadDir = new File(uploadDirParam);
             } else {
                 // Context path exists : is upload-directory absolute ?
@@ -183,7 +173,7 @@
                     uploadDir = uploadDirParamFile;
                 } else {
                     // No : consider it relative to context path
-                    uploadDir = new File(env.getContextPath(), uploadDirParam);
+                    uploadDir = new File(env.getContextForWriting(), uploadDirParam);
                 }
             }
             if (this.log.isDebugEnabled()) {
@@ -202,7 +192,7 @@
         String cacheDirParam = this.settings.getCacheDirectory();
         File cacheDir;
         if (cacheDirParam != null) {
-            if (env.getContextPath() == null) {
+            if (env.getContextForWriting() == null) {
                 cacheDir = new File(cacheDirParam);
             } else {
                 // Context path exists : is cache-directory absolute ?
@@ -212,7 +202,7 @@
                     cacheDir = cacheDirParamFile;
                 } else {
                     // No : consider it relative to context path
-                    cacheDir = new File(env.getContextPath(), cacheDirParam);
+                    cacheDir = new File(env.getContextForWriting(), cacheDirParam);
                 }
             }
             if (this.log.isDebugEnabled()) {
@@ -232,12 +222,20 @@
         appContext.put(Constants.CONTEXT_CACHE_DIR, cacheDir);
         this.settings.setCacheDirectory(cacheDir.getAbsolutePath());
 
-        // create new Core
-        final Core cocoon = new Core(this.settings);
-        
+        // update settings
+        final URL u = this.env.getConfigFile(this.log, this.settings.getConfiguration());
+        this.settings.setConfiguration(u.toExternalForm());
+        this.appContext.put(Constants.CONTEXT_CONFIG_URL, u);
+
         // create parent service manager
         final ServiceManager parent = this.getParentServiceManager();
 
+        // set encoding
+        this.appContext.put(Constants.CONTEXT_DEFAULT_ENCODING, settings.getFormEncoding());
+
+        // create new Core
+        final Core cocoon = new Core(this.settings);
+
         return new RootServiceManager(parent, cocoon);
     }
     
@@ -267,13 +265,13 @@
                 Constructor pcmc = pcm.getConstructor(new Class[]{String.class});
                 parentServiceManager = (ServiceManager) pcmc.newInstance(new Object[]{parentServiceManagerInitParam});
 
-                //ContainerUtil.enableLogging(parentServiceManager, getLogger());
-                //ContainerUtil.contextualize(parentServiceManager, this.appContext);
+                ContainerUtil.enableLogging(parentServiceManager, this.log);
+                ContainerUtil.contextualize(parentServiceManager, this.appContext);
                 ContainerUtil.initialize(parentServiceManager);
             } catch (Exception e) {
-                /*if (getLogger().isErrorEnabled()) {
-                    getLogger().error("Could not initialize parent component manager.", e);
-                }*/
+                if (this.log.isErrorEnabled()) {
+                    this.log.error("Could not initialize parent component manager.", e);
+                }
             }
         }
         return parentServiceManager;
@@ -282,19 +280,212 @@
     protected void initLogger() {
         final DefaultContext subcontext = new DefaultContext(this.appContext);
         subcontext.put("context-work", new File(this.settings.getWorkDirectory()));
-        if (this.env.getContextPath() == null) {
+        if (this.env.getContextURL() == null) {
             File logSCDir = new File(this.settings.getWorkDirectory(), "log");
             logSCDir.mkdirs();
             subcontext.put("context-root", logSCDir.toString());
         } else {
-            subcontext.put("context-root", this.env.getContextPath());
+            subcontext.put("context-root", this.env.getContextURL());
         }
         this.env.configureLoggingContext(subcontext);
 
-        // FIXME - we can move the logging helper into this class
-        LoggingHelper loggingHelper = new LoggingHelper(this.settings, this.env.getDefaultLogTarget(), subcontext);
-        this.loggerManager = loggingHelper.getLoggerManager();
-        this.log = loggingHelper.getLogger();
+        String logLevel = settings.getBootstrapLogLevel();
+        if (logLevel == null) {
+            logLevel = "INFO";
+        }
+
+        String accesslogger = settings.getAccessLogger();
+        if (accesslogger == null) {
+            accesslogger = "cocoon";
+        }
+
+        final Priority logPriority = Priority.getPriorityForName(logLevel);
+
+        final Hierarchy defaultHierarchy = Hierarchy.getDefaultHierarchy();
+        final ErrorHandler errorHandler = new DefaultErrorHandler();
+        defaultHierarchy.setErrorHandler(errorHandler);
+        defaultHierarchy.setDefaultLogTarget(this.env.getDefaultLogTarget());
+        defaultHierarchy.setDefaultPriority(logPriority);
+        final Logger logger = new LogKitLogger(Hierarchy.getDefaultHierarchy()
+                .getLoggerFor(""));
+
+        // we can't pass the context-root to our resolver
+        Object value = null;
+        try {
+            value = subcontext.get("context-root");
+            ((DefaultContext) subcontext).put("context-root", null);
+        } catch (ContextException ignore) {
+            // not available
+        }
+        // Create our own resolver
+        SimpleSourceResolver resolver = new SimpleSourceResolver();
+        resolver.enableLogging(logger);
+        try {
+            resolver.contextualize(subcontext);
+        } catch (ContextException ce) {
+            throw new CascadingRuntimeException(
+                    "Cannot setup source resolver.", ce);
+        }
+        if (value != null) {
+            ((DefaultContext) subcontext).put("context-root", value);
+        }
+        String loggerManagerClass = settings.getLoggerClassName();
+        if (loggerManagerClass == null) {
+            loggerManagerClass = LogKitLoggerManager.class.getName();
+        }
+
+        // the log4j support requires currently that the log4j system is already
+        // configured elsewhere
+
+        final LoggerManager loggerManager = newLoggerManager(
+                loggerManagerClass, defaultHierarchy);
+        ContainerUtil.enableLogging(loggerManager, logger);
+
+        try {
+            ContainerUtil.contextualize(loggerManager, subcontext);
+            this.loggerManager = loggerManager;
+
+            if (loggerManager instanceof Configurable) {
+                //Configure the logkit management
+                String logkitConfig = settings.getLoggingConfiguration();
+                if (logkitConfig == null) {
+                    logkitConfig = "/WEB-INF/logkit.xconf";
+                }
+
+                Source source = null;
+                try {
+                    source = resolver.resolveURI(logkitConfig);
+                    final ConfigurationBuilder builder = new ConfigurationBuilder(
+                            settings);
+                    final Configuration conf = builder.build(source
+                            .getInputStream());
+                    final DefaultConfiguration categories = (DefaultConfiguration) conf
+                            .getChild("categories");
+                    final DefaultConfiguration targets = (DefaultConfiguration) conf
+                            .getChild("targets");
+                    final DefaultConfiguration factories = (DefaultConfiguration) conf
+                            .getChild("factories");
+
+                    // now process includes
+                    final Configuration[] children = conf
+                            .getChildren("include");
+                    for (int i = 0; i < children.length; i++) {
+                        String directoryURI = children[i].getAttribute("dir");
+                        final String pattern = children[i].getAttribute(
+                                "pattern", null);
+                        int[] parsedPattern = null;
+                        if (pattern != null) {
+                            parsedPattern = WildcardHelper
+                                    .compilePattern(pattern);
+                        }
+                        Source directory = null;
+                        try {
+                            directory = resolver.resolveURI(directoryURI,
+                                    source.getURI(), CONTEXT_PARAMETERS);
+                            if (directory instanceof TraversableSource) {
+                                final Iterator c = ((TraversableSource) directory)
+                                        .getChildren().iterator();
+                                while (c.hasNext()) {
+                                    final Source s = (Source) c.next();
+                                    if (parsedPattern == null
+                                            || this.match(s.getURI(),
+                                                    parsedPattern)) {
+                                        final Configuration includeConf = builder
+                                                .build(s.getInputStream());
+                                        // add targets and categories
+                                        categories.addAllChildren(includeConf
+                                                .getChild("categories"));
+                                        targets.addAllChildren(includeConf
+                                                .getChild("targets"));
+                                        factories.addAllChildren(includeConf
+                                                .getChild("factories"));
+                                    }
+                                }
+                            } else {
+                                throw new ConfigurationException(
+                                        "Include.dir must point to a directory, '"
+                                                + directory.getURI()
+                                                + "' is not a directory.'");
+                            }
+                        } catch (IOException ioe) {
+                            throw new ConfigurationException(
+                                    "Unable to read configurations from "
+                                            + directoryURI);
+                        } finally {
+                            resolver.release(directory);
+                        }
+
+                        // finally remove include
+                        ((DefaultConfiguration) conf).removeChild(children[i]);
+                    }
+                    // override log level?
+                    if (settings.getOverrideLogLevel() != null) {
+                        this.overrideLogLevel(conf.getChild("categories"),
+                                settings.getOverrideLogLevel());
+                    }
+                    ContainerUtil.configure(loggerManager, conf);
+                } finally {
+                    resolver.release(source);
+                }
+            }
+
+            // let's configure log4j
+            final String log4jConfig = settings.getLog4jConfiguration();
+            if (log4jConfig != null) {
+                final Log4JConfigurator configurator = new Log4JConfigurator(subcontext);
+
+                Source source = null;
+                try {
+                    source = resolver.resolveURI(log4jConfig);
+                    configurator.doConfigure(source.getInputStream(),
+                            LogManager.getLoggerRepository());
+                } finally {
+                    resolver.release(source);
+                }
+            }
+
+            ContainerUtil.initialize(loggerManager);
+        } catch (Exception e) {
+            errorHandler.error(
+                    "Could not set up Cocoon Logger, will use screen instead",
+                    e, null);
+        }
+
+        this.log = this.loggerManager.getLoggerForCategory(accesslogger);
+    }
+
+    private LoggerManager newLoggerManager(String loggerManagerClass,
+            Hierarchy hierarchy) {
+        if (loggerManagerClass.equals(LogKitLoggerManager.class.getName())) {
+            return new LogKitLoggerManager(hierarchy);
+        } else if (loggerManagerClass
+                .equals(Log4JLoggerManager.class.getName())
+                || loggerManagerClass.equalsIgnoreCase("LOG4J")) {
+            return new Log4JLoggerManager();
+        } else {
+            try {
+                Class clazz = Class.forName(loggerManagerClass);
+                return (LoggerManager) clazz.newInstance();
+            } catch (Exception e) {
+                return new LogKitLoggerManager(hierarchy);
+            }
+        }
+    }
+
+    protected void overrideLogLevel(Configuration root, String value) {
+        Configuration[] c = root.getChildren("category");
+        for(int i=0;i<c.length;i++) {
+            ((DefaultConfiguration)c[i]).setAttribute("log-level", value);
+            this.overrideLogLevel(c[i], value);
+        }
+    }
+
+    private boolean match(String uri, int[] parsedPattern ) {
+        int pos = uri.lastIndexOf('/');
+        if ( pos != -1 ) {
+            uri = uri.substring(pos+1);
+        }
+        return WildcardHelper.match(null, uri, parsedPattern);      
     }
 
     public static final class RootServiceManager implements ServiceManager {
@@ -344,5 +535,5 @@
             }
         }
     }
-    
+
 }

Modified: cocoon/trunk/src/java/org/apache/cocoon/servlet/CocoonServlet.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/servlet/CocoonServlet.java?view=diff&r1=160039&r2=160040
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/servlet/CocoonServlet.java (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/servlet/CocoonServlet.java Mon Apr  4 06:27:43 2005
@@ -181,9 +181,40 @@
         super.init(conf);
 
         this.servletContextPath = this.servletContext.getRealPath("/");
+        String path = this.servletContextPath;
+        // these two variables are just for debugging. We can't log at this point
+        // as the logger isn't initialized yet.
+        String debugPathOne = null, debugPathTwo = null;
+        if (path == null) {
+            // Try to figure out the path of the root from that of WEB-INF
+            try {
+                path = this.servletContext.getResource("/WEB-INF").toString();
+            } catch (MalformedURLException me) {
+                throw new ServletException("Unable to get resource 'WEB-INF'.", me);
+            }
+            debugPathOne = path;
+            path = path.substring(0, path.length() - "WEB-INF".length());
+            debugPathTwo = path;
+        }
+        try {
+            if (path.indexOf(':') > 1) {
+                this.servletContextURL = path;
+            } else {
+                this.servletContextURL = new File(path).toURL().toExternalForm();
+            }
+        } catch (MalformedURLException me) {
+            // VG: Novell has absolute file names starting with the
+            // volume name which is easily more then one letter.
+            // Examples: sys:/apache/cocoon or sys:\apache\cocoon
+            try {
+                this.servletContextURL = new File(path).toURL().toExternalForm();
+            } catch (MalformedURLException ignored) {
+                throw new ServletException("Unable to determine servlet context URL.", me);
+            }
+        }
 
         // initialize settings
-        Core.BootstrapEnvironment env = new ServletBootstrapEnvironment(conf, this.classLoader, this.servletContextPath);
+        Core.BootstrapEnvironment env = new ServletBootstrapEnvironment(conf, this.classLoader, this.servletContextPath, this.servletContextURL);
 
         this.settings = Core.createSettings(env);
 
@@ -242,37 +273,6 @@
         this.appContext.put(Constants.CONTEXT_WORK_DIR, workDir);
         this.settings.setWorkDirectory(workDir.getAbsolutePath());
 
-        String path = this.servletContextPath;
-        // these two variables are just for debugging. We can't log at this point
-        // as the logger isn't initialized yet.
-        String debugPathOne = null, debugPathTwo = null;
-        if (path == null) {
-            // Try to figure out the path of the root from that of WEB-INF
-            try {
-                path = this.servletContext.getResource("/WEB-INF").toString();
-            } catch (MalformedURLException me) {
-                throw new ServletException("Unable to get resource 'WEB-INF'.", me);
-            }
-            debugPathOne = path;
-            path = path.substring(0, path.length() - "WEB-INF".length());
-            debugPathTwo = path;
-        }
-        try {
-            if (path.indexOf(':') > 1) {
-                this.servletContextURL = path;
-            } else {
-                this.servletContextURL = new File(path).toURL().toExternalForm();
-            }
-        } catch (MalformedURLException me) {
-            // VG: Novell has absolute file names starting with the
-            // volume name which is easily more then one letter.
-            // Examples: sys:/apache/cocoon or sys:\apache\cocoon
-            try {
-                this.servletContextURL = new File(path).toURL().toExternalForm();
-            } catch (MalformedURLException ignored) {
-                throw new ServletException("Unable to determine servlet context URL.", me);
-            }
-        }
         try {
             this.appContext.put(ContextHelper.CONTEXT_ROOT_URL, new URL(this.servletContextURL));
         } catch (MalformedURLException ignore) {
@@ -360,9 +360,16 @@
         this.settings.setCacheDirectory(cacheDir.getAbsolutePath());
 
         // update settings
-        final URL u = this.getConfigFile(this.settings.getConfiguration());
-        this.settings.setConfiguration(u.toExternalForm());
-        this.appContext.put(Constants.CONTEXT_CONFIG_URL, u);
+        try {
+            final URL u = env.getConfigFile(this.log, this.settings.getConfiguration());
+            this.settings.setConfiguration(u.toExternalForm());
+            this.appContext.put(Constants.CONTEXT_CONFIG_URL, u);
+        } catch (Exception e) {
+            if ( e instanceof ServletException ) {
+                throw (ServletException)e;
+            }
+            throw new ServletException(e);
+        }
 
         parentServiceManagerClass = this.settings.getParentServiceManagerClassName();
         if (parentServiceManagerClass != null) {
@@ -677,65 +684,6 @@
     }
 
     /**
-     * Set the ConfigFile for the Cocoon object.
-     *
-     * @param configFileName The file location for the cocoon.xconf
-     *
-     * @throws ServletException
-     */
-    private URL getConfigFile(final String configFileName)
-    throws ServletException {
-        final String usedFileName;
-
-        if (configFileName == null) {
-            if (getLogger().isWarnEnabled()) {
-                getLogger().warn("Servlet initialization argument 'configurations' not specified, attempting to use '/WEB-INF/cocoon.xconf'");
-            }
-            usedFileName = "/WEB-INF/cocoon.xconf";
-        } else {
-            usedFileName = configFileName;
-        }
-
-        if (getLogger().isDebugEnabled()) {
-            getLogger().debug("Using configuration file: " + usedFileName);
-        }
-
-        URL result;
-        try {
-            // test if this is a qualified url
-            if (usedFileName.indexOf(':') == -1) {
-                result = this.servletContext.getResource(usedFileName);
-            } else {
-                result = new URL(usedFileName);
-            }
-        } catch (Exception mue) {
-            String msg = "Init parameter 'configurations' is invalid : " + usedFileName;
-            getLogger().error(msg, mue);
-            throw new ServletException(msg, mue);
-        }
-
-        if (result == null) {
-            File resultFile = new File(usedFileName);
-            if (resultFile.isFile()) {
-                try {
-                    result = resultFile.getCanonicalFile().toURL();
-                } catch (Exception e) {
-                    String msg = "Init parameter 'configurations' is invalid : " + usedFileName;
-                    getLogger().error(msg, e);
-                    throw new ServletException(msg, e);
-                }
-            }
-        }
-
-        if (result == null) {
-            String msg = "Init parameter 'configuration' doesn't name an existing resource : " + usedFileName;
-            getLogger().error(msg);
-            throw new ServletException(msg);
-        }
-        return result;
-    }
-
-    /**
      * Handle the <code>load-class</code> parameter. This overcomes
      * limits in many classpath issues. One of the more notorious
      * ones is a bug in WebSphere that does not load the URL handler
@@ -1308,10 +1256,20 @@
 
         private final ServletConfig config;
         private final ClassLoader   classLoader;
+        private final File          writeableContextPath;
         private final String        contextPath;
-        public ServletBootstrapEnvironment(ServletConfig config, ClassLoader cl, String path) {
+
+        public ServletBootstrapEnvironment(ServletConfig config, 
+                                           ClassLoader   cl, 
+                                           String        writeablePath,
+                                           String        path) {
             this.config = config;
             this.classLoader = cl;
+            if ( writeablePath == null ) {
+                this.writeableContextPath = null;
+            } else {
+                this.writeableContextPath = new File(writeablePath);
+            }
             this.contextPath = path;
         }
 
@@ -1363,14 +1321,20 @@
         }
 
         /**
-         * @see org.apache.cocoon.core.Core.BootstrapEnvironment#getContextPath()
+         * @see org.apache.cocoon.core.Core.BootstrapEnvironment#getContextURL()
          */
-        public String getContextPath() {
+        public String getContextURL() {
             return this.contextPath;
         }
 
 
         /**
+         * @see org.apache.cocoon.core.Core.BootstrapEnvironment#getContextForWriting()
+         */
+        public File getContextForWriting() {
+            return this.writeableContextPath;
+        }
+        /**
          * @see org.apache.cocoon.core.Core.BootstrapEnvironment#getDefaultLogTarget()
          */
         public LogTarget getDefaultLogTarget() {
@@ -1385,7 +1349,70 @@
          * @see org.apache.cocoon.core.Core.BootstrapEnvironment#configureLoggingContext(org.apache.avalon.framework.context.DefaultContext)
          */
         public void configureLoggingContext(DefaultContext context) {
-            context.put("servlet-context", this.config.getServletContext());
+            context.put(CONTEXT_SERVLET_CONFIG, this.config.getServletContext());
+        }
+
+        /**
+         * @see org.apache.cocoon.core.Core.BootstrapEnvironment#configure(org.apache.avalon.framework.context.DefaultContext)
+         */
+        public void configure(DefaultContext context) {
+            context.put(CONTEXT_SERVLET_CONFIG, this.config.getServletContext());
+        }
+
+        /**
+         * @see org.apache.cocoon.core.Core.BootstrapEnvironment#getConfigFile(org.apache.avalon.framework.logger.Logger, java.lang.String)
+         */
+        public URL getConfigFile(final Logger logger, final String configFileName)
+        throws Exception {
+            final String usedFileName;
+
+            if (configFileName == null) {
+                if (logger.isWarnEnabled()) {
+                    logger.warn("Servlet initialization argument 'configurations' not specified, attempting to use '/WEB-INF/cocoon.xconf'");
+                }
+                usedFileName = "/WEB-INF/cocoon.xconf";
+            } else {
+                usedFileName = configFileName;
+            }
+
+            if (logger.isDebugEnabled()) {
+                logger.debug("Using configuration file: " + usedFileName);
+            }
+
+            URL result;
+            try {
+                // test if this is a qualified url
+                if (usedFileName.indexOf(':') == -1) {
+                    result = this.config.getServletContext().getResource(usedFileName);
+                } else {
+                    result = new URL(usedFileName);
+                }
+            } catch (Exception mue) {
+                String msg = "Init parameter 'configurations' is invalid : " + usedFileName;
+                logger.error(msg, mue);
+                throw new ServletException(msg, mue);
+            }
+
+            if (result == null) {
+                File resultFile = new File(usedFileName);
+                if (resultFile.isFile()) {
+                    try {
+                        result = resultFile.getCanonicalFile().toURL();
+                    } catch (Exception e) {
+                        String msg = "Init parameter 'configurations' is invalid : " + usedFileName;
+                        logger.error(msg, e);
+                        throw new ServletException(msg, e);
+                    }
+                }
+            }
+
+            if (result == null) {
+                String msg = "Init parameter 'configuration' doesn't name an existing resource : " + usedFileName;
+                logger.error(msg);
+                throw new ServletException(msg);
+            }
+            return result;
         }
+
     }
 }