You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by pi...@apache.org on 2004/11/03 03:03:53 UTC

svn commit: rev 56453 - in cocoon/whiteboard/kernel/sources: runtime/org/apache/cocoon/kernel/deployment runtime/org/apache/cocoon/kernel/description runtime/org/apache/cocoon/kernel/plugins startup/org/apache/cocoon/kernel/startup

Author: pier
Date: Tue Nov  2 18:03:53 2004
New Revision: 56453

Added:
   cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/plugins/AbstractPlugin.java
   cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/plugins/LoggingPlugin.java
   cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/plugins/Utilities.java
   cocoon/whiteboard/kernel/sources/startup/org/apache/cocoon/kernel/startup/AbstractLogger.java
   cocoon/whiteboard/kernel/sources/startup/org/apache/cocoon/kernel/startup/ConsoleLogger.java
   cocoon/whiteboard/kernel/sources/startup/org/apache/cocoon/kernel/startup/Logger.java
   cocoon/whiteboard/kernel/sources/startup/org/apache/cocoon/kernel/startup/ServletLogger.java
Modified:
   cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/deployment/Deployer.java
   cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/deployment/Factory.java
   cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/deployment/Instance.java
   cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/description/Extension.java
   cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/description/Library.java
   cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/plugins/Plugin.java
   cocoon/whiteboard/kernel/sources/startup/org/apache/cocoon/kernel/startup/KernelLoader.java
   cocoon/whiteboard/kernel/sources/startup/org/apache/cocoon/kernel/startup/Main.java
   cocoon/whiteboard/kernel/sources/startup/org/apache/cocoon/kernel/startup/ServletLoader.java
   cocoon/whiteboard/kernel/sources/startup/org/apache/cocoon/kernel/startup/StartupKernel.java
Log:
Kernel logging implemented working as a plugin and using Log4J + Commons Logging: logging is provided to blocks using those two APIs and transparently re-processed by the kernel

Modified: cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/deployment/Deployer.java
==============================================================================
--- cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/deployment/Deployer.java	(original)
+++ cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/deployment/Deployer.java	Tue Nov  2 18:03:53 2004
@@ -20,12 +20,16 @@
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.cocoon.kernel.Kernel;
 import org.apache.cocoon.kernel.KernelException;
 import org.apache.cocoon.kernel.configuration.Configuration;
 import org.apache.cocoon.kernel.description.Block;
 import org.apache.cocoon.kernel.description.Descriptor;
+import org.apache.cocoon.kernel.description.Extension;
 import org.apache.cocoon.kernel.description.Library;
+import org.apache.cocoon.kernel.plugins.Plugin;
 import org.apache.cocoon.kernel.startup.KernelLoader;
+import org.apache.cocoon.kernel.startup.Logger;
 import org.apache.cocoon.kernel.startup.StartupKernel;
 
 /**
@@ -45,14 +49,16 @@
     private KernelLoader loader = null;
     /** <p>The {@link Library} of all {@link Block}s and {@link Interface}s.</p> */
     private Library library = null;
-    /** <p>The {@link Runtime} of all available {@link Instance}s.</p> */
-    //private Runtime runtime = null;
-    /** <p>A {@link Map} of all initialized singleton components.</p> */
-    private Map singletons = new HashMap();
     /** <p>A {@link Set} containing all components being initialized.</p> */
     private Set initializing = new HashSet();
+    /** <p>A {@link Map} of all initialized plugins.</p> */
+    private Map plugins = new HashMap();
     /** <p>A simple {@link Map} holding all instances and configurations.</p> */
     private Map wrappers = new HashMap();
+    /** <p>A {@link Map} of all initialized singleton components.</p> */
+    private Map singletons = new HashMap();
+    /** <p>The {@link Logger} used internally.</p> */
+    private Logger logger = new Logger();
 
     /**
      * <p>Create a new {@link Deployer} instance.</p>
@@ -83,34 +89,80 @@
      * @param instances A {@link Configuration} containing block instances.
      */
     public void initialize(Configuration descriptors, Configuration instances) {
+        this.logger.log("Initializing kernel instance");
+
         try {
             /* Retrieve all descriptors and put them in the library */
             Factory.configure(this.library, descriptors);
 
-            /* Make sure that our loader adds _all_ the libraries we need */
-            Iterator extensions = library.iterator(Descriptor.EXTENSION);
-            while (extensions.hasNext()) {
-                Descriptor descriptor = ((Descriptor) extensions.next());
-                this.loader.addURL(this, descriptor.getLibraries());
-            }
-
+            /* Make sure that our loader adds the interface libraries */
             Iterator interfaces = library.iterator(Descriptor.INTERFACE);
             while (interfaces.hasNext()) {
                 Descriptor descriptor = ((Descriptor) interfaces.next());
                 this.loader.addURL(this, descriptor.getLibraries());
             }
+
+            /* Add, load and instantiate plugins */
+            Iterator extensions = library.iterator(Descriptor.EXTENSION);
+            while (extensions.hasNext()) {
+                Extension descriptor = (Extension) extensions.next();
+                String element = descriptor.getPluginConfigurationElement();
+                String name = descriptor.getPlugin();
+                this.loader.addURL(this, descriptor.getLibraries());
+                java.net.URL libs[] = descriptor.getLibraries();
+                this.getLogger().debug("Adding a total of " + libs.length + " for " + descriptor);
+                for (int x = 0; x < libs.length; x ++) {
+                    this.getLogger().debug("Adding library at " + libs[x]);
+                }
+                
+                /* Now for the initialization */
+                try {
+                    /*
+                     * Instantiate the plugin in the classloader loading this class,
+                     * as the plug-in might be bundled with the kernel JAR itself
+                     */
+                    Class clazz = this.getClass().getClassLoader().loadClass(name);
+                    Plugin plugin = (Plugin) clazz.newInstance();
+
+                    /* Create a proxy for ourselves implementing StartupKernel */
+                    Wiring wiring = new Wiring(this);
+                    StartupKernel kernel = (StartupKernel) Proxy.newProxyInstance(
+                          this.loader, new Class[] { StartupKernel.class }, wiring);
+                    
+                    /* Configure the plugin with its configuration */
+                    plugin.configure(kernel, instances.child(element));
+                    plugin.initialize();
+                    this.plugins.put(element, plugin);
+
+                } catch (Throwable throwable) {
+                    throw new KernelException("Unable to load and initialize plugin "
+                            + "class \"" + descriptor.getPlugin() + "\" declared "
+                            + "by extension \"" + descriptor + "\"", throwable);
+                }
+            }
             
+            /* Do some logging */
+            this.logger.log("Configured descriptors:");
+            Iterator iterator = this.library.iterator();
+            while (iterator.hasNext()) {
+                Descriptor descriptor = (Descriptor) iterator.next();
+                this.logger.log(" - [" + Descriptor.NAMES[descriptor.getType()]
+                        + "] " + descriptor.toString());
+            }
+
             /* Configure all instances and be done with it */
             Factory.configure(this, instances);
 
             /* Initialize all singletons */
-            Iterator iterator = this.iterator();
-            System.err.println("INSTANCES:");
-            while (iterator.hasNext()) {
+            this.logger.log("Initializing singleton instances:");
+            Iterator wrappers = this.wrappers.keySet().iterator();
+            while (wrappers.hasNext()) {
                 /* Retrieve the instance and configuration */
-                String name = (String) iterator.next();
-                System.err.println(" " + name);
-                this.singletons.put(name, this.instantiate(name));
+                String name = (String) wrappers.next();
+                this.logger.log(" - [" + name + "] " + this.getBlock(name));
+                if (this.getBlock(name).isSingletonComponent()) {
+                    this.singletons.put(name, this.instantiate(name));
+                }
             }
 
         } catch (DeployerException exception) {
@@ -122,18 +174,31 @@
      * <p>Destroy this deployer and all block instances.</p>
      */
     public void destroy() {
+        this.logger.log("Destroying deployer instance");
+
+        this.logger.log("Destroying singleton instances:");
         Iterator iterator = this.singletons.keySet().iterator();
         while (iterator.hasNext()) {
             String current = (String) iterator.next();
+            this.logger.log(" - [" + current + "] " + this.getBlock(current));
             Object component = this.singletons.get(current);
             Instance instance = this.getInstance(current);
             Method destructor = instance.getComponentDestroyerMethod();
             try {
                 if (destructor != null) destructor.invoke(component, NULL);
             } catch (Throwable t) {
-                // TODO: log this with the block logger!
-                System.err.println("Exception destroying singleton: " + current);
-                t.printStackTrace(System.err);
+                this.logger.error("Exception destroying singleton: " + current, t);
+            }
+        }
+        
+        Iterator plugins = this.plugins.keySet().iterator();
+        while (plugins.hasNext()) {
+            String current = (String) plugins.next();
+            Plugin plugin = (Plugin) this.plugins.get(current);
+            try {
+                plugin.destroy();
+            } catch (Throwable t) {
+                this.logger.error("Exception destroying plugin: " + current, t);
             }
         }
     }
@@ -172,6 +237,20 @@
         }
     }
 
+    /**
+     * <p>Set the {@link Logger} used by the kernel internals.</p>
+     */
+    public void setLogger(Logger logger) {
+        if (logger != null) this.logger = logger;
+    }
+
+    /**
+     * <p>Retrieve {@link Logger} used by the kernel internals.</p>
+     */
+    public Logger getLogger() {
+        return this.logger;
+    }
+
     /* =========================================================================== */
     /* PROTECTED METHODS                                                           */
     /* =========================================================================== */
@@ -179,18 +258,18 @@
     /**
      * <p>Push a new {@link Block} {@link Instance} into this {@link Runtime}.</p>
      */
-    protected void add(String name, Instance instance, Configuration configuration) {
+    protected void putInstance(String name, Instance inst, Configuration conf) {
         if (name == null) throw new NullPointerException("Null name");
-        if (instance == null) throw new NullPointerException("Null instance");
-        if (configuration == null) throw new NullPointerException("Null config");
-        this.wrappers.put(name, new Wrapper(instance, configuration));
-    }
+        if (inst == null) throw new NullPointerException("Null instance");
+        if (conf == null) throw new NullPointerException("Null config");
+        this.wrappers.put(name, new Wrapper(inst, conf));
 
-    /**
-     * <p>Return an {@link Iterator} over all {@link Instance} names configured.</p>
-     */
-    protected Iterator iterator() {
-        return(this.wrappers.keySet().iterator());
+        Iterator iterator = this.plugins.keySet().iterator();
+        while (iterator.hasNext()) {
+            String plugin = (String) iterator.next();
+            Configuration curr = conf.child(plugin);
+            ((Plugin)this.plugins.get(plugin)).notify(inst, curr);
+        }
     }
 
     /**

Modified: cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/deployment/Factory.java
==============================================================================
--- cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/deployment/Factory.java	(original)
+++ cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/deployment/Factory.java	Tue Nov  2 18:03:53 2004
@@ -108,8 +108,8 @@
                 throw new DeployerException("Unable to instantiate non-block \""
                         + block + " declared at " + current.location());
             }
-            Instance instance = new Instance(runtime, (Block) descriptor);
-            runtime.add(name, instance, current);
+            Instance instance = new Instance(runtime, (Block) descriptor, name);
+            runtime.putInstance(name, instance, current);
         } catch (DeployerException e) {
             throw e;
         } catch (Throwable t) {

Modified: cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/deployment/Instance.java
==============================================================================
--- cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/deployment/Instance.java	(original)
+++ cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/deployment/Instance.java	Tue Nov  2 18:03:53 2004
@@ -46,16 +46,19 @@
     private Block block = null;
     /** <p>A set of all known {@link URL}s to avoid duplications.</p> */
     private Set urls = new HashSet();
+    /** <p>The name of this instance.</p> */
+    private String name = null;
 
     /**
      * <p>Create a new {@link Instance} instance.</p>
      */
-    public Instance(Deployer deployer, Block block)
+    public Instance(Deployer deployer, Block block, String name)
     throws DeployerException {
         super(block.getLibraries(), deployer.getLoader());
         URL libraries[] = block.getLibraries();
         for (int k = 0; k < libraries.length; k ++) urls.add(libraries[k]);
         this.block = block;
+        this.name = name;
 
         /* Process all interfaces, all extended blocks and all modules */
         Dependencies dependencies = new Dependencies();
@@ -105,6 +108,13 @@
 
         /* Remember where we're coming from */
         this.block = block;
+    }
+
+    /**
+     * <p>Return the name associated with this {@link Instance}.</p>
+     */
+    public String getName() {
+        return(this.name);
     }
 
     /**

Modified: cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/description/Extension.java
==============================================================================
--- cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/description/Extension.java	(original)
+++ cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/description/Extension.java	Tue Nov  2 18:03:53 2004
@@ -27,10 +27,8 @@
 
     /** <p>The name of the provided Java plugin.</p> */ 
     private String clazz = null;
-    /** <p>The name (if any) of the initializer method.</p> */
-    private String initializer = null;
-    /** <p>The name (if any) of the destroyer method.</p> */
-    private String destroyer = null;
+    /** <p>The name of the configuration element in the instances file.</p> */
+    private String element = null;
 
     /**
      * <p>Create a new {@link Extension} instance.</p>
@@ -56,8 +54,7 @@
         }
 
         /* Process initializer, destroyer, and singleton */
-        this.initializer = plugin.getStringAttribute("initialize", null);
-        this.destroyer = plugin.getStringAttribute("destroy", null);
+        this.element = plugin.getStringAttribute("configuration-element", null);
     }
 
     /**
@@ -68,23 +65,17 @@
     }
 
     /**
-     * <p>Return the name of the metod to call at initialization.</p>
+     * <p>Return the name of the element to be looked up in the configuration file
+     * containing the configuration of this plugin.</p>
      */
-    public String getPluginInitializer() {
-        return(this.initializer);
-    }
-
-    /**
-     * <p>Return the name of the metod to call at destruction.</p>
-     */
-    public String getPluginDestroyer() {
-        return(this.initializer);
+    public String getPluginConfigurationElement() {
+        return(this.element);
     }
 
     /**
      * <p>Return the type of this descriptor.</p>
      */
     public int getType() {
-        return Descriptor.BLOCK;
+        return Descriptor.EXTENSION;
     }
 }

Modified: cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/description/Library.java
==============================================================================
--- cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/description/Library.java	(original)
+++ cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/description/Library.java	Tue Nov  2 18:03:53 2004
@@ -128,6 +128,7 @@
             } catch (Throwable throwable) {
                 throw new IllegalArgumentException("Invalid type " + type);
             }
+            this.type = type;
             this.iterator = iterator;
         }
         

Added: cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/plugins/AbstractPlugin.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/plugins/AbstractPlugin.java	Tue Nov  2 18:03:53 2004
@@ -0,0 +1,138 @@
+/* =============================================================================== *
+ * Copyright (C) 1999-2004, The Apache Software Foundation.   All rights reserved. *
+ *                                                                                 *
+ * Licensed under the Apache License, Version 2.0 (the "License"). You may not use *
+ * this file except in  compliance with the License.  You may obtain a copy of the *
+ * License at <http://www.apache.org/licenses/LICENSE-2.0>.                        *
+ *                                                                                 *
+ * Unless required by applicable law or agreed to in writing, software distributed *
+ * under the License  is distributed on an  "AS IS"  BASIS,  WITHOUT WARRANTIES OR *
+ * CONDITIONS  OF ANY KIND,  either express  or implied.  See the License  for the *
+ * specific language governing permissions and limitations under the License.      *
+ * =============================================================================== */
+package org.apache.cocoon.kernel.plugins;
+
+import org.apache.cocoon.kernel.configuration.Configuration;
+import org.apache.cocoon.kernel.deployment.Instance;
+import org.apache.cocoon.kernel.startup.Logger;
+import org.apache.cocoon.kernel.startup.StartupKernel;
+
+/**
+ * <p>TODO.</p> 
+ *
+ * @author <a href="mailto:pier@apache.org">Pier Fumagalli</a>
+ * @author Copyright &copy; 2000-2004 <a href="http://www.apache.org/">The Apache
+ *         Software Foundation</a>. All rights reserved.
+ */
+public class AbstractPlugin extends Logger implements Plugin {
+    
+    /** <p>The configured {@link StartupKernel} instance.</p> */
+    private StartupKernel kernel = null;
+    /** <p>The global plugin {@link Configuration} member.</p> */
+    private Configuration config = null;
+
+    /**
+     * <p>Create a new {@link AbstractPlugin} instance.</p>
+     */
+    public AbstractPlugin() {
+        super();
+    }
+
+    /**
+     * <p>Configure this plugin from a specified {@link Configuration}.</p>
+     * 
+     * <p>This method is <b>final</b>. Implement the {@link #configure()} method
+     * and access the {@link StartupKernel} and {@link Configuration} calling
+     * the {@link #getKernel()} and {@link #getConfiguration()} methods.</p>
+     */
+    public final void configure(StartupKernel kernel, Configuration config) {
+        this.config = config;
+        this.kernel = kernel;
+        this.configure();
+        this.debug("Plugin \"" + this.getClass().getName() + "\" configured");
+    }
+
+    /**
+     * <p>This implementation doesn't do anything.</p>
+     */
+    public void configure() {
+        // NO-OP implementation.
+    }
+
+    /**
+     * <p>This implementation doesn't do anything.</p>
+     */
+    public void initialize() {
+        // NO-OP implementation.
+    }
+
+    /**
+     * <p>This implementation doesn't do anything.</p>
+     */
+    public void notify(Instance instance, Configuration config) {
+        // NO-OP implementation.
+    }
+
+    /**
+     * <p>This implementation doesn't do anything.</p>
+     */
+    public void destroy() {
+        // NO-OP implementation.
+    }
+
+    /**
+     * <p>Return the configured {@link StartupKernel} instance.</p>
+     */
+    public StartupKernel getKernel() {
+        return(this.kernel);
+    }
+
+    /**
+     * <p>Return the configured {@link Configuration} instance.</p>
+     */
+    public Configuration getConfiguration() {
+        return(this.config);
+    }
+
+    /**
+     * <p>Log a debug message.</p>
+     */
+    public void debug(String message) {
+        this.kernel.getLogger().debug(message);
+    }
+    
+    /**
+     * <p>Log a debug message.</p>
+     */
+    public void debug(String message, Throwable throwable) {
+        this.kernel.getLogger().debug(message, throwable);
+    }
+    
+    /**
+     * <p>Log a info message.</p>
+     */
+    public void log(String message) {
+        this.kernel.getLogger().log(message);
+    }
+    
+    /**
+     * <p>Log a info message.</p>
+     */
+    public void log(String message, Throwable throwable) {
+        this.kernel.getLogger().log(message, throwable);
+    }
+   
+    /**
+     * <p>Log a fatal error message.</p>
+     */
+    public void error(String message) {
+        this.kernel.getLogger().error(message);
+    }
+    
+    /**
+     * <p>Log a fatal error message.</p>
+     */
+    public void error(String message, Throwable throwable) {
+        this.kernel.getLogger().error(message, throwable);
+    }
+}

Added: cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/plugins/LoggingPlugin.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/plugins/LoggingPlugin.java	Tue Nov  2 18:03:53 2004
@@ -0,0 +1,269 @@
+/* =============================================================================== *
+ * Copyright (C) 1999-2004, The Apache Software Foundation.   All rights reserved. *
+ *                                                                                 *
+ * Licensed under the Apache License, Version 2.0 (the "License"). You may not use *
+ * this file except in  compliance with the License.  You may obtain a copy of the *
+ * License at <http://www.apache.org/licenses/LICENSE-2.0>.                        *
+ *                                                                                 *
+ * Unless required by applicable law or agreed to in writing, software distributed *
+ * under the License  is distributed on an  "AS IS"  BASIS,  WITHOUT WARRANTIES OR *
+ * CONDITIONS  OF ANY KIND,  either express  or implied.  See the License  for the *
+ * specific language governing permissions and limitations under the License.      *
+ * =============================================================================== */
+package org.apache.cocoon.kernel.plugins;
+
+import java.net.URL;
+import java.util.Enumeration;
+
+import org.apache.cocoon.kernel.deployment.Instance;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.logging.impl.Log4jFactory;
+import org.apache.log4j.Appender;
+import org.apache.log4j.Category;
+import org.apache.log4j.Level;
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+import org.apache.log4j.spi.HierarchyEventListener;
+import org.apache.log4j.spi.LoggerFactory;
+import org.apache.log4j.spi.LoggerRepository;
+import org.apache.log4j.spi.RepositorySelector;
+import org.apache.log4j.xml.DOMConfigurator;
+
+/**
+ * <p>The {@link LoggingPlugin} enables the use of Log4J and Commons-Logging
+ * in a kernel-aware way.</p> 
+ *
+ * @author <a href="mailto:pier@apache.org">Pier Fumagalli</a>
+ * @author Copyright &copy; 2000-2004 <a href="http://www.apache.org/">The Apache
+ *         Software Foundation</a>. All rights reserved.
+ */
+public class LoggingPlugin extends AbstractPlugin
+implements LoggerRepository, RepositorySelector {
+
+    /** <p>The original {@link LoggerRepository} of Log4J.</p> */
+    private LoggerRepository repository = null;
+    /** <p>The logger originally associated with the kernel.</p> */
+    private org.apache.cocoon.kernel.startup.Logger original = null;
+
+    /**
+     * <p>Create a new {@link LoggingPlugin} instance.</p>
+     */
+    public LoggingPlugin() {
+        this.repository = LogManager.getLoggerRepository();
+    }
+
+    public void initialize() {
+        /* Configure Log4J if we were told to do so */
+        String conf = this.getConfiguration().getStringAttribute("log4j", null);
+        if (conf != null) try {
+            URL url = new URL(this.getConfiguration().locationURL(), conf);
+            DOMConfigurator configurator = new DOMConfigurator();
+            configurator.doConfigure(url, this.repository);
+        } catch (Throwable throwable) {
+            this.error("Cannot configure Log4J", throwable);
+        }
+        
+        /* Error or no error, we _are_ using Log4J, no questions asked */
+        this.debug("Switching logger implementation");
+        this.original = this.getKernel().getLogger();
+        this.getKernel().setLogger(new Wrapper(Logger.getLogger("kernel")));
+        this.debug("Switched logger implementation");
+
+        /* Replace the Log4J Logger Repository */
+        this.debug("Configuring Log4J");
+        try {
+            LogManager.setRepositorySelector(this, null);
+        } catch (Throwable t) {
+            this.error("Unable to configure Log4J repository selector", t);
+        }
+        
+        /* And make sure that commons has the Log4J factory configured */
+        String factory = Log4jFactory.class.getName();
+        System.setProperty(LogFactory.FACTORY_PROPERTY, factory);
+        LogFactory.getLog(this.getClass()).debug("Commons-Logging configured");
+    }
+
+    public void destroy() {
+        this.debug("Restoring logger implementation");
+        this.getKernel().setLogger(this.original);
+        this.debug("Restored logger implementation");
+        this.repository.shutdown();
+    }
+
+    /* =========================================================================== */
+    /* UNDERSTANDABLE LOG4J METHODS                                                */
+    /* =========================================================================== */
+
+    /**
+     * <p>Return ourselves.</p>
+     */
+    public LoggerRepository getLoggerRepository() {
+        return(this);
+    }
+
+    /**
+     * <p>Return the logger associated with the calling block.</p>
+     */
+    public Logger getLogger(String arg0) {
+        return this.repository.getLogger(this.getLoggerName(arg0));
+    }
+
+    /**
+     * <p>Return the logger associated with the calling block.</p>
+     */
+    public Logger getLogger(String arg0, LoggerFactory arg1) {
+        return this.repository.getLogger(this.getLoggerName(arg0), arg1);
+    }
+
+    /**
+     * <p>Return the logger associated with the calling block.</p>
+     */
+    public Logger getRootLogger() {
+        return this.repository.getLogger(this.getLoggerName(null));
+    }
+
+    /**
+     * <p>Check if the logger specified exists.</p>
+     */
+    public Logger exists(String arg0) {
+        return this.repository.exists(this.getLoggerName(arg0));
+    }
+
+    /**
+     * <p>Canonicalize the name of the logger to return.</p>
+     */
+    public String getLoggerName(String arg0) {
+        String name = Utilities.getCallerName();
+        if (name == null) {
+            if (arg0 == null) return "unknown";
+            if (arg0.length() == 0) return "unknown";
+            return arg0;
+        } else {
+            if (arg0 == null) return name;
+            if (arg0.length() == 0) return name;
+            return (name + "." + arg0);
+        }
+    }
+
+    /**
+     * <p>Simply ignore this call from the kernel.</p>
+     */
+    public void resetConfiguration() {
+        // Nothing to do...
+    }
+
+    /**
+     * <p>Simply ignore this call from the kernel.</p>
+     */
+    public void shutdown() {
+        // Nothing to do...
+    }
+
+    /* =========================================================================== */
+    /* GOD KNOWS WHAT THIS DOES METHODS GO STRAIGHT TO LOG4J (TOO COMPLICATED)     */
+    /* =========================================================================== */
+
+    /**
+     * <p>Forwarded directly to the Log4J original {@link LoggerRepository}.</p>
+     */
+    public void addHierarchyEventListener(HierarchyEventListener arg0) {
+        this.repository.addHierarchyEventListener(arg0);
+    }
+
+    /**
+     * <p>Forwarded directly to the Log4J original {@link LoggerRepository}.</p>
+     */
+    public boolean isDisabled(int arg0) {
+        return this.repository.isDisabled(arg0);
+    }
+
+    /**
+     * <p>Forwarded directly to the Log4J original {@link LoggerRepository}.</p>
+     */
+    public void setThreshold(Level arg0) {
+        this.repository.setThreshold(arg0);
+    }
+
+    /**
+     * <p>Forwarded directly to the Log4J original {@link LoggerRepository}.</p>
+     */
+    public void setThreshold(String arg0) {
+        this.repository.setThreshold(arg0);
+    }
+
+    /**
+     * <p>Forwarded directly to the Log4J original {@link LoggerRepository}.</p>
+     */
+    public void emitNoAppenderWarning(Category arg0) {
+        this.repository.emitNoAppenderWarning(arg0);
+    }
+
+    /**
+     * <p>Forwarded directly to the Log4J original {@link LoggerRepository}.</p>
+     */
+    public Level getThreshold() {
+        return this.repository.getThreshold();
+    }
+
+    /**
+     * <p>Forwarded directly to the Log4J original {@link LoggerRepository}.</p>
+     */
+    public Enumeration getCurrentLoggers() {
+        return this.repository.getCurrentLoggers();
+    }
+
+    /**
+     * <p>Forwarded directly to the Log4J original {@link LoggerRepository}.</p>
+     */
+    public Enumeration getCurrentCategories() {
+        return this.repository.getCurrentCategories();
+    }
+
+    /**
+     * <p>Forwarded directly to the Log4J original {@link LoggerRepository}.</p>
+     */
+    public void fireAddAppenderEvent(Category arg0, Appender arg1) {
+        this.repository.fireAddAppenderEvent(arg0, arg1);
+    }
+
+    /* =========================================================================== */
+    /* WRAPPER FOR THE KERNEL LOGGER AROUND LOG4J                                  */
+    /* =========================================================================== */
+    
+    /**
+     * <p>A simple wrapper for the internal kernel logger.</p>
+     */
+    private static class Wrapper extends org.apache.cocoon.kernel.startup.Logger {
+
+        private Logger logger = null;
+
+        private Wrapper(Logger logger) {
+            if (logger == null) throw new NullPointerException("Null logger");
+            this.logger = logger;
+        }
+
+        public void debug(String message) {
+            this.logger.debug(message);
+        }
+        
+        public void debug(String message, Throwable throwable) {
+            this.logger.debug(message, throwable);
+        }
+        
+        public void log(String message) {
+            this.logger.info(message);
+        }
+        
+        public void log(String message, Throwable throwable) {
+            this.logger.info(message, throwable);
+        }
+       
+        public void error(String message) {
+            this.logger.error(message);
+        }
+        
+        public void error(String message, Throwable throwable) {
+            this.logger.error(message, throwable);
+        }
+    }
+}

Modified: cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/plugins/Plugin.java
==============================================================================
--- cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/plugins/Plugin.java	(original)
+++ cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/plugins/Plugin.java	Tue Nov  2 18:03:53 2004
@@ -12,13 +12,49 @@
  * =============================================================================== */
 package org.apache.cocoon.kernel.plugins;
 
+import org.apache.cocoon.kernel.configuration.Configuration;
+import org.apache.cocoon.kernel.deployment.Instance;
+import org.apache.cocoon.kernel.startup.StartupKernel;
+
 /**
- * <p>The {@link Plugin} interface identifies a.</p> 
+ * <p>The {@link Plugin} interface defines a kernel extension.</p> 
  *
+ * <p>Kernel plug-ins follow a very simple lifecycle:</p>
+ * 
+ * <ol>
+ *   <li>{@link #configure(StartupKernel, Configuration)}</li>
+ *   <li>{@link #initialize()}</li>
+ *   <li>
+ *     {@link #notify(String, Instance, Configuration)}<br />
+ *     <i>called as many times as many block instances are deployed</i>
+ *   </li>
+ *   <li>{@link #destroy()}</li>
+ * </ol>
+ * 
  * @author <a href="mailto:pier@apache.org">Pier Fumagalli</a>
  * @author Copyright &copy; 2000-2004 <a href="http://www.apache.org/">The Apache
  *         Software Foundation</a>. All rights reserved.
  */
 public interface Plugin {
+
+    /**
+     * <p>Configure this plugin from a specified {@link Configuration}.</p>
+     */
+    public void configure(StartupKernel kernel, Configuration configuration);
+
+    /**
+     * <p>Initialize this kernel {@link Plugin}.</p>
+     */
+    public void initialize();
+    
+    /**
+     * <p>Receive notification of the creation of a new block {@link Instance}.</p>
+     */
+    public void notify(Instance instance, Configuration configuration);
+    
+    /**
+     * <p>Destroy this kernel {@link Plugin}.</p>
+     */
+    public void destroy();
 
 }

Added: cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/plugins/Utilities.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/plugins/Utilities.java	Tue Nov  2 18:03:53 2004
@@ -0,0 +1,56 @@
+/* =============================================================================== *
+ * Copyright (C) 1999-2004, The Apache Software Foundation.   All rights reserved. *
+ *                                                                                 *
+ * Licensed under the Apache License, Version 2.0 (the "License"). You may not use *
+ * this file except in  compliance with the License.  You may obtain a copy of the *
+ * License at <http://www.apache.org/licenses/LICENSE-2.0>.                        *
+ *                                                                                 *
+ * Unless required by applicable law or agreed to in writing, software distributed *
+ * under the License  is distributed on an  "AS IS"  BASIS,  WITHOUT WARRANTIES OR *
+ * CONDITIONS  OF ANY KIND,  either express  or implied.  See the License  for the *
+ * specific language governing permissions and limitations under the License.      *
+ * =============================================================================== */
+package org.apache.cocoon.kernel.plugins;
+
+import org.apache.cocoon.kernel.deployment.Instance;
+
+/**
+ * <p>TODO.</p> 
+ *
+ * @author <a href="mailto:pier@apache.org">Pier Fumagalli</a>
+ * @author Copyright &copy; 2000-2004 <a href="http://www.apache.org/">The Apache
+ *         Software Foundation</a>. All rights reserved.
+ */
+public class Utilities extends SecurityManager {
+    
+    /** <p>Our {@link Utilities} instance.</p> */
+    private static Utilities instance = new Utilities();
+
+    /** <p>Deny normal construction.</p> */
+    private Utilities() {
+        super();
+    }
+    
+    /**
+     * <p>Retrieve the block instance calling this method.</p>
+     */
+    public static Instance getCaller() {
+        Class context[] = Utilities.instance.getClassContext();
+        if (context == null) return(null);
+        for (int x = 0; x < context.length; x++) {
+            if (context[x].getClassLoader() instanceof Instance) {
+                return((Instance)(context[x].getClassLoader()));
+            }
+        }
+        return(null);
+    }
+
+    /**
+     * <p>Retrieve the block instance calling this method.</p>
+     */
+    public static String getCallerName() {
+        Instance instance = Utilities.getCaller();
+        if (instance != null) return (instance.getName());
+        return(null);
+    }
+}

Added: cocoon/whiteboard/kernel/sources/startup/org/apache/cocoon/kernel/startup/AbstractLogger.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/sources/startup/org/apache/cocoon/kernel/startup/AbstractLogger.java	Tue Nov  2 18:03:53 2004
@@ -0,0 +1,255 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.kernel.startup;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import javax.xml.transform.TransformerException;
+
+import org.xml.sax.SAXException;
+
+/**
+ * <p>The {@link AbstractLogger} is a simple abstract {@link Logger} formatting
+ * log entries and outputting them.</p>
+ *
+ * @author <a href="mailto:pier@apache.org">Pier Fumagalli</a>
+ * @version 1.0 (CVS $Revision: 1.9 $)
+ */
+public abstract class AbstractLogger extends Logger {
+
+    /** <p>Output debug, info, warn, error and fatal messages.</p> */
+    public static final int DEBUG = 0;
+    /** <p>Output info, warn, error and fatal messages.</p> */
+    public static final int INFO = 1;
+    /** <p>Output only fatal error messages.</p> */
+    public static final int ERROR = 2;
+
+    /* ====================================================================== */
+
+    /** <p>The logging level.</p> */
+    protected int level = DEBUG;
+    /** <p>The timestamp formatter (if any).</p> */
+    private SimpleDateFormat format = null;
+
+    /* ====================================================================== */
+        
+    /**
+     * <p>Create a new {@link AbstractLogger}.</p>
+     *
+     * @param level the minimum level of logging messages to output.
+     */
+    public AbstractLogger(int level) {
+        this.format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
+        if (level < DEBUG) this.level = DEBUG;
+        else if (level > ERROR) this.level = ERROR;
+        else this.level = level;
+    }
+
+    /* ====================================================================== */
+
+    /**
+     * <p>Log a debug message.</p>
+     *
+     * @param message the message.
+     */
+    public void debug(String message) {
+        this.out(DEBUG, message, null);
+    }
+    
+    /**
+     * <p>Log a debug message.</p>
+     *
+     * @param message the message.
+     * @param throwable the throwable.
+     */
+    public void debug(String message, Throwable throwable) {
+        this.out(DEBUG, message, throwable);
+    }
+    
+    /**
+     * <p>Log a info message.</p>
+     *
+     * @param message the message.
+     */
+    public void log(String message) {
+        this.out(INFO, message, null);
+    }
+    
+    /**
+     * <p>Log a info message.</p>
+     *
+     * @param message the message.
+     * @param throwable the throwable.
+     */
+    public void log(String message, Throwable throwable) {
+        this.out(INFO, message, throwable);
+    }
+   
+    /**
+     * <p>Log a fatal error message.</p>
+     *
+     * @param message the message.
+     */
+    public void error(String message) {
+        this.out(ERROR, message, null);
+    }
+    
+    /**
+     * <p>Log a fatal error message.</p>
+     *
+     * @param message the message.
+     * @param throwable the throwable.
+     */
+    public void error(String message, Throwable throwable) {
+        this.out(ERROR, message, throwable);
+    }
+    
+    /* ====================================================================== */
+
+    /**
+     * <p>Write a line to the output.</p>
+     *
+     * @param line the line to write.
+     */
+    protected abstract void output(String line);
+    
+    /* ====================================================================== */
+
+    /**
+     * <p>Generate output from this logger.</p>
+     *
+     * @param level the level of the log entry.
+     * @param message the message to log (if any).
+     * @param throwable the {@link Throwable} to log (if any).
+     */
+    private void out(int level, String message, Throwable throwable) {
+        if (level < this.level) return;
+
+        /* Prepare the header for output in a new buffer */
+        StringBuffer buffer = new StringBuffer(64);
+        
+        /* If we got a time formatter, append the time */
+        if (this.format != null) buffer.append(this.format.format(new Date()));
+        
+        /* Dump out the log level */
+        if (buffer.length() > 0) buffer.append(" ");
+        switch (level) {
+            case DEBUG: buffer.append("[DEBUG] "); break;
+            case INFO:  buffer.append("[INFO ] "); break;
+            case ERROR: buffer.append("[ERROR] "); break;
+            default:    buffer.append("[?????] "); break;
+        }
+
+        /* If both message and throwable were null, whopsie */
+        if ((message == null) && (throwable == null)) {
+            this.output(buffer.append("null logging entry?").toString());
+            return;
+        }
+
+        /* If we want to re-use the header for the throwable, lets save it*/
+        String header = (throwable != null ? buffer.toString() : null);
+        
+        /* If we have a message, we want to output it */
+        if (message != null) this.output(buffer.append(message).toString());
+
+        /* If we have a throwable, we output it with the saved header */
+        if (throwable != null) this.out(header, throwable, false);
+    }
+
+    /**
+     * <p>Generate output from this logger for a {@link Throwable}.</p>
+     *
+     * @param header the header to use.
+     * @param throwable the {@link Throwable} to log.
+     * @param cause if the {@link Throwable} is the cause of another.
+     */
+    private void out(String header, Throwable throwable, boolean cause) {
+        StringBuffer buffer = new StringBuffer(200);
+
+        /* Check if this throwable has a cause */
+        Throwable causedby = null;
+        if (throwable instanceof SAXException) {
+            causedby = ((SAXException)throwable).getException();
+        } else causedby = throwable.getCause();
+
+        /* Print the logging header and an explaination */
+        buffer.append(header);
+        buffer.append(cause ? "+ Caused by " : "Exception ");
+
+        /* Print the Throwable class name */
+        buffer.append(throwable.getClass().getName());
+        buffer = this.out(buffer);
+
+        /* Print the Throwable message */
+        String message = throwable.getMessage();
+        if (throwable instanceof TransformerException) {
+            message = ((TransformerException)throwable).getMessageAndLocation();
+        }
+        if (message == null) message = "[Null Exception Message!]";
+        /* Print the header for the message */
+        buffer.append(header);
+            
+        /* Widgeting, many checks, one buffer append call */
+        if (!cause) buffer.append("+--- ");
+        else buffer.append(causedby == null ? "  +--- "  : "| +--- ");
+
+        /* Print out the message */
+        buffer = this.out(buffer.append(message));
+
+        /* Analyze every single stack trace element */
+        StackTraceElement trace[] = throwable.getStackTrace();
+        for (int x = 0; x < trace.length; x++) {
+
+            /* Per each stack trace element print the header */
+            buffer.append(header);
+
+            /* Widgeting, many checks, one buffer append call */
+            if ((x + 1) == trace.length) {
+                /* What widgets to print if this the last trace element */
+                if (causedby == null)
+                     buffer.append(cause ? "  + at " : "+ at ");
+                else buffer.append(cause ? "| + at " : "| at ");
+            } else {
+                /* What widgets to print if this the last trace element */
+                if (cause) 
+                     buffer.append(causedby == null ? "  | at " : "| | at ");
+                else buffer.append("| at ");
+            }
+
+            /* And finally print the trace */
+            buffer = this.out(buffer.append(trace[x].toString()));
+        }
+
+        /* Recursively loop through the causes of the exception */
+        if (causedby != null) {
+            buffer.append(header);
+            this.out(buffer.append("|"));
+            this.out(header, causedby, true);
+        } else this.out(buffer.append(header));
+    }
+
+    /**
+     * <p>Output a StringBuffer and return a new one.</p>
+     *
+     * @param buffer the buffer to output.
+     * @return a new buffer.
+     */
+    private StringBuffer out(StringBuffer buffer) {
+        if (buffer != null) this.output(buffer.toString());
+        return(new StringBuffer(200));
+    }
+}

Added: cocoon/whiteboard/kernel/sources/startup/org/apache/cocoon/kernel/startup/ConsoleLogger.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/sources/startup/org/apache/cocoon/kernel/startup/ConsoleLogger.java	Tue Nov  2 18:03:53 2004
@@ -0,0 +1,64 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.kernel.startup;
+
+import java.io.PrintStream;
+
+
+/**
+ * <p>The {@link ConsoleLogger} is a simple {@link Logger} implementation
+ * writing to {@link System#err}.</p>
+ *
+ * @author <a href="mailto:pier@apache.org">Pier Fumagalli</a>
+ * @version 1.0 (CVS $Revision: 1.6 $)
+ */
+public class ConsoleLogger extends AbstractLogger {
+
+    /** The {@link PrintStream} used for output */
+    private PrintStream out = null;
+    
+    /* ====================================================================== */
+
+    /**
+     * <p>Create a new {@link ConsoleLogger} logging everything to
+     * {@link System#err}.</p>
+     */
+    public ConsoleLogger() {
+        this(DEBUG);
+    }
+
+    /**
+     * <p>Create a new {@link ConsoleLogger} logging message at a specified level
+     * to {@link System#err}.</p>
+     *
+     * @param level the level of output.
+     */
+    public ConsoleLogger(int level) {
+        super(level);
+        this.out = System.err;
+    }
+    
+    /* ====================================================================== */
+
+    /**
+     * <p>Write a line to the output.</p>
+     *
+     * @param line the line to write.
+     */
+    protected void output(String line) {
+        this.out.println(line);
+    }
+}

Modified: cocoon/whiteboard/kernel/sources/startup/org/apache/cocoon/kernel/startup/KernelLoader.java
==============================================================================
--- cocoon/whiteboard/kernel/sources/startup/org/apache/cocoon/kernel/startup/KernelLoader.java	(original)
+++ cocoon/whiteboard/kernel/sources/startup/org/apache/cocoon/kernel/startup/KernelLoader.java	Tue Nov  2 18:03:53 2004
@@ -37,8 +37,6 @@
     /** <p>Deny public construction.</p> */
     private KernelLoader(ClassLoader loader, URL libraries[]) {
         super(libraries, loader);
-        if (libraries == null) return;
-        for (int k = 0; k < libraries.length; k ++) urls.add(libraries[k]);
     }
 
     /**
@@ -73,7 +71,10 @@
     throws Throwable {
         if (loader == null) loader = Thread.currentThread().getContextClassLoader();
         if (libraries == null) libraries = new URL[0];
+
+        /* Instantiate the deployer in a child classloader of the kernel loader */
         KernelLoader kernel_loader = new KernelLoader(loader, libraries);
+        URLClassLoader child_loader = new URLClassLoader(libraries, kernel_loader);
 
         Class clazz = kernel_loader.loadClass(KernelLoader.CLASS);
         Class signature[] = new Class [] { KernelLoader.class };
@@ -103,6 +104,6 @@
     public void addURL(StartupKernel kernel, URL urls[]) {
         if (this.kernel != kernel) throw new SecurityException("Invalid instance");
         if (urls == null) return;
-        for (int x = 0; x < urls.length; x ++) super.addURL(urls[x]);
+        for (int x = 0; x < urls.length; x ++) this.addURL(kernel, urls[x]);
     }
 }

Added: cocoon/whiteboard/kernel/sources/startup/org/apache/cocoon/kernel/startup/Logger.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/sources/startup/org/apache/cocoon/kernel/startup/Logger.java	Tue Nov  2 18:03:53 2004
@@ -0,0 +1,90 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.kernel.startup;
+
+/**
+ * <p>A {@link Logger} instance is used by the kernel internals to log messages and
+ * errors.</p>
+ *
+ * <p>Normally a kernel plugin will provide the real instance used by the kernel
+ * to log, and the initial {@link Logger} instance is used exclusively during
+ * the startup phase of the kernel.</p>
+ *
+ * <p>This implementation never logs.</p>
+ *
+ * @author <a href="mailto:pier@apache.org">Pier Fumagalli</a>
+ * @version 1.0 (CVS $Revision: 1.2 $)
+ */
+public class Logger {
+
+    /**
+     * <p>Create a new {@link Logger}.</p>
+     */
+    public Logger() {
+        super();
+    }
+    
+    /**
+     * <p>Log a debug message.</p>
+     *
+     * @param message the message.
+     */
+    public void debug(String message) {
+    }
+    
+    /**
+     * <p>Log a debug message.</p>
+     *
+     * @param message the message.
+     * @param throwable the throwable.
+     */
+    public void debug(String message, Throwable throwable) {
+    }
+    
+    /**
+     * <p>Log a info message.</p>
+     *
+     * @param message the message.
+     */
+    public void log(String message) {
+    }
+    
+    /**
+     * <p>Log a info message.</p>
+     *
+     * @param message the message.
+     * @param throwable the throwable.
+     */
+    public void log(String message, Throwable throwable) {
+    }
+   
+    /**
+     * <p>Log a fatal error message.</p>
+     *
+     * @param message the message.
+     */
+    public void error(String message) {
+    }
+    
+    /**
+     * <p>Log a fatal error message.</p>
+     *
+     * @param message the message.
+     * @param throwable the throwable.
+     */
+    public void error(String message, Throwable throwable) {
+    }
+}

Modified: cocoon/whiteboard/kernel/sources/startup/org/apache/cocoon/kernel/startup/Main.java
==============================================================================
--- cocoon/whiteboard/kernel/sources/startup/org/apache/cocoon/kernel/startup/Main.java	(original)
+++ cocoon/whiteboard/kernel/sources/startup/org/apache/cocoon/kernel/startup/Main.java	Tue Nov  2 18:03:53 2004
@@ -20,7 +20,6 @@
 import org.apache.cocoon.kernel.Kernel;
 import org.apache.cocoon.kernel.configuration.Configuration;
 import org.apache.cocoon.kernel.configuration.ConfigurationBuilder;
-import org.apache.cocoon.kernel.deployment.Deployer;
 
 /**
  * <p>A simple class initializing a {@link Kernel} from a the command line.</p> 
@@ -85,18 +84,24 @@
             return;
         }
 
-        /* Parse the (possibly two) configurations */
-        Configuration descriptors = ConfigurationBuilder.parse(args[1]);
-        Configuration instances = (args.length == 2 ? descriptors : 
-                ConfigurationBuilder.parse(args[2]));
+        ConsoleLogger logger = new ConsoleLogger();
+        try {
+            /* Parse the (possibly two) configurations */
+            Configuration descriptors = ConfigurationBuilder.parse(args[1]);
+            Configuration instances = (args.length == 2 ? descriptors : 
+                    ConfigurationBuilder.parse(args[2]));
         
-        /* Create and initialize a new deployer */
-        URL library = new File(args[0]).toURL();
-        StartupKernel kernel = KernelLoader.load(library);
-        kernel.initialize(descriptors, instances);
-
-        /* Add the shutdown hook */
-        Runtime.getRuntime().addShutdownHook(new Thread(new Main(kernel)));
+            /* Create and initialize a new deployer */
+            URL library = new File(args[0]).toURL();
+            StartupKernel kernel = KernelLoader.load(library);
+            kernel.setLogger(logger);
+            kernel.initialize(descriptors, instances);
+
+            /* Add the shutdown hook */
+            Runtime.getRuntime().addShutdownHook(new Thread(new Main(kernel)));
+        } catch (Throwable throwable) {
+            logger.log("Unable to startup kernel", throwable);
+        }
 
         /* 
          * If non-daemon threads are still running, this thread will siply exit but

Modified: cocoon/whiteboard/kernel/sources/startup/org/apache/cocoon/kernel/startup/ServletLoader.java
==============================================================================
--- cocoon/whiteboard/kernel/sources/startup/org/apache/cocoon/kernel/startup/ServletLoader.java	(original)
+++ cocoon/whiteboard/kernel/sources/startup/org/apache/cocoon/kernel/startup/ServletLoader.java	Tue Nov  2 18:03:53 2004
@@ -12,7 +12,6 @@
  * =============================================================================== */
 package org.apache.cocoon.kernel.startup;
 
-import java.lang.reflect.Proxy;
 import java.net.URL;
 
 import javax.servlet.Servlet;
@@ -23,8 +22,6 @@
 import org.apache.cocoon.kernel.Kernel;
 import org.apache.cocoon.kernel.configuration.Configuration;
 import org.apache.cocoon.kernel.configuration.ConfigurationBuilder;
-import org.apache.cocoon.kernel.deployment.Deployer;
-import org.apache.cocoon.kernel.deployment.Wiring;
 
 /**
  * <p>The {@link ServletLoader} is a {@link ServletContextListener} managing the
@@ -98,6 +95,7 @@
         String instances = context.getInitParameter("kernel-instances");
         
         /* Load and initialize the kernel */
+        ServletLogger logger = new ServletLogger(context);
         try {
             URL library_url = context.getResource(library);
             if (library_url == null) {
@@ -106,6 +104,7 @@
                 throw new RuntimeException(message);
             }
             this.kernel = KernelLoader.load(library_url);
+            this.kernel.setLogger(logger);
 
             /* Parse the (possibly two) configurations and initialize the deployer */
             if (configuration != null) {
@@ -120,16 +119,13 @@
                 this.kernel.initialize(desc, inst);
             }
         } catch (Throwable t) {
-            context.log("Unable to intialize kernel", t);
+            logger.error("Unable to intialize kernel", t);
             throw new RuntimeException("Unable to initialize kernel", t);
         }
 
         /* Make the kernel available through the servlet context */
-        ClassLoader loader = this.getClass().getClassLoader();
-        Class interfaces[] = new Class[] { Kernel.class };
-        Wiring wiring = new Wiring(this.kernel);
-        Kernel kernel = (Kernel) Proxy.newProxyInstance(loader, interfaces, wiring);
-        context.setAttribute(ServletLoader.ATTRIBUTE, kernel);
+        Wrapper wrapper = new Wrapper(this.kernel);
+        context.setAttribute(ServletLoader.ATTRIBUTE, wrapper);
     }
 
     /**
@@ -145,6 +141,23 @@
             throw new RuntimeException("Unable to destroy kernel", t);
         } finally {
             this.kernel = null;
+        }
+    }
+    
+    /**
+     * <p>A simple wrapper for the {@link Kernel}.</p>
+     */
+    private static class Wrapper implements Kernel {
+        
+        private Kernel kernel = null;
+
+        private Wrapper(Kernel kernel) {
+            if (kernel == null) throw new NullPointerException("Null kernel");
+            this.kernel = kernel;
+        }
+        
+        public Object lookup(String name) {
+            return(this.kernel.lookup(name));
         }
     }
 }

Added: cocoon/whiteboard/kernel/sources/startup/org/apache/cocoon/kernel/startup/ServletLogger.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/sources/startup/org/apache/cocoon/kernel/startup/ServletLogger.java	Tue Nov  2 18:03:53 2004
@@ -0,0 +1,66 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.kernel.startup;
+
+import javax.servlet.ServletContext;
+
+
+/**
+ * <p>The {@link ServletLogger} is a simple {@link Logger} implementation
+ * logging individual lines to a {@link ServletContext}.</p>
+ *
+ * @author <a href="mailto:pier@apache.org">Pier Fumagalli</a>
+ * @version 1.0 (CVS $Revision: 1.3 $)
+ */
+public class ServletLogger extends AbstractLogger {
+
+    /** <p>Our {@link ServletContext} instance.</p> */
+    private ServletContext context = null;
+    
+    /**
+     * <p>Create a new {@link ServletLogger} associated with a specific
+     * {@link ServletContext}.</p>
+     *
+     * @param context the {@link ServletContext} to log to.
+     */
+    public ServletLogger(ServletContext context) {
+        this(context, DEBUG);
+    }
+    
+    /**
+     * <p>Create a new {@link ServletLogger} associated with a specific
+     * {@link ServletContext}.</p>
+     *
+     * @param level the level of output.
+     * @param context the {@link ServletContext} to log to.
+     */
+    public ServletLogger(ServletContext context, int level) {
+        super(level);
+        if (context == null) throw new NullPointerException("Null context");
+        this.context = context;
+    }
+
+    /* ====================================================================== */
+
+    /**
+     * <p>Write a line to the output.</p>
+     *
+     * @param line the line to write.
+     */
+    protected void output(String line) {
+        this.context.log(line);
+    }
+}

Modified: cocoon/whiteboard/kernel/sources/startup/org/apache/cocoon/kernel/startup/StartupKernel.java
==============================================================================
--- cocoon/whiteboard/kernel/sources/startup/org/apache/cocoon/kernel/startup/StartupKernel.java	(original)
+++ cocoon/whiteboard/kernel/sources/startup/org/apache/cocoon/kernel/startup/StartupKernel.java	Tue Nov  2 18:03:53 2004
@@ -45,4 +45,13 @@
      */
     public void destroy();
 
+    /**
+     * <p>Set the {@link Logger} used by the kernel internals.</p>
+     */
+    public void setLogger(Logger logger);
+
+    /**
+     * <p>Retrieve {@link Logger} used by the kernel internals.</p>
+     */
+    public Logger getLogger();
 }