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 [EMAIL PROTECTED] Set} containing all components being initialized.</p> */ private Set initializing = new HashSet(); /** <p>A [EMAIL PROTECTED] Map} of all initialized plugins.</p> */ - private Map plugins = new HashMap(); + private Set plugins = new HashSet(); /** <p>A simple [EMAIL PROTECTED] Map} holding all instances and configurations.</p> */ private Map wrappers = new HashMap(); /** <p>A [EMAIL PROTECTED] 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 [EMAIL PROTECTED] Block} [EMAIL PROTECTED] Instance} into this [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 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 [EMAIL PROTECTED] Library} associated with this [EMAIL PROTECTED] 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 [EMAIL PROTECTED] String} representation of this instance.</p> + */ + public String toString() { + return(super.toString() + "{" + this.getName() + "}"); + } + + /** + * <p>Invert the [EMAIL PROTECTED] Class} load order of this [EMAIL PROTECTED] ClassLoader}.</p> + */ + public synchronized Class loadClass(String name) + throws ClassNotFoundException { + return this.loadClass(name, false); + } + + /** + * <p>Invert the [EMAIL PROTECTED] Class} load order of this [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 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 [EMAIL PROTECTED] Configuration} for components.</p> */ + private Configuration defaults = null; /** * <p>Create a new [EMAIL PROTECTED] 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 [EMAIL PROTECTED] Configuration} for instances of this + * [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 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™ 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 © 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 [EMAIL PROTECTED] StartupKernel} instance.</p> */ private StartupKernel kernel = null; /** <p>The global plugin [EMAIL PROTECTED] Configuration} member.</p> */ private Configuration config = null; + /** <p>The element configuration name.</p> */ + private String element = null; /** * <p>Create a new [EMAIL PROTECTED] AbstractPlugin} instance.</p> */ - public AbstractPlugin() { - super(); + protected AbstractPlugin() { + this(null); } + /** + * <p>Create a new [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 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 [EMAIL PROTECTED] Configuration}.</p> */ public void configure(StartupKernel kernel, Configuration configuration);