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/04 23:58:41 UTC

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

Author: pier
Date: Thu Nov  4 14:58:41 2004
New Revision: 56626

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/Block.java
   cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/description/Extension.java
   cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/plugins/AbstractPlugin.java
   cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/plugins/Plugin.java
Log:
Slimmer container, multiple plugin per extension, default configurations from descriptors.

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	Thu Nov  4 14:58:41 2004
@@ -53,7 +53,7 @@
     /** <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();
+    private Set plugins = new HashSet();
     /** <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> */
@@ -107,18 +107,15 @@
             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.logger.debug("Initializing plugins for: " + descriptor);
+
                 /* 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);
+                String plugins[] = descriptor.getPluginClassNames();
+                for (int x = 0; x < plugins.length; x ++) try {
+
+                    /* Load the plugin class and instantiate it */
+                    Class clazz = this.loader.loadClass(plugins[x]);
                     Plugin plugin = (Plugin) clazz.newInstance();
 
                     /* Create a proxy for ourselves implementing StartupKernel */
@@ -127,14 +124,18 @@
                           this.loader, new Class[] { StartupKernel.class }, wiring);
                     
                     /* Configure the plugin with its configuration */
-                    plugin.configure(kernel, instances.child(element));
+                    String element = plugin.getConfigurationElement();
+                    Configuration configuration = instances.child(element);
+                    plugin.configure(kernel, configuration);
                     plugin.initialize();
-                    this.plugins.put(element, plugin);
+                    this.logger.debug("Recording plugin \"" + plugins[x] + "\" with "
+                            + " element \"" + element + "\"");
+                    this.plugins.add(plugin);
 
                 } catch (Throwable throwable) {
                     throw new KernelException("Unable to load and initialize plugin "
-                            + "class \"" + descriptor.getPlugin() + "\" declared "
-                            + "by extension \"" + descriptor + "\"", throwable);
+                            + "class \"" + plugins[x] + "\" declared by extension \""
+                            + descriptor + "\"", throwable);
                 }
             }
             
@@ -155,16 +156,18 @@
 
             /* Initialize all singletons */
             this.logger.log("Initializing singleton instances:");
-            Iterator wrappers = this.wrappers.keySet().iterator();
+            Iterator wrappers = this.wrappers.values().iterator();
             while (wrappers.hasNext()) {
                 /* Retrieve the instance and configuration */
-                String name = (String) wrappers.next();
-                this.logger.log(" - [" + name + "] " + this.getBlock(name));
-                if (this.getBlock(name).isSingletonComponent()) {
-                    this.singletons.put(name, this.instantiate(name));
+                Wrapper wrapper = (Wrapper) wrappers.next();
+                String name = wrapper.instance.getName();
+                Block block = wrapper.instance.getBlock();
+                if (block.isSingletonComponent()) {
+                    this.logger.log(" - [" + name + "] " + block);
+                    Object singleton = this.newComponentInstance(wrapper);
+                    this.singletons.put(name, singleton);
                 }
             }
-
         } catch (DeployerException exception) {
             throw new KernelException("Unable to initialize kernel", exception);
         }
@@ -180,25 +183,32 @@
         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);
+            Wrapper wrapper = (Wrapper) this.wrappers.get(current);
+            Instance instance = wrapper.instance;
+
+            this.logger.log(" - [" + current + "] " + instance.getBlock());
             Method destructor = instance.getComponentDestroyerMethod();
+
+            Thread thread = Thread.currentThread();
+            ClassLoader context = thread.getContextClassLoader();
+            thread.setContextClassLoader(instance);
             try {
                 if (destructor != null) destructor.invoke(component, NULL);
             } catch (Throwable t) {
                 this.logger.error("Exception destroying singleton: " + current, t);
             }
+            thread.setContextClassLoader(instance);
         }
         
-        Iterator plugins = this.plugins.keySet().iterator();
+        Iterator plugins = this.plugins.iterator();
         while (plugins.hasNext()) {
-            String current = (String) plugins.next();
-            Plugin plugin = (Plugin) this.plugins.get(current);
+            Plugin plugin = (Plugin) plugins.next();
             try {
                 plugin.destroy();
             } catch (Throwable t) {
-                this.logger.error("Exception destroying plugin: " + current, t);
+                String plugin_name = plugin.getClass().getName();
+                this.logger.error("Exception destroying plugin " + plugin_name, t);
             }
         }
     }
@@ -210,29 +220,29 @@
     throws KernelException {
 
         /* Retrieve and check the instance */
-        Instance instance = this.getInstance(name);
-        if (instance == null) {
+        Wrapper wrapper = (Wrapper) this.wrappers.get(name);
+        if (wrapper == null) {
             throw new KernelException("Block instance \"" + name + "\" unknown");
         }
 
         /* Prepare wiring and component */
-        Object component = this.singletons.get(instance);
+        Object component = this.singletons.get(name);
         if (component == null) try {
-            component = this.instantiate(name);
+            component = this.newComponentInstance(wrapper);
         } catch (Throwable t) {
             throw new KernelException("Unable to create non-singleton component "
-                    + " instance for block \"" + instance.getBlock().toString()
+                    + " instance for block \"" + wrapper.instance.getBlock()
                     + "\" instantiated with name \"" + name + "\"", t);
         }
         Wiring wiring = new Wiring(component); 
 
         /* Create and return the proxy instance */
-        Class interfaces[] = instance.getImplementedInterfaces();
+        Class interfaces[] = wrapper.instance.getImplementedInterfaces();
         try {
             return Proxy.newProxyInstance(this.loader, interfaces, wiring);
         } catch (Throwable t) {
             throw new KernelException("Unable to create component proxy instance "
-                    + " for block \"" + instance.getBlock().toString()
+                    + " for block \"" + wrapper.instance.getBlock()
                     + "\" instantiated with name \"" + name + "\"", t);
         }
     }
@@ -258,45 +268,26 @@
     /**
      * <p>Push a new {@link Block} {@link Instance} into this {@link Runtime}.</p>
      */
-    protected void putInstance(String name, Instance inst, Configuration conf) {
+    protected void addInstance(String name, Instance inst, Configuration conf)
+    throws DeployerException {
         if (name == null) throw new NullPointerException("Null name");
         if (inst == null) throw new NullPointerException("Null instance");
         if (conf == null) throw new NullPointerException("Null config");
-        this.wrappers.put(name, new Wrapper(inst, conf));
+        if (this.wrappers.get(name) != null) {
+            throw new DeployerException("Instance \"" + name + "\" aready added");
+        } else {
+            this.wrappers.put(name, new Wrapper(inst, conf));
+        }
 
-        Iterator iterator = this.plugins.keySet().iterator();
+        Iterator iterator = this.plugins.iterator();
         while (iterator.hasNext()) {
-            String plugin = (String) iterator.next();
-            Configuration curr = conf.child(plugin);
-            ((Plugin)this.plugins.get(plugin)).notify(inst, curr);
+            Plugin plugin = (Plugin) iterator.next();
+            Configuration curr = conf.child(plugin.getConfigurationElement());
+            plugin.notify(inst, curr);
         }
     }
 
     /**
-     * <p>Return the {@link Block} associated with the given name.</p>
-     */
-    protected Block getBlock(String name) {
-        Wrapper wrapper = (Wrapper) this.wrappers.get(name);
-        return (wrapper == null? null : wrapper.instance.getBlock());
-    }
-
-    /**
-     * <p>Return the {@link Instance} associated with the given name.</p>
-     */
-    protected Instance getInstance(String name) {
-        Wrapper wrapper = (Wrapper) this.wrappers.get(name);
-        return (wrapper == null? null : wrapper.instance);
-    }
-
-    /**
-     * <p>Return the {@link Configuration} associated with the given name.</p>
-     */
-    protected Configuration getConfiguration(String name) {
-        Wrapper wrapper = (Wrapper) this.wrappers.get(name);
-        return (wrapper == null? null : wrapper.configuration);
-    }
-    
-    /**
      * <p>Return the {@link Library} associated with this {@link Runtime}.</p>
      */
     protected Library getLibrary() {
@@ -317,40 +308,57 @@
     /**
      * <p>Instantiate a new component given its block instance and name.</p>
      */
-    private Object instantiate(String name)
+    private Object newComponentInstance(Wrapper wrapper)
     throws DeployerException {
-        Instance instance = this.getInstance(name);
-        if (instance == null) {
-            throw new DeployerException("Invalid instance \"" + name + "\"");
-        }
+        Instance instance = wrapper.instance;
+        Configuration configuration = wrapper.configuration;
+        String name = instance.getName();
 
-        /* Prepare a new instance */
+        /* Prepare a new component instance */
         Object component = null;
         Class clazz = instance.getComponentClass();
+        Thread thread = Thread.currentThread();
+        ClassLoader context = thread.getContextClassLoader();
+        thread.setContextClassLoader(instance);
         try {
             component = clazz.newInstance();
         } catch (Throwable t) {
             throw new DeployerException("Can't instantiate " + clazz.getName(), t);
+        } finally {
+            thread.setContextClassLoader(context);
         }
 
         /* Configure this component instance */
-        Configuration configuration = this.getConfiguration(name);
         if (this.initializing.contains(name)) {
+            thread.setContextClassLoader(context);
             throw new DeployerException("Circular dependancy found initializing "
                     + "instance \"" + name + "\"");
         } else {
             this.initializing.add(name);
-            Factory.configure(component, this, configuration);
+            /* Configure with the defaults and with the local configuration */
+            Configuration defaults = instance.getBlock().getComponentDefaults();
+            context = thread.getContextClassLoader();
+            thread.setContextClassLoader(instance);
+            try {
+                Factory.configure(component, this, defaults);
+                Factory.configure(component, this, configuration);
+            } finally {
+                thread.setContextClassLoader(context);
+            }
             this.initializing.remove(name);
         }
 
         /* Initialize the component and prepare the wiring */
         Method initializer = instance.getComponentInitializerMethod();
+        context = thread.getContextClassLoader();
+        thread.setContextClassLoader(instance);
         try {
             /* Non singletons will never have an initializer method set */
             if (initializer != null) initializer.invoke(component, NULL);
         } catch (Throwable t) {
             throw new DeployerException("Can't initialize component " + name, t);
+        } finally {
+            thread.setContextClassLoader(context);
         }
 
         /* Return the initialized component */

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	Thu Nov  4 14:58:41 2004
@@ -14,6 +14,7 @@
 
 import java.beans.PropertyDescriptor;
 import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Proxy;
 import java.net.URL;
 import java.util.HashSet;
@@ -109,7 +110,7 @@
                         + block + " declared at " + current.location());
             }
             Instance instance = new Instance(deployer, (Block) descriptor, name);
-            deployer.putInstance(name, instance, current);
+            deployer.addInstance(name, instance, current);
         } catch (DeployerException e) {
             throw e;
         } catch (Throwable t) {
@@ -151,6 +152,9 @@
                 Object value = curr.getAttributeAs("value", type);
                 descr.getWriteMethod().invoke(obj, new Object[] { value });
                 continue;
+            } catch (InvocationTargetException e) {
+                throw new DeployerException("Unable to set value for property \""
+                        + prop + "\" specified at " + curr.location(), e.getCause());
             } catch (Throwable t) {
                 throw new DeployerException("Unable to set value for property \""
                         + prop + "\" specified at " + curr.location(), t);
@@ -161,6 +165,9 @@
                 Object value = depl.lookup(curr.getStringAttribute("component"));
                 descr.getWriteMethod().invoke(obj, new Object[] { value });
                 continue;
+            } catch (InvocationTargetException e) {
+                throw new DeployerException("Unable to set component for property \""
+                        + prop + "\" specified at " + curr.location(), e.getCause());
             } catch (Throwable t) {
                 throw new DeployerException("Unable to set component for property \""
                         + prop + "\" specified at " + curr.location(), t);
@@ -187,7 +194,9 @@
 
                 /* No exceptions, continue */
                 continue;
-
+            } catch (InvocationTargetException e) {
+                throw new DeployerException("Unable to set component for property \""
+                        + prop + "\" specified at " + curr.location(), e.getCause());
             } catch (Throwable t) {
                 throw new DeployerException("Unable to set component for property \""
                         + prop + "\" specified at " + curr.location(), t);
@@ -200,6 +209,9 @@
                 Object value = Proxy.newProxyInstance(depl.getLoader(), i, w);
                 descr.getWriteMethod().invoke(obj, new Object[] { value });
                 continue;
+            } catch (InvocationTargetException e) {
+                throw new DeployerException("Unable to set kernel for property \""
+                        + prop + "\" specified at " + curr.location(), e.getCause());
             } catch (Throwable t) {
                 throw new DeployerException("Unable to set kernel for property \""
                         + prop + "\" specified at " + curr.location(), 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	Thu Nov  4 14:58:41 2004
@@ -228,4 +228,57 @@
         /* Pop from the dependencies check */
         dependencies.pop(identifier);
     }
+
+    /**
+     * <p>Return a {@link String} representation of this instance.</p>
+     */
+    public String toString() {
+        return(super.toString() + "{" + this.getName() + "}");
+    }
+
+    /**
+     * <p>Invert the {@link Class} load order of this {@link ClassLoader}.</p>
+     */
+    public synchronized Class loadClass(String name)
+    throws ClassNotFoundException {
+        return this.loadClass(name, false);
+    }
+
+    /**
+     * <p>Invert the {@link Class} load order of this {@link ClassLoader}.</p>
+     */
+    protected synchronized Class loadClass(String name, boolean resolve)
+    throws ClassNotFoundException { 
+        Class clazz = findLoadedClass(name);
+        if (clazz != null) return(clazz);
+        
+        /* Just in case some dummy put the kernel implementation in the path */
+        if ((name.equals("org.apache.cocoon.kernel.Kernel")) ||
+            (name.equals("org.apache.cocoon.kernel.KernelException")) ||
+            (name.startsWith("org.apache.cocoon.kernel.configuration.")) ||
+            (name.startsWith("org.apache.cocoon.kernel.startup"))) {
+            return super.loadClass(name, resolve);
+        }
+
+        try {
+            clazz= this.findClass(name);
+        } catch (ClassNotFoundException e) {
+            clazz = this.getParent().loadClass(name);
+        }
+
+        if (resolve) resolveClass(clazz);
+        return clazz;
+    }
+
+    /**
+     * <p>Invert the resource resolution order of this {@link ClassLoader}.</p>
+     */
+    public synchronized URL getResource(String name) {
+        URL url= null;
+
+        url= this.findResource(name);
+        if (url == null) url= this.getParent().getResource(name);
+
+        return url;
+    }    
 }

Modified: cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/description/Block.java
==============================================================================
--- cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/description/Block.java	(original)
+++ cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/description/Block.java	Thu Nov  4 14:58:41 2004
@@ -37,6 +37,8 @@
     private Identifier[] implementations = null;
     /** <p>The array of identifiers of all required modules.</p> */
     private Identifier[] requirements = null;
+    /** <p>The default {@link Configuration} for components.</p> */
+    private Configuration defaults = null;
 
     /**
      * <p>Create a new {@link Block} instance.</p>
@@ -79,6 +81,9 @@
             throw new DeployerException("Non-singleton component declares "
                     + "initializer or destroyer method at " + provides.location());
         }
+        
+        /* The default configuration */
+        this.defaults = configuration.child(NAMESPACE, "defaults");
     }
 
     /**
@@ -100,6 +105,14 @@
      */
     public String getComponentDestroyer() {
         return(this.initializer);
+    }
+
+    /**
+     * <p>Return the default {@link Configuration} for instances of this
+     * {@link Block}.</p>
+     */
+    public Configuration getComponentDefaults() {
+        return(this.defaults);
     }
 
     /**

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	Thu Nov  4 14:58:41 2004
@@ -12,7 +12,12 @@
  * =============================================================================== */
 package org.apache.cocoon.kernel.description;
 
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
 import org.apache.cocoon.kernel.configuration.Configuration;
+import org.apache.cocoon.kernel.configuration.ConfigurationException;
 import org.apache.cocoon.kernel.deployment.DeployerException;
 
 /**
@@ -25,10 +30,8 @@
  */
 public class Extension extends Descriptor {
 
-    /** <p>The name of the provided Java plugin.</p> */ 
-    private String clazz = null;
-    /** <p>The name of the configuration element in the instances file.</p> */
-    private String element = null;
+    /** <p>The class names of the provided Java plugins.</p> */ 
+    private String plugins[] = null;
 
     /**
      * <p>Create a new {@link Extension} instance.</p>
@@ -44,32 +47,30 @@
         }
 
         /* Plugin provision */
-        Configuration plugin = configuration.child(NAMESPACE, "plugin");
-        this.clazz = plugin.getStringAttribute("class", null);
-
-        /* No class? Abstract block, only libraries */
-        if (this.clazz == null) {
-            throw new DeployerException("Extension descriptor does not specify "
-                    + "  plugin class name at " + plugin.location());
+        Set classes = new HashSet();
+        Iterator iterator = configuration.children(NAMESPACE, "plugin");
+        while (iterator.hasNext()) try {
+            Configuration plugin = (Configuration) iterator.next();
+            classes.add(plugin.getStringAttribute("class"));
+        } catch (ConfigurationException exception) {
+            Configuration current = exception.getConfiguration();
+            if (current == null) current = configuration;
+            String message = "Extension descriptor does not specify plugin ";
+            message += "class name at " + current.location();
+            throw new DeployerException(message, exception);
         }
-
-        /* Process initializer, destroyer, and singleton */
-        this.element = plugin.getStringAttribute("configuration-element", null);
+        this.plugins = new String[classes.size()];
+        this.plugins = (String []) classes.toArray(this.plugins);
+        
+        /* Retrieve the plugin configuration element name */
+        configuration = configuration.child("configuration");
     }
 
     /**
      * <p>Return the class name of the provided Java&trade; class.</p>
      */
-    public String getPlugin() {
-        return(this.clazz);
-    }
-
-    /**
-     * <p>Return the name of the element to be looked up in the configuration file
-     * containing the configuration of this plugin.</p>
-     */
-    public String getPluginConfigurationElement() {
-        return(this.element);
+    public String[] getPluginClassNames() {
+        return(this.plugins);
     }
 
     /**

Modified: cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/plugins/AbstractPlugin.java
==============================================================================
--- cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/plugins/AbstractPlugin.java	(original)
+++ cocoon/whiteboard/kernel/sources/runtime/org/apache/cocoon/kernel/plugins/AbstractPlugin.java	Thu Nov  4 14:58:41 2004
@@ -24,20 +24,35 @@
  * @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 {
+public abstract 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>The element configuration name.</p> */
+    private String element = null;
 
     /**
      * <p>Create a new {@link AbstractPlugin} instance.</p>
      */
-    public AbstractPlugin() {
-        super();
+    protected AbstractPlugin() {
+        this(null);
     }
 
+    /**
+     * <p>Create a new {@link AbstractPlugin} instance.</p>
+     */
+    protected AbstractPlugin(String element) {
+        this.element = element;
+    }
+
+    /**
+     * <p>Return the configuration element name associated with this plugin.</p>
+     */
+    public String getConfigurationElement() {
+        return this.element;
+    }
     /**
      * <p>Configure this plugin from a specified {@link Configuration}.</p>
      * 

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	Thu Nov  4 14:58:41 2004
@@ -38,6 +38,11 @@
 public interface Plugin {
 
     /**
+     * <p>Return the configuration element name associated with this plugin.</p>
+     */
+    public String getConfigurationElement();
+    
+    /**
      * <p>Configure this plugin from a specified {@link Configuration}.</p>
      */
     public void configure(StartupKernel kernel, Configuration configuration);