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/01 03:10:17 UTC

svn commit: rev 56181 - in cocoon/whiteboard/kernel: . src src/org src/org/apache src/org/apache/cocoon src/org/apache/cocoon/kernel src/org/apache/cocoon/kernel/configuration src/org/apache/cocoon/kernel/description src/org/apache/cocoon/kernel/runtime src/org/apache/cocoon/kernel/startup

Author: pier
Date: Sun Oct 31 18:10:16 2004
New Revision: 56181

Added:
   cocoon/whiteboard/kernel/
   cocoon/whiteboard/kernel/LICENSE.txt
   cocoon/whiteboard/kernel/src/
   cocoon/whiteboard/kernel/src/org/
   cocoon/whiteboard/kernel/src/org/apache/
   cocoon/whiteboard/kernel/src/org/apache/cocoon/
   cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/
   cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/Kernel.java
   cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/KernelException.java
   cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/configuration/
   cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/configuration/Configuration.java
   cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/configuration/ConfigurationBuilder.java
   cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/configuration/ConfigurationException.java
   cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/configuration/ConfigurationSerializer.java
   cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/configuration/Parameters.java
   cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/
   cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Block.java
   cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Descriptor.java
   cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Interface.java
   cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Library.java
   cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/
   cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/Deployer.java
   cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/Factory.java
   cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/Instance.java
   cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/Runtime.java
   cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/Wiring.java
   cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/startup/
   cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/startup/Main.java
Log:
Adding new dependancy-injection based Kernel

Added: cocoon/whiteboard/kernel/LICENSE.txt
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/LICENSE.txt	Sun Oct 31 18:10:16 2004
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.

Added: cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/Kernel.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/Kernel.java	Sun Oct 31 18:10:16 2004
@@ -0,0 +1,44 @@
+/* =============================================================================== *
+ * 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;
+
+/**
+ * <p>The {@link Kernel} interface describes the unique contract between the
+ * kernel internals and its blocks.</p> 
+ *
+ * <p>Note that <i>normally</i> blocks deployed by this {@link Kernel} won't have
+ * to know about this interface, as all configuration is done through dependancy
+ * injection using <i>&quot;Plain Old Java Objects&quot;</i> setters and getters.</p>
+ * 
+ * <p>Only objects requiring direct access to the {@link Kernel} itself and requiring
+ * to communicate with every part of the deployment environment will have to provide
+ * a simple <code>setKernel(Kernel kernel)</code> setter method which (when correctly
+ * configured) will be called with an instance of this interface.</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 interface Kernel {
+
+    /**
+     * <p>Returns the instance of a component deployed by the {@link Kernel}.</p>
+     * 
+     * @param name The name of the block instance deployed by this {@link Kernel}.
+     * @return A <b>non-null</b> object.
+     * @throws KernelException If an error occurred accessing the instance. 
+     */
+    public Object lookup(String name)
+    throws KernelException;
+
+}

Added: cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/KernelException.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/KernelException.java	Sun Oct 31 18:10:16 2004
@@ -0,0 +1,38 @@
+/* =============================================================================== *
+ * 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;
+
+/**
+ * <p>A {@link KernelException} is thrown whenever an error occurred in the lookup
+ * operation performed by the {@link Kernel}.</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 KernelException extends Exception {
+
+    /**
+     * <p>Create a new {@link KernelException} instance.</p>
+     */
+    public KernelException(String message) {
+        super(message);
+    }
+
+    /**
+     * <p>Create a new {@link KernelException} instance.</p>
+     */
+    public KernelException(String message, Throwable throwable) {
+        super(message, throwable);
+    }
+}

Added: cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/configuration/Configuration.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/configuration/Configuration.java	Sun Oct 31 18:10:16 2004
@@ -0,0 +1,1159 @@
+/* =============================================================================== *
+ * 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.configuration;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * <p>The {@link Configuration} class provides an XML/DOM-like view over a
+ * set of configurable {@link Parameters}.</p>
+ *
+ * <p>In the context of a {@link Configuration}, {@link Parameters} are seen
+ * as &quot;attributes&quot; of the configuration element itself.</p>
+ *
+ * <p>Furthermore a number of methods have been added to retrieve the node
+ * namespace, name, and value, effectively allowing an XML-like structure
+ * to be mapped into a {@link Configuration}.</p>
+ *
+ * <p>This is <b>not</b> a complete XML representation of a document, as the
+ * {@link Configuration} class does no allow text nodes to be intermixed with
+ * children {@link Configuration} nodes, does not support comments and/or
+ * processing instructions and most important <b>does not support attribute
+ * name spaces</b>.</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 Configuration extends ArrayList {
+
+    /** <p>Whether this instance is locked or not.</p> */
+    private boolean locked = false;
+    
+    /** <p>The name of this {@link Configuration} element. */
+    private String name = null;
+
+    /** <p>The namespace associated with this {@link Configuration} element. */
+    private String namespace = null;
+
+    /** <p>The value of {@link Configuration} element. */
+    private Object value = null;
+
+    /** <p>The {@link Parameters} instance to use as attributes. */
+    private Parameters attributes = null;
+    
+    /** <p>The configuration location (if any).</p> */
+    private String location = null;
+
+    /** <p>The configuration location URL (if any).</p> */
+    private URL url = null;
+    
+    /** <p>The hash code of this instance.</p> */
+    private int hash = 0;
+    
+    /* ====================================================================== */
+    
+    /**
+     * <p>Create a new empty {@link Configuration} element to be used only
+     * when returning unavailable children.</p>
+     */
+    private Configuration() {
+        super();
+        this.name = "";
+        this.namespace = null;
+        this.attributes = new Parameters();
+        this.lock();
+        this.hash = 0;
+    }
+
+    /**
+     * <p>Create a new {@link Configuration} element with a specified name.</p>
+     *
+     * @param name this {@link Configuration} element name.
+     * @throws NullPointerException if the specified name was <b>null</b>.
+     * @throws IllegalArgumentException if the specified name was empty.
+     */
+    public Configuration(String name) {
+        this(null, name, null);
+    }
+
+    /**
+     * <p>Create a new {@link Configuration} element with a specified name and
+     * an optional namespace associated with it.</p>
+     *
+     * @param name this {@link Configuration} element name.
+     * @param namespace the name space associated with the element name.
+     * @throws NullPointerException if the specified name was <b>null</b>.
+     * @throws IllegalArgumentException if the specified name was empty.
+     */
+    public Configuration(String namespace, String name) {
+        this(namespace, name, null);
+    }
+
+    /**
+     * <p>Create a new {@link Configuration} element with a specified name and
+     * a {@link Parameters} instance to use as element attributes.</p>
+     *
+     * @param name this {@link Configuration} element name.
+     * @param attributes the {@link Parameters} instance to use as attributes.
+     * @throws NullPointerException if the specified name was <b>null</b>.
+     * @throws IllegalArgumentException if the specified name was empty.
+     */
+    public Configuration(String name, Parameters attributes) {
+        this(null, name, attributes);
+    }
+    
+    /**
+     * <p>Create a new {@link Configuration} element with a specified name, an
+     * optional namespace associated with it and a {@link Parameters} instance
+     * to use as element attributes.</p>
+     *
+     * @param name this {@link Configuration} element name.
+     * @param namespace the name space associated with the element name.
+     * @param attributes the {@link Parameters} instance to use as attributes.
+     * @throws NullPointerException if the specified name was <b>null</b>.
+     * @throws IllegalArgumentException if the specified name was empty.
+     */
+    public Configuration(String namespace, String name, Parameters attributes) {
+        super();
+        if (name == null) throw new NullPointerException("Null name");
+        if (name.equals("")) throw new IllegalArgumentException("Empty name");
+        this.name = name;
+        this.namespace = ("".equals(namespace)? null: namespace);
+        this.attributes = (attributes == null? new Parameters(): attributes);
+        this.hash = new String(this.namespace + "|" + this.name).hashCode();
+    }
+
+    /* ====================================================================== */
+    
+    /**
+     * <p>Lock this {@link Configuration} instance.</p>
+     *
+     * <p>After this method is called, no further modifications are allowed
+     * into this {@link Configuration} instance, and any modification operation
+     * will throw a {@link ConfigurationException}.</p>
+     *
+     * @return this {@link Configuration} instance.
+     */
+    public Configuration lock() {
+        this.locked = true;
+        return(this);
+    }
+    
+    /* ====================================================================== */
+    
+    /**
+     * <p>Return the name of this {@link Configuration} element.</p>
+     */
+    public String name() {
+        return(this.name);
+    }
+
+    /**
+     * <p>Return the namespace declaration (if any) associated with this
+     * {@link Configuration} element.</p>
+     */
+    public String namespace() {
+        return(this.namespace);
+    }
+
+    /**
+     * <p>Return the {@link Parameters} instance backing up attribute names
+     * and values.</p>
+     */
+    public Parameters attributes() {
+        return(this.attributes);
+    }
+    
+    /* ====================================================================== */
+
+    /**
+     * <p>Add the specified {@link Configuration} instance as a child of this
+     * instance at the end of this list.</p>
+     *
+     * @param child the child {@link Configuration}
+     * @return <b>true</b> if this list was modified, <b>false</b> otherwise.
+     * @throws NullPointerException if the child was <b>null</b>.
+     * @throws ClassCastException if the child was not a {@link Configuration}.
+     */
+    public boolean add(Object child) {
+        this.check(child);
+        return(super.add(child));
+    }
+
+    /**
+     * <p>Add the specified {@link Configuration} instance as a child of this
+     * instance at the specified offset.</p>
+     *
+     * @param index the offset where the child must be added.
+     * @param child the child {@link Configuration}
+     * @return <b>true</b> if this list was modified, <b>false</b> otherwise.
+     * @throws NullPointerException if the child was <b>null</b>.
+     * @throws ClassCastException if the child was not a {@link Configuration}.
+     */
+     public void add(int index, Object child) {
+         this.check(child);
+         super.add(index, child);
+     }
+     
+    /**
+     * <p>Add the specified collection of {@link Configuration} instances as
+     * children of this instance at the end of this list.</p>
+     *
+     * @param children the collection of children {@link Configuration}
+     * @return <b>true</b> if this list was modified, <b>false</b> otherwise.
+     * @throws NullPointerException if any of the children was <b>null</b>.
+     * @throws ClassCastException if any of the children was not a
+     *                            {@link Configuration} instance.
+     */
+    public boolean addAll(Collection children) {
+        if (children == null) return(false);
+        Iterator iterator = children.iterator();
+        while (iterator.hasNext()) this.check(iterator.next());
+        return(super.addAll(children));
+    }
+
+    /**
+     * <p>Add the specified collection of {@link Configuration} instances as
+     * children of this instance at the specified offset.</p>
+     *
+     * @param index the offset where the children must be added.
+     * @param children the collection of children {@link Configuration}
+     * @return <b>true</b> if this list was modified, <b>false</b> otherwise.
+     * @throws NullPointerException if any of the children was <b>null</b>.
+     * @throws ClassCastException if any of the children was not a
+     *                            {@link Configuration} instance.
+     */
+    public boolean addAll(int index,  Collection children) {
+        if (children == null) return(false);
+        Iterator iterator = children.iterator();
+        while (iterator.hasNext()) this.check(iterator.next());
+        return(super.addAll(index, children));
+    }
+
+    /**
+     * <p>Returns an unlocked deep copy of this {@link Configuration}
+     * instance.</p>
+     *
+     * <p>The value and attribute names and values themselves are not cloned,
+     * but the entire structure of all nested {@link Configuration} and
+     * {@link Parameters} instances will be cloned.</p>
+     *
+     * <p>The returned instance will not be locked.</p>
+     *
+     * @return a new <b>non null</b> cloned {@link Configuration} instance.
+     */
+    public Object clone() {
+        Configuration configuration = (Configuration) super.clone();
+        configuration.locked = false;
+
+        /* Clone attributes and children */
+        configuration.clear();
+        configuration.attributes = (Parameters)this.attributes.clone();
+        Configuration array[] = new Configuration[this.size()];
+        array = (Configuration [])this.toArray(array);
+        for (int x = 0; x < array.length; x ++) {
+            configuration.add(array[x].clone());
+        }
+        return(configuration);
+    }
+    
+    
+    
+    /* ====================================================================== */
+
+    /**
+     * <p>Return an {@link Iterator} over all children of this
+     * {@link Configuration} with a specified name.</p>
+     *
+     * @param name the name of all returned configuration children.
+     * @return a <b>non null</b> {@link Iterator}.
+     */
+    public Iterator children(String name) {
+        return(new ConfigurationIterator(this, null, name));
+    }
+
+    /**
+     * <p>Return an {@link Iterator} over all children of this
+     * {@link Configuration} with a specified name and namespace.</p>
+     *
+     * @param name the name of all returned configuration children.
+     * @param namespace the namespace of all returned configuration children.
+     * @return a <b>non null</b> {@link Iterator}.
+     */
+    public Iterator children(String namespace, String name) {
+        return(new ConfigurationIterator(this, namespace, name));
+    }
+    
+    /**
+     * <p>Return the first child {@link Configuration} instance with the
+     * specified name.</p>
+     *
+     * <p>If a child cannot be found an empty {@link Configuration} instance
+     * is returned. The returned {@link Configuration} will have an empty (and
+     * therefore illegal) name. To check if the element returned was the one
+     * requested, the suggested method is to proceed in the following way:</p>
+     *
+     * <pre>
+     * Configuration conf = configuration.child(name);
+     * if (!configuration.name().equals(name)) {
+     *   // There is no child with this name.
+     * }</pre>
+     *
+     * <p>The empty {@link Configuration} element is returned to allow
+     * constructs such as:</p>
+     *
+     * <pre>
+     * Configuration conf = configuration.child(name).child(name2).child(namex);
+     * </pre>
+     * 
+     * @param name the name of the returned configuration child.
+     * @return a <b>non null</b> {@link Configuration} element.
+     */
+    public Configuration child(String name) {
+        Iterator iterator = this.children(name);
+        if (iterator.hasNext()) return((Configuration)iterator.next());
+        Configuration child = new Configuration();
+        child.location = this.location;
+        child.url = this.url;
+        return(child);
+    }
+    
+    /**
+     * <p>Return the first child {@link Configuration} instance with the
+     * specified namespace and name.</p>
+     *
+     * <p>If a child cannot be found an empty {@link Configuration} instance
+     * is returned. The returned {@link Configuration} will have an empty (and
+     * therefore illegal) name. To check if the element returned was the one
+     * requested, the suggested method is to proceed in the following way:</p>
+     *
+     * <pre>
+     * Configuration conf = configuration.child(namespace, name);
+     * if (!configuration.name().equals(name)) {
+     *   // There is no child with this name.
+     * }</pre>
+     *
+     * <p>The empty {@link Configuration} element is returned to allow
+     * constructs such as:</p>
+     *
+     * <pre>
+     * Configuration conf = configuration.child(name).child(name2).child(namex);
+     * </pre>
+     * 
+     * @param name the name of the returned configuration child.
+     * @param namespace the namespace of the returned configuration child.
+     * @return a <b>non null</b> {@link Iterator}.
+     */
+    public Configuration child(String namespace, String name) {
+        Iterator iterator = this.children(namespace, name);
+        if (iterator.hasNext()) return((Configuration)iterator.next());
+        Configuration child = new Configuration();
+        child.location = this.location;
+        child.url = this.url;
+        return(child);
+    }
+
+    /* ====================================================================== */
+
+    /**
+     * <p>Create and return a {@link String} describing the location of this
+     * {@link Configuration} element, if known.</p>
+     *
+     * <p>The returned string will assume the following format:
+     * <code>file@line,column</code>.</p>
+     *
+     * @return a <b>non null</b> {@link String} describing the location.
+     */
+    public String location() {
+        return(this.location);
+    }
+
+    /**
+     * <p>Return (if possible) a URL absolutely locating this
+     * {@link Configuration} as a file or resource.</p>
+     *
+     * @return a {@link URL} instance or <b>null</b> if unknown.
+     */
+    public URL locationURL() {
+        return(this.url);
+    }
+    
+    /**
+     * Specify the location details for this {@link Configuration} item.
+     *
+     * @param location the path or URL of the source file.
+     * @param line the line number in the source file.
+     * @param column the column number in the source file.
+     */
+    public String locate(String location, int line, int column) {
+        try {
+            this.url = new URL(location);
+        } catch (MalformedURLException e) {
+            // Forget about this exception
+        }
+
+        /* Prepare the location string now */
+        String old = this.location;
+        this.location = location;
+        if (line < 0) return(old);
+        this.location += "@line=" + line;
+        if (column < 0) return(old);
+        this.location += ",column=" + column;
+        return(old);
+    }
+
+    /* ====================================================================== */
+
+    /**
+     * <p>Return the value of this {@link Configuration} element.</p>
+     *
+     * @return the value of this configuration.
+     * @throws ConfigurationException if the value was not set.
+     */
+    public Object getValue()
+    throws ConfigurationException {
+        if (this.value == null)
+            throw new ConfigurationException("Value not set", this);
+        return(this.value);
+    }
+
+    /**
+     * <p>Return the value of this {@link Configuration} element.</p>
+     *
+     * @return the value of this configuration or the specified default.
+     */
+    public Object getValue(Object defaultValue) {
+        return(this.value == null? defaultValue: value);
+    }
+    
+    /**
+     * <p>Set the value of this {@link Configuration} element.</p>
+     *
+     * @param value the value of this configuration element.
+     * @return the value of this configuration.
+     * @throws NullPointerException if the specified value was <b>null</b>.
+     */
+    public Object setValue(Object value) {
+        if (value == null) throw new NullPointerException("Null value");
+        Object old = this.value;
+        this.value = value;
+        return(old);
+    }
+
+    /**
+     * <p>Set the boolean value of this {@link Configuration} element.</p>
+     *
+     * @param value the value of this configuration element.
+     * @return the previous value of this configuration.
+     */
+    public Object setValue(boolean value) {
+        return this.setValue(new Boolean(value));
+    }
+    
+    /**
+     * <p>Set the double value of this {@link Configuration} element.</p>
+     *
+     * @param value the value of this configuration element.
+     * @return the previous value of this configuration.
+     */
+    public Object setValue(double value) {
+        return this.setValue(new Double(value));
+    }
+    
+    /**
+     * <p>Set the float value of this {@link Configuration} element.</p>
+     *
+     * @param value the value of this configuration element.
+     * @return the previous value of this configuration.
+     */
+    public Object setValue(float value) {
+        return this.setValue(new Float(value));
+    }
+    
+    /**
+     * <p>Set the int value of this {@link Configuration} element.</p>
+     *
+     * @param value the value of this configuration element.
+     * @return the previous value of this configuration.
+     */
+    public Object setValue(int value) {
+        return this.setValue(new Integer(value));
+    }
+    
+    /**
+     * <p>Set the long value of this {@link Configuration} element.</p>
+     *
+     * @param value the value of this configuration element.
+     * @return the previous value of this configuration.
+     */
+    public Object setValue(long value) {
+        return this.setValue(new Long(value));
+    }
+    
+    /**
+     * <p>Remove the value of this {@link Configuration} element.</p>
+     *
+     * @return the value of this configuration or <b>null</b>.
+     */
+    public Object removeValue() {
+        Object old = this.value;
+        this.value = null;
+        return(old);
+    }
+    
+    /* ====================================================================== */
+
+    /**
+     * <p>Return the boolean representation of this element value.</p>
+     *
+     * @return the boolean value of the element value.
+     * @throws ConfigurationException if the value was not found or could
+     *                                not be converted to a boolean.
+     */
+    public boolean getBooleanValue()
+    throws ConfigurationException {
+        Object object = this.getValue();
+        if (object instanceof Boolean) return(((Boolean)object).booleanValue());
+        String string = object.toString();
+        if ("0".equals(string)) return(false);
+        if ("1".equals(string)) return(true);
+        if ("false".equalsIgnoreCase(string)) return(false);
+        if ("true".equalsIgnoreCase(string)) return(true);
+        throw this.error("boolean", null);
+    }
+
+    /**
+     * <p>Return the boolean representation of this element value.</p>
+     *
+     * @param defaultValue the default value to assign if the value was
+     *                     not found or could not be converted.
+     * @return the boolean value of the element value or the specified default.
+     */
+    public boolean getBooleanValue(boolean defaultValue) {
+        try {
+            return(this.getBooleanValue());
+        } catch(ConfigurationException e) {
+            return(defaultValue);
+        }
+    }
+    
+    /* ====================================================================== */
+    
+    /**
+     * <p>Return the integer representation of this element value.</p>
+     *
+     * @return the integer value of the element value.
+     * @throws ConfigurationException if the value was not found or could
+     *                                not be converted to an integer.
+     */
+    public int getIntegerValue()
+    throws ConfigurationException {
+        Object object = this.getValue();
+        if (object instanceof Number) return(((Number)object).intValue());
+        try {
+            return(Integer.parseInt(object.toString()));
+        } catch (NumberFormatException e) {
+            throw this.error("int", e);
+        }
+    }
+    
+    /**
+     * <p>Return the integer representation of this element value.</p>
+     *
+     * @param defaultValue the default value to assign if the element value was
+     *                     not found or could not be converted.
+     * @return the integer value of the element value or the specified default.
+     */
+    public int getIntegerValue(int defaultValue) {
+        try {
+            return(this.getIntegerValue());
+        } catch(ConfigurationException e) {
+            return(defaultValue);
+        }
+    }
+    
+    /* ====================================================================== */
+    
+    /**
+     * <p>Return the long integer representation of this element value.</p>
+     *
+     * @throws ConfigurationException if the value was not found or could
+     *                                not be converted to a long integer.
+     */
+    public long getLongValue()
+    throws ConfigurationException {
+        Object object = this.getValue();
+        if (object instanceof Number) return(((Number)object).longValue());
+        try {
+            return(Long.parseLong(object.toString()));
+        } catch (NumberFormatException e) {
+            throw this.error("long", e);
+        }
+    }
+    
+    /**
+     * <p>Return the long integer representation of this element value.</p>
+     *
+     * @param defaultValue the default value to assign if the element value was
+     *                     not found or could not be converted.
+     * @return the long integer value of the element value or the specified default.
+     */
+    public long getLongValue(long defaultValue) {
+        try {
+            return(this.getLongValue());
+        } catch(ConfigurationException e) {
+            return(defaultValue);
+        }
+    }
+    
+    /* ====================================================================== */
+    
+    /**
+     * <p>Return the float representation of this element value.</p>
+     *
+     * @return the float value of the value.
+     * @throws ConfigurationException if the value was not found or could
+     *                                not be converted to a float.
+     */
+    public float getFloatValue()
+    throws ConfigurationException {
+        Object object = this.getValue();
+        if (object instanceof Number) return(((Number)object).floatValue());
+        try {
+            return(Float.parseFloat(object.toString()));
+        } catch (NumberFormatException e) {
+            throw this.error("float", e);
+        }
+    }
+
+    /**
+     * <p>Return the float representation of this element value.</p>
+     *
+     * @param defaultValue the default value to assign if the element value was
+     *                     not found or could not be converted.
+     * @return the float value of the element value or the specified default.
+     */
+    public float getFloatValue(float defaultValue) {
+        try {
+            return(this.getFloatValue());
+        } catch(ConfigurationException e) {
+            return(defaultValue);
+        }
+    }
+    
+    /* ====================================================================== */
+    
+    /**
+     * <p>Return the double representation of this element value.</p>
+     *
+     * @return the double value of the value.
+     * @throws ConfigurationException if the value was not found or could
+     *                                not be converted to a double.
+     */
+    public double getDoubleValue()
+    throws ConfigurationException {
+        Object object = this.getValue();
+        if (object instanceof Number) return(((Number)object).doubleValue());
+        try {
+            return(Double.parseDouble(object.toString()));
+        } catch (NumberFormatException e) {
+            throw this.error("double", e);
+        }
+    }
+
+    /**
+     * <p>Return the double representation of this element value.</p>
+     *
+     * @param defaultValue the default value to assign if the element value was
+     *                     not found or could not be converted.
+     * @return the double value of the element value or the specified default.
+     */
+    public double getDoubleValue(double defaultValue) {
+        try {
+            return(this.getDoubleValue());
+        } catch(ConfigurationException e) {
+            return(defaultValue);
+        }
+    }
+    
+    /* ====================================================================== */
+    
+    /**
+     * <p>Return the {@link String} representation of this element value.</p>
+     *
+     * <p>The returned {@link String} will be created invoking the
+     * {@link Object#toString() toString()} method on the value instance.</p>
+     *
+     * @return the {@link String} value of the element value.
+     * @throws ConfigurationException if the value was not found.
+     */
+    public String getStringValue()
+    throws ConfigurationException {
+        return(this.getValue().toString());
+   }
+    
+    /**
+     * <p>Return the {@link String} representation of this element value.</p>
+     *
+     * <p>The returned {@link String} will be created invoking the
+     * {@link Object#toString() toString()} method on the value instance.</p>
+     *
+     * @param defaultValue the default value to assign if the element value was
+     *                     not found or could not be converted.
+     * @return the {@link String} value of the element value or the specified default.
+     */
+    public String getStringValue(String defaultValue) {
+        try {
+            return(this.getStringValue());
+        } catch(ConfigurationException e) {
+            return(defaultValue);
+        }
+    }
+
+    /* ====================================================================== */
+    
+    /**
+     * <p>Return the value as a specific type.</p>
+     *
+     * @param type the {@link Class} type of the value to return.
+     * @return a <b>non null</b> object instance.
+     * @throws ConfigurationException if the attribute was not found or could
+     *                                not be converted to the specified type.
+     */
+    public Object getValueAs(Class type)
+    throws ConfigurationException {
+        if (Boolean.class.equals(type)) {
+            return new Boolean(this.getBooleanValue());
+        } else if (Double.class.equals(type)) {
+            return new Double(this.getDoubleValue());
+        } else if (Float.class.equals(type)) {
+            return new Float(this.getFloatValue());
+        } else if (Integer.class.equals(type)) {
+            return new Integer(this.getIntegerValue());
+        } else if (Long.class.equals(type)) {
+            return new Long(this.getLongValue());
+        } else if (String.class.equals(type)) {
+            return this.getStringValue();
+        }
+        throw new ConfigurationException("Unsupported type " + type.getName());
+    }
+
+    /* ====================================================================== */
+    
+    /**
+     * <p>Check if this configuration contains the specified attribute.</p>
+     *
+     * @param name the name of the attribute to check.
+     * @return <b>true</b> if the attribute was found, <b>false</b> otherwise.
+     */
+    public boolean hasAttribute(String name) {
+        return(this.attributes.containsKey(name));
+    }
+
+    /* ====================================================================== */
+    
+    /**
+     * <p>Return the attribute value.</p>
+     *
+     * @param name the name of the attribute to retrieve.
+     * @return the value of the attribute or <b>null</b> if the attribute was
+     *         not found.
+     */
+    public Object getAttribute(String name) {
+        return(this.attributes.get(name));
+    }
+    
+    /**
+     * <p>Return the attribute value.</p>
+     *
+     * @param name the name of the attribute.
+     * @param defaultValue the default value to return.
+     * @return the value of the attribute or the specified default.
+     */
+    public Object getAttribute(String name, Object defaultValue) {
+        return(this.attributes.get(name, defaultValue));
+    }
+    
+    /* ====================================================================== */
+    
+    /**
+     * <p>Return the boolean representation of the specified attribute.</p>
+     *
+     * @param name the name of the attribute to retrieve as a boolean.
+     * @return the boolean value of the attribute.
+     * @throws ConfigurationException if the attribute was not found or could
+     *                                not be converted to a boolean.
+     */
+    public boolean getBooleanAttribute(String name)
+    throws ConfigurationException {
+        try {
+            return(this.attributes.getBoolean(name));
+        } catch (ConfigurationException e) {
+            throw new ConfigurationException("Attribute \"" + name +  "\" "
+                                             + "invalid or not found", this);
+        }
+    }
+    
+    /**
+     * <p>Return the boolean representation of the specified attribute.</p>
+     *
+     * @param name the name of the attribute to retrieve as a boolean.
+     * @param defaultValue the default value to assign if the attribute was
+     *                     not found or could not be converted.
+     * @return the boolean value of the attribute or the specified default.
+     */
+    public boolean getBooleanAttribute(String name, boolean defaultValue) {
+        return(this.attributes.getBoolean(name, defaultValue));
+    }
+    
+    /* ====================================================================== */
+    
+    /**
+     * <p>Return the integer representation of the specified attribute.</p>
+     *
+     * @param name the name of the attribute to retrieve as an integer.
+     * @return the integer value of the attribute.
+     * @throws ConfigurationException if the attribute was not found or could
+     *                                not be converted to an integer.
+     */
+    public int getIntegerAttribute(String name)
+    throws ConfigurationException {
+        try {
+            return(this.attributes.getInteger(name));
+        } catch (ConfigurationException e) {
+            throw new ConfigurationException("Attribute \"" + name +  "\" "
+                                             + "invalid or not found", this);
+        }
+    }
+    
+    /**
+     * <p>Return the integer representation of the specified attribute.</p>
+     *
+     * @param name the name of the attribute to retrieve as a integer.
+     * @param defaultValue the default value to assign if the attribute was
+     *                     not found or could not be converted.
+     * @return the integer value of the attribute or the specified default.
+     */
+    public int getIntegerAttribute(String name, int defaultValue) {
+        return(this.attributes.getInteger(name, defaultValue));
+    }
+    
+    /* ====================================================================== */
+    
+    /**
+     * <p>Return the long integer representation of the specified attribute.</p>
+     *
+     * @param name the name of the attribute to retrieve as a long integer.
+     * @return the long integer value of the attribute.
+     * @throws ConfigurationException if the attribute was not found or could
+     *                                not be converted to a long integer.
+     */
+    public long getLongAttribute(String name)
+    throws ConfigurationException {
+        try {
+            return(this.attributes.getLong(name));
+        } catch (ConfigurationException e) {
+            throw new ConfigurationException("Attribute \"" + name +  "\" "
+                                             + "invalid or not found", this);
+        }
+    }
+    
+    /**
+     * <p>Return the long integer representation of the specified attribute.</p>
+     *
+     * @param name the name of the attribute to retrieve as a long integer.
+     * @param defaultValue the default value to assign if the attribute was
+     *                     not found or could not be converted.
+     * @return the long integer value of the attribute or the specified default.
+     */
+    public long getLongAttribute(String name, long defaultValue) {
+        return(this.attributes.getLong(name, defaultValue));
+    }
+    
+    /* ====================================================================== */
+    
+    /**
+        * <p>Return the float representation of the specified attribute.</p>
+     *
+     * @param name the name of the attribute to retrieve as a float.
+     * @return the float value of the attribute.
+     * @throws ConfigurationException if the attribute was not found or could
+     *                                not be converted to a float.
+     */
+    public float getFloatAttribute(String name)
+    throws ConfigurationException {
+        try {
+            return(this.attributes.getFloat(name));
+        } catch (ConfigurationException e) {
+            throw new ConfigurationException("Attribute \"" + name +  "\" "
+                                             + "invalid or not found", this);
+        }
+    }
+    
+    /**
+     * <p>Return the float representation of the specified attribute.</p>
+     *
+     * @param name the name of the attribute to retrieve as a float.
+     * @param defaultValue the default value to assign if the attribute was
+     *                     not found or could not be converted.
+     * @return the float value of the attribute or the specified default.
+     */
+    public float getFloatAttribute(String name, float defaultValue) {
+        return(this.attributes.getFloat(name, defaultValue));
+    }
+    
+    /* ====================================================================== */
+    
+    /**
+     * <p>Return the double representation of the specified attribute.</p>
+     *
+     * @param name the name of the attribute to retrieve as a double.
+     * @return the double value of the attribute.
+     * @throws ConfigurationException if the attribute was not found or could
+     *                                not be converted to a doube.
+     */
+    public double getDoubleAttribute(String name)
+    throws ConfigurationException {
+        try {
+            return(this.attributes.getDouble(name));
+        } catch (ConfigurationException e) {
+            throw new ConfigurationException("Attribute \"" + name +  "\" "
+                                             + "invalid or not found", this);
+        }
+    }
+    
+    /**
+     * <p>Return the double representation of the specified attribute.</p>
+     *
+     * @param name the name of the attribute to retrieve as a double.
+     * @param defaultValue the default value to assign if the attribute was
+     *                     not found or could not be converted.
+     * @return the double value of the attribute or the specified default.
+     */
+    public double getDoubleAttribute(String name, double defaultValue) {
+        return(this.attributes.getDouble(name, defaultValue));
+    }
+    
+    /* ====================================================================== */
+    
+    /**
+     * <p>Return the {@link String} representation of the specified attribute.</p>
+     *
+     * <p>The returned {@link String} will be created invoking the
+     * {@link Object#toString() toString()} method on the value instance.</p>
+     *
+     * @param name the name of the attribute to retrieve as a {@link String}.
+     * @return the {@link String} value of the attribute.
+     * @throws ConfigurationException if the attribute was not found.
+     */
+    public String getStringAttribute(String name)
+    throws ConfigurationException {
+        try {
+            return(this.attributes.getString(name));
+        } catch (ConfigurationException e) {
+            throw new ConfigurationException("Attribute \"" + name +  "\" "
+                                             + "invalid or not found", this);
+        }
+    }
+    
+    /**
+     * <p>Return the {@link String} representation of the specified attribute.</p>
+     *
+     * <p>The returned {@link String} will be created invoking the
+     * {@link Object#toString() toString()} method on the value instance.</p>
+     *
+     * @param name the name of the attribute to retrieve as a {@link String}.
+     * @param defaultValue the default value to assign if the attribute was
+     *                     not found or could not be converted.
+     * @return the {@link String} value of the attribute or the specified default.
+     */
+    public String getStringAttribute(String name, String defaultValue) {
+        return(this.attributes.getString(name, defaultValue));
+    }
+    
+    /* ====================================================================== */
+    
+    /**
+     * <p>Return the specified attribute value as a specific type.</p>
+     *
+     * @param name the name of the attribute to return.
+     * @param type the {@link Class} type of the value to return.
+     * @return a <b>non null</b> object instance.
+     * @throws ConfigurationException if the attribute was not found or could
+     *                                not be converted to the specified type.
+     */
+    public Object getAttributeAs(String name, Class type)
+    throws ConfigurationException {
+        if (Boolean.class.equals(type)) {
+            return new Boolean(this.getBooleanAttribute(name));
+        } else if (Double.class.equals(type)) {
+            return new Double(this.getDoubleAttribute(name));
+        } else if (Float.class.equals(type)) {
+            return new Float(this.getFloatAttribute(name));
+        } else if (Integer.class.equals(type)) {
+            return new Integer(this.getIntegerAttribute(name));
+        } else if (Long.class.equals(type)) {
+            return new Long(this.getLongAttribute(name));
+        } else if (String.class.equals(type)) {
+            return this.getStringAttribute(name);
+        }
+        throw new ConfigurationException("Unsupported type " + type.getName());
+    }
+
+    /* ====================================================================== */
+
+    /**
+     * <p>Return a human readable {@link String} representation of this
+     * {@link Configuration} instance.</p>
+     *
+     * @return a <b>non null</b> {@link String}.
+     */
+    public String toString() {
+        String value = getClass().getName() + "[" + name() + "]@" + hashCode();
+        return(value);
+    }
+
+    /**
+     * <p>Return the hash code of this {@link Configuration} instance.</p>
+     *
+     * @return the hash code.
+     */
+    public int hashCode() {
+        return(this.hash);
+    }
+
+    /**
+     * <p>Compare an {@link Object} for equality.</p>
+     *
+     * @param o an {@link Object} to compare for equality.
+     * @return <b>true</b> if the object equals this, <b>false</b> otherwise.
+     */
+    public boolean equals(Object o) {
+        /* Simple check */
+        if (o == null) return (false);
+        if (o == this) return (true);
+        return(false);
+    }
+    
+    /* ====================================================================== */
+
+    /**
+     * <p>Simple method to check the value of a child.</p>
+     */
+    private void check(Object child) {
+        if (child == null) throw new NullPointerException("Can't add null");
+        if (child instanceof Configuration) return;
+        throw new ClassCastException("Unable to add non Configuration child");
+    }
+
+    /**
+     * <p>Simple method to throw a nicely formatted exception.</p>
+     */
+    private ConfigurationException error(String type, Throwable throwable) {
+        return new ConfigurationException("Value \""+ this.getStringValue("?")
+                                          + "\" can "+ "not be converted to a "
+                                          + type, this, throwable);
+    }
+
+    /**
+     * <p>A simple iterator over children configurations.</p>
+     */
+    private static class ConfigurationIterator implements Iterator {
+        /** <p>The next configuration element.</p> */
+        private Configuration configuration = null;
+
+        /** <p>The sub-iterator from where to fetch elements.</p> */
+        private Iterator iterator = null;
+
+        /** <p>The namespace of the {@link Configuration}s to return.</p> */
+        private String namespace = null;
+
+        /** <p>The name of the {@link Configuration}s to return.</p> */
+        private String name = null;
+
+        /**
+         * <p>Create a new {@link ConfigurationIterator} returning a selected
+         * part of the children of a specified {@link Configuration}.</p>
+         *
+         * @param c the {@link Configuration} to iterate for children.
+         * @param ns the namespace of the {@link Configuration}s to return.
+         * @param n the name of the {@link Configuration}s to return.
+         */
+        private ConfigurationIterator(Configuration c, String ns, String n) {
+            this.iterator = c.iterator();
+            this.namespace = ns;
+            this.name = n;
+        }
+
+        /**
+         * <p>Check if this {@link Iterator} can return the next element.</p>
+         *
+         * @author <a href="mailto:pier@apache.org">Pier Fumagalli</a>
+         * @version 1.0 (CVS $Revision: 1.4 $)
+         */
+        public boolean hasNext() {
+            /* No name, no children. Bye! */
+            if (this.name == null) return(false);
+
+            /* Run on the nested iterator */
+            while(this.iterator.hasNext()) {
+
+                /* Return the next child configuration, whatever it is */
+                Configuration child = (Configuration)iterator.next();
+
+                /* If we process namespaces check both name and namespace */
+                if (this.namespace != null) {
+                    if ((!this.namespace.equals(child.namespace()))
+                        || (!this.name.equals(child.name()))) continue;
+
+                /* If we process only names, check only the name */
+                } else if (!this.name.equals(child.name())) continue;
+
+                /* If we didn't "continue" before, we have a match */
+                this.configuration = child;
+                return(true);
+            }
+            /* The nested iterator doesn't have any more children */
+            return(false);
+        }
+
+        /**
+         * <p>Return the next {@link Configuration} element available to this
+         * {@link ConfigurationIterator}.</p>
+         */
+        public Object next() {
+            /* If the "hasNext()" method didn't produce anything, try it */
+            if ((this.configuration == null) && (!this.hasNext())) {
+                throw new NoSuchElementException("Next element not found");
+            }
+            
+            /* Return and invalidate the "next" object */
+            Configuration current = this.configuration;
+            this.configuration = null;
+            return(current);
+        }
+
+        /**
+         * <p>Block anyone attempting to remove only children.</p>
+         */
+        public void remove() {
+            throw new UnsupportedOperationException("Use a normal iterator");
+        }
+    }
+}

Added: cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/configuration/ConfigurationBuilder.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/configuration/ConfigurationBuilder.java	Sun Oct 31 18:10:16 2004
@@ -0,0 +1,271 @@
+/* =============================================================================== *
+ * 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.configuration;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * <p>The {@link ConfigurationBuilder} builds {@link Configuration} instances
+ * from XML data.</p>
+ *
+ * <p>This class can be instantiated and used directly as a SAX
+ * {@link DefaultHandler} to use with any SAX-2 compliant parser.</p>
+ *
+ * <p>Otherwise a simple static {@link #parse(InputSource)} method is provided
+ * using the default JAXP implementation of the platform to parse XML documents
+ * and producing {@link Configuration} instances.</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 ConfigurationBuilder extends DefaultHandler {
+
+    /** <p>The returnable {@link Configuration} element.</p> */
+    private Configuration configuration = null;
+
+    /** <p>The current {@link Configuration} element.</p> */
+    private Configuration current = null;
+    
+    /** <p>The stack of {@link Configuration} elements.</p> */
+    private List stack = new ArrayList();
+
+    /** <p>The buffer holding element values.</p> */
+    private StringBuffer buffer = null;
+
+    /** <p>The current {@link Locator}.</p> */
+    private Locator locator = null;
+
+    /**
+     * <p>Create a new {@link ConfigurationBuilder} instance.</p>
+     */
+    public ConfigurationBuilder() {
+        super();
+    }
+
+    /**
+     * <p>Return the parsed {@link Configuration} instance.</p>
+     *
+     * @return the parsed {@link Configuration} or <b>null</b>.
+     */
+    public Configuration configuration() {
+        return(this.configuration);
+    }
+
+    /**
+     * <p>Receive a {@link Locator} object to locate the different document
+     * events.</p>
+     *
+     * @param locator a <b>non null</b> {@link Locator} instance.
+     */
+    public void setDocumentLocator (Locator locator) {
+        this.locator = locator;
+    }
+    
+    /**
+     * <p>Receive notification of the beginning of the document.</p>
+     *
+     * <p>This method will effectively reset the {@link Configuration} item
+     * being parsed.</p>
+     */
+    public void startDocument ()
+    throws SAXException {
+        this.current = null;
+    }
+
+    /**
+     * <p>Receive notification of the end of the document.</p>
+     *
+     * <p>This method will effectively mark the {@link Configuration} item
+     * being parsed as returnable by the {@link #configuration()} method.</p>
+     */
+    public void endDocument ()
+    throws SAXException {
+        this.configuration = this.current;
+    }
+    
+    /**
+     * <p>Receive notification of the start of an element.</p>
+     *
+     * @param uri the namespace URI of the element.
+     * @param local the local name of the element.
+     * @param qualified the fully qualified name of the element.
+     * @param attributes all the XML attributes of the element.
+     */
+    public void startElement(String uri, String local, String qualified,
+                             Attributes attributes)
+    throws SAXException {
+        /* Convert the attributes into parameters */
+        Parameters parameters = new Parameters();
+        for (int x = 0; x < attributes.getLength(); x++) {
+            String name = attributes.getLocalName(x);
+            parameters.put(name, attributes.getValue(x));
+        }
+        /* Create the new configuration element */
+        Configuration element = new Configuration(uri, local, parameters);
+        if (this.locator != null) element.locate(locator.getSystemId(),
+                                                 locator.getLineNumber(),
+                                                 locator.getColumnNumber());
+
+        /* If no root element has been found yet, add it */
+        if (this.current == null) this.current = element;
+        this.stack.add(element);
+    }
+
+    /**
+     * <p>Receive notification of the end of an element.</p>
+     *
+     * @param uri the namespace URI of the element.
+     * @param local the local name of the element.
+     * @param qualified the fully qualified name of the element.
+     */
+    public void endElement(String uri, String local, String qualified)
+    throws SAXException {
+        /* Process the value of the element */
+        Configuration element = (Configuration) stack.remove(stack.size() - 1);
+        if (this.buffer != null) {
+            element.setValue(this.buffer.toString());
+            this.buffer = null;
+        }
+
+        /* If this is not the root element, add it to the parent element */
+        if (stack.size() > 0) {
+            Configuration parent = (Configuration) stack.get(stack.size() - 1);
+            parent.add(element);
+        }
+    }
+
+    /**
+     * <p>Receive notification of some character data.</p>
+     *
+     * @param characters an array of characters.
+     * @param start the index where relevant characters start from in the array.
+     * @param length the number of relevant characters in the array.
+     */
+    public void characters(char characters[], int start, int length)
+    throws SAXException {
+        /* Append valid characters to the buffer (collapse spaces) */
+        String value = new String(characters, start, length);
+        StringTokenizer tokenizer = new StringTokenizer(value);
+        while (tokenizer.hasMoreTokens()) {
+            value = tokenizer.nextToken().trim();
+            if (value.length() == 0) continue;
+            if (this.buffer == null) {
+                this.buffer = new StringBuffer(value);
+            } else {
+                if (this.buffer.length() > 0) this.buffer.append(' ');
+                this.buffer.append(value);
+            }
+        }
+    }
+
+    /**
+     * <p>Parse an XML file returning a {@link Configuration} instance.</p>
+     *
+     * @param document the XML document to parse.
+     * @throws IOException if an I/O error occurred parsing the document.
+     * @throws ConfigurationException if the XML file could not be parsed or
+     *                                represented as a {@link Configuration}.
+     */
+    public static Configuration parse(File document)
+    throws ConfigurationException, IOException {
+        if (document == null) throw new NullPointerException("Null document");
+        return(ConfigurationBuilder.parse(document.toURL()));
+    }
+
+    /**
+     * <p>Parse an XML file returning a {@link Configuration} instance.</p>
+     *
+     * @param document the XML document to parse.
+     * @throws IOException if an I/O error occurred parsing the document.
+     * @throws ConfigurationException if the XML file could not be parsed or
+     *                                represented as a {@link Configuration}.
+     */
+    public static Configuration parse(URL document)
+    throws ConfigurationException, IOException {
+        if (document == null) throw new NullPointerException("Null document");
+        return(ConfigurationBuilder.parse(document.toString()));
+    }
+
+    /**
+     * <p>Parse an XML file returning a {@link Configuration} instance.</p>
+     *
+     * @param document the XML document to parse.
+     * @throws IOException if an I/O error occurred parsing the document.
+     * @throws ConfigurationException if the XML file could not be parsed or
+     *                                represented as a {@link Configuration}.
+     */
+    public static Configuration parse(String document)
+    throws ConfigurationException, IOException {
+        if (document == null) throw new NullPointerException("Null document");
+        return(ConfigurationBuilder.parse(new InputSource(document)));
+    }
+
+    /**
+     * <p>Parse an XML file returning a {@link Configuration} instance.</p>
+     *
+     * @param document the XML document to parse.
+     * @throws IOException if an I/O error occurred parsing the document.
+     * @throws ConfigurationException if the XML file could not be parsed or
+     *                                represented as a {@link Configuration}.
+     */
+    public static Configuration parse(InputSource document)
+    throws ConfigurationException, IOException {
+        /* Check our InputSource */
+        if (document == null) throw new NullPointerException("Null document");
+        
+        /* Instantiate a non-validating namespace aware SAXParserFactory */
+        SAXParserFactory factory = SAXParserFactory.newInstance();
+        factory.setNamespaceAware(true);
+        factory.setValidating(false);
+        try {
+            /* Try to do some parsing */
+            ConfigurationBuilder builder = new ConfigurationBuilder();
+            SAXParser parser = factory.newSAXParser();
+            parser.parse(document, builder);
+            return(builder.configuration());
+        } catch(ParserConfigurationException e) {
+            throw new ConfigurationException("Unable to configure parser", e);
+        } catch(SAXParseException e) {
+            throw new ConfigurationException("Error parsing configurations "
+                                             + "from \"" + e.getSystemId()
+                                             + "\" line " + e.getLineNumber()
+                                             + " column "+ e.getColumnNumber()
+                                             + ": " + e.getMessage(), e);
+        } catch(SAXException e) {
+            Exception x = e.getException();
+            if ((x != null) && (x instanceof ConfigurationException)) {
+                throw((ConfigurationException)x);
+            }
+            throw new ConfigurationException("Can't parse configurations from "
+                                             + "\"" + document.getSystemId()
+                                             + "\": " + e.getMessage(), e);
+        }
+    }
+}

Added: cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/configuration/ConfigurationException.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/configuration/ConfigurationException.java	Sun Oct 31 18:10:16 2004
@@ -0,0 +1,110 @@
+/* =============================================================================== *
+ * 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.configuration;
+
+/**
+ * <p>An exception identifying an error in a configuration operation.</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 ConfigurationException extends Exception {
+
+    /** <p>The associated {@link Configuration} element.</p> */
+    private Configuration configuration = null;
+
+    /**
+     * <p>Create a new {@link ConfigurationException} instance.</p>
+     */
+    public ConfigurationException() {
+        super();
+    }
+
+    /**
+     * <p>Create a new {@link ConfigurationException} instance with a
+     * specified detail message.</p>
+     *
+     * @param message the detail message of this exception.
+     */
+    public ConfigurationException(String message) {
+        super(message);
+    }
+    
+    /**
+     * <p>Create a new {@link ConfigurationException} instance with a
+     * specified detail message and a related {@link Configuration}.</p>
+     *
+     * @param message the detail message of this exception.
+     * @param configuration the related configuration element.
+     */
+    public ConfigurationException(String message, Configuration configuration) {
+        super(message + (configuration == null ? "" :
+                         " [" + configuration.location() + "]"));
+    }
+    
+    /**
+     * <p>Create a new {@link ConfigurationException} instance with a
+     * specified detail message and cause.</p>
+     *
+     * @param message the detail message of this exception.
+     * @param cause the cause of this exception.
+     */
+    public ConfigurationException(String message, Throwable cause) {
+        super(message, cause);
+    }
+    
+    /**
+     * <p>Create a new {@link ConfigurationException} instance with a
+     * specified detail message and cause.</p>
+     *
+     * @param message the detail message of this exception.
+     * @param configuration the related configuration element.
+     * @param cause the cause of this exception.
+     */
+    public ConfigurationException(String message, Configuration configuration,
+                                  Throwable cause) {
+        super(message + (configuration == null ? "" :
+                         " [" + configuration.location() + "]"), cause);
+    }
+    
+    /**
+     * <p>Create a new {@link ConfigurationException} instance with a
+     * specified cause.</p>
+     *
+     * @param cause the cause of this exception.
+     */
+    public ConfigurationException(Throwable cause) {
+        super((cause == null ? null : cause.toString()), cause);
+    }
+
+    /**
+     * <p>Return the associated {@link Configuration} element.</p>
+     *
+     * @return a {@link Configuration} element or <b>null</b>.
+     */
+    public Configuration getConfiguration() {
+        return(this.configuration);
+    }
+
+    /**
+     * <p>Return the associated {@link Configuration} location if known.</p>
+     *
+     * @see Configuration#location()
+     * @return a <b>non null</b> location {@link String}.
+     */
+    public String getLocation() {
+        if (this.configuration != null) return(configuration.location());
+        return("null@-1,-1");
+    }
+}

Added: cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/configuration/ConfigurationSerializer.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/configuration/ConfigurationSerializer.java	Sun Oct 31 18:10:16 2004
@@ -0,0 +1,184 @@
+/*
+ * 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.configuration;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Iterator;
+
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+import javax.xml.transform.stream.StreamResult;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * <p>The {@link ConfigurationSerializer} serializes {@link Configuration}
+ * instances as XML data.</p>
+ *
+ * <p>A simple static {@link #serialize(Configuration,ContentHandler)} method
+ * is provided for direct SAX-2 integration, otherwise the
+ * {@link #serialize(Configuration,OutputStream)} method will use the default
+ * JAXP implementation of the platform to serialize XML documents to
+ * {@link OutputStream} instances.</p>
+ *
+ * @author <a href="mailto:pier@apache.org">Pier Fumagalli</a>
+ * @version 1.0 (CVS $Revision: 1.5 $)
+ */
+public class ConfigurationSerializer {
+
+    /** <p>The character array used for indenting.</p> */
+    private static final char indent[] = "  ".toCharArray();
+    
+    /** <p>The character array used for newlines.</p> */
+    private static final char newline [] = 
+        System.getProperty("line.separator").toCharArray();
+    
+    /** <p>Deny creation of {@link ConfigurationSerializer} instances.</p> */
+    public ConfigurationSerializer() {
+        super();
+    }
+
+    /**
+     * <p>Serialize a {@link Configuration} instance as an XML document to
+     * the specified {@link OutputStream}.</p>
+     *
+     * @param configuration the {@link Configuration} instance to serialize.
+     * @param out the {@link OutputStream} where XML will be written to.
+     * @throws SAXException if there was a problem generating XML data.
+     * @throws ConfigurationException if there was a problem generating XML data.
+     */
+    public static void serialize(Configuration configuration, OutputStream out)
+    throws SAXException, ConfigurationException, IOException {
+        try {
+            SAXTransformerFactory fact = null;
+            fact = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
+            TransformerHandler hdlr = fact.newTransformerHandler();
+            hdlr.setResult(new StreamResult(out));
+            serialize(configuration, hdlr);
+        } catch (TransformerFactoryConfigurationError e) {
+            throw new SAXException("JAXP transformer factory unavailable");
+        } catch (TransformerConfigurationException e) {
+            throw new SAXException("JAXP transformer unavailable", e);
+        } catch (SAXException e) {
+            Exception x = e.getException();
+            if ((x != null) && (x instanceof IOException)) {
+                throw ((IOException) x);
+            }
+            throw (e);
+        }
+    }
+    
+    /**
+     * <p>Serialize a {@link Configuration} instance to a specified
+     * SAX-2 {@link ContentHandler}.</p>
+     *
+     * @param configuration the {@link Configuration} instance to serialize.
+     * @param h the {@link ContentHandler} where events will be sent to.
+     * @throws SAXException if there was a problem generating XML data.
+     * @throws ConfigurationException if there was a problem generating XML data.
+     */
+    public static void serialize(Configuration configuration, ContentHandler h)
+    throws SAXException, ConfigurationException {
+        h.startDocument();
+        element(configuration, h, 0, null);
+        h.endDocument();
+    }
+
+    /**
+     * <p>Simple method to recursively serialize a {@link Configuration}
+     * element and all its children.</p>
+     *
+     * @param configuration the {@link Configuration} instance to serialize.
+     * @param h the {@link ContentHandler} where events will be sent to.
+     * @param indent the indenting level.
+     * @param namespace the currently declared namespace.
+     * @throws SAXException if there was a problem generating XML data.
+     * @throws ConfigurationException if there was a problem converting.
+     */
+    private static void element(Configuration configuration, ContentHandler h,
+                                int indent, String namespace)
+    throws SAXException, ConfigurationException {
+        /* Create and fill attributes from configuration properties */
+        AttributesImpl attr = new AttributesImpl();
+        Iterator iterator = configuration.attributes().keySet().iterator();
+        while (iterator.hasNext()) {
+            String name = (String) iterator.next();
+            attr.addAttribute("", name, name, "CDATA",
+                              configuration.getStringAttribute(name));
+        }
+
+        /* Check for namespace declarations */
+        boolean namespacedeclared = false;
+        if (namespace == null) {
+            if (configuration.namespace() != null) {
+                h.startPrefixMapping("", configuration.namespace());
+                attr.addAttribute("", "xmlns", "xmlns", "CDATA",
+                                  configuration.namespace());
+                namespacedeclared = true;
+            }
+        } else if (!namespace.equals(configuration.namespace())) {
+            String local = configuration.namespace();
+            if (local == null) local = "";
+            h.startPrefixMapping("", (local == null? "": local));
+            attr.addAttribute("", "xmlns", "xmlns", "CDATA",
+                              (local == null? "": local));
+            namespacedeclared = true;
+        }
+
+        /* Notify the content handler of an element start */
+        indent(h, indent);
+        h.startElement("", configuration.name(), configuration.name(), attr);
+
+        /* Dump the value if and only if we have it */
+        char value[] = configuration.getStringValue("").toCharArray();
+        if (value.length > 0) {
+            if (configuration.size() > 0) indent(h, (indent + 1));
+            h.characters(value, 0, value.length);
+        }
+
+        /* Recurse into our children processing them */
+        iterator = configuration.iterator();
+        while (iterator.hasNext()) {
+            Configuration current = (Configuration) iterator.next();
+            element(current, h, (indent + 1), configuration.namespace());
+        }
+        
+        /* Indent (if there was output) and put the end name */
+        if (configuration.size() > 0) indent(h, indent);
+        h.endElement("", configuration.name(), configuration.name());
+
+        /* If we declared the namespace, undeclare it */
+        if (namespacedeclared) h.endPrefixMapping("");
+    }
+
+    /**
+     * <p>Simple method to indent text in a {@link ContentHandler}.</p>
+     *
+     * @param h the {@link ContentHandler} where events will be sent to.
+     * @param n the indenting level.
+     * @throws SAXException if there was a problem generating XML data.
+     */
+    private static void indent(ContentHandler h, int n)
+    throws SAXException {
+        h.characters(newline, 0, newline.length);
+        for (int x = 0; x < n; x ++) h.characters(indent, 0, indent.length);
+    }
+}

Added: cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/configuration/Parameters.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/configuration/Parameters.java	Sun Oct 31 18:10:16 2004
@@ -0,0 +1,590 @@
+/* =============================================================================== *
+ * 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.configuration;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * <p>The {@link Parameters} class defines a simple {@link Map} that can
+ * be used to configure components.</p>
+ *
+ * <p>A {@link Parameters} map differs from a regular {@link HashMap} in the
+ * sense that no <b>null</b> keys or values are accepted, and that keys can
+ * only be {@link String} instances.</p>
+ *
+ * <p>This class also provides simple methods for resolving values to some
+ * of the Java&trade; primitive types: boolean, int, long, float, double and
+ * {@link String}.</p>
+ *
+ * <p>Validation of {@link Parameters} instances can be performed using the
+ * {@link Parameters} object.</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 Parameters extends HashMap implements Map {
+
+    /** <p>Whether this instance is locked or not.</p> */
+    private boolean locked = false;
+
+    /**
+     * <p>Create a new empty {@link Parameters} instance.</p>
+     */
+    public Parameters() {
+        super();
+    }
+
+    /**
+     * <p>Create a new {@link Parameters} instance parsing all elements of a
+     * {@link Configuration} instance.</p>
+     * 
+     * <p>Elements of the configuration that will be parsed must look like
+     * this:</p>
+     * 
+     * <p><nobr><code>&lt;parameter
+     * name=&quot;<b>name</b>&quot;
+     * value=&quot;<b>value</b>&quot;
+     * <i>type=&quot;<b>type identifier</b>&quot;</i>/&gt;</code></nobr></p>
+     *
+     * @throws ConfigurationException if the instance cannot be created.
+     */
+    public Parameters(Configuration configuration)
+    throws ConfigurationException {
+        super();
+        Iterator iterator = configuration.children("parameter");
+        while (iterator.hasNext()) try {
+            Configuration c = (Configuration)iterator.next();
+            String n = c.getStringAttribute("name");
+            String t = c.getStringAttribute("type", "string");
+            if ("string".equalsIgnoreCase(t)) {
+                this.put(n, c.getStringValue(c.getStringAttribute("value")));
+            } else if ("boolean".equalsIgnoreCase(t)) {
+                this.put(n, c.getBooleanValue(c.getBooleanAttribute("value")));
+            } else if ("double".equalsIgnoreCase(t)) {
+                this.put(n, c.getDoubleValue(c.getDoubleAttribute("value")));
+            } else if ("float".equalsIgnoreCase(t)) {
+                this.put(n, c.getFloatValue(c.getFloatAttribute("value")));
+            } else if ("integer".equalsIgnoreCase(t)) {
+                this.put(n, c.getIntegerValue(c.getIntegerAttribute("value")));
+            } else if ("long".equalsIgnoreCase(t)) {
+                this.put(n, c.getLongValue(c.getLongAttribute("value")));
+            } else if ("configuration".equalsIgnoreCase(t)) {
+                Configuration k = new Configuration(n);
+                k.addAll(c);
+                this.put(n, k);
+            } else {
+                this.put(n, c.getValue(c.getAttribute("value")));
+            }
+        } catch (ConfigurationException e) {
+            throw new ConfigurationException(e.getMessage(), configuration, e);
+        }
+    }
+
+    /**
+     * <p>Lock this {@link Parameters} instance.</p>
+     *
+     * <p>After this method is called, no further modifications are allowed
+     * into this {@link Parameters} instance, and any call to the
+     * {@link #put(Object,Object)} or {@link #remove(Object)} methods will
+     * throw an {@link UnsupportedOperationException}.</p>
+     *
+     * @return this {@link Parameters} instance.
+     */
+    public Parameters lock() {
+        this.locked = true;
+        return(this);
+    }
+
+    /* ====================================================================== */
+
+    /**
+     * <p>Return the parameter value.</p>
+     *
+     * @param name the name of the parameter to retrieve.
+     * @return the value of the parameter or <b>null</b> if the parameter was
+     *         not found.
+     */
+    public Object get(Object name) {
+        if (name == null) return(null);
+        return(super.get(name));
+    }
+
+    /**
+     * <p>Return the parameter value.</p>
+     *
+     * @param name the name of the parameter.
+     * @param defaultValue the default value to return.
+     * @return the value of the parameter or the specified default.
+     */
+    public Object get(Object name, Object defaultValue) {
+        Object value = this.get(name);
+        return(value == null? defaultValue: value);
+    }
+    
+    /**
+     * <p>Put a new parameter in this {@link Parameters} map.</p>
+     *
+     * @param name the name of the parameter.
+     * @param value the value of the parameter.
+     * @throws NullPointerException if either name or value are <b>null</b>.
+     * @throws ClassCastException if the name is not a {@link String}.
+     * @throws UnsupportedOperationException if this instance is locked.
+     */
+    public Object put(Object name, Object value) {
+        if (this.locked)  throw new UnsupportedOperationException("Locked");
+        if (name == null) throw new NullPointerException("Null name");
+        if (value == null) throw new NullPointerException("Null value");
+        if (name instanceof String) return(super.put(name, value));
+        throw new ClassCastException("Invalid parameter name");
+    }
+    
+    /**
+     * <p>Put a new boolean parameter in this {@link Parameters} map.</p>
+     *
+     * @param name the name of the parameter.
+     * @param value the value of the parameter.
+     * @throws NullPointerException if the name was <b>null</b>.
+     * @throws UnsupportedOperationException if this instance is locked.
+     */
+    public Object put(Object name, boolean value) {
+        return this.put(name, new Boolean(value));
+    }
+
+    /**
+     * <p>Put a new double parameter in this {@link Parameters} map.</p>
+     *
+     * @param name the name of the parameter.
+     * @param value the value of the parameter.
+     * @throws NullPointerException if the name was <b>null</b>.
+     * @throws UnsupportedOperationException if this instance is locked.
+     */
+    public Object put(Object name, double value) {
+        return this.put(name, new Double(value));
+    }
+
+    /**
+     * <p>Put a new float parameter in this {@link Parameters} map.</p>
+     *
+     * @param name the name of the parameter.
+     * @param value the value of the parameter.
+     * @throws NullPointerException if the name was <b>null</b>.
+     * @throws UnsupportedOperationException if this instance is locked.
+     */
+    public Object put(Object name, float value) {
+        return this.put(name, new Float(value));
+    }
+
+    /**
+     * <p>Put a new int parameter in this {@link Parameters} map.</p>
+     *
+     * @param name the name of the parameter.
+     * @param value the value of the parameter.
+     * @throws NullPointerException if the name was <b>null</b>.
+     * @throws UnsupportedOperationException if this instance is locked.
+     */
+    public Object put(Object name, int value) {
+        return this.put(name, new Integer(value));
+    }
+
+    /**
+     * <p>Put a new long parameter in this {@link Parameters} map.</p>
+     *
+     * @param name the name of the parameter.
+     * @param value the value of the parameter.
+     * @throws NullPointerException if the name was <b>null</b>.
+     * @throws UnsupportedOperationException if this instance is locked.
+     */
+    public Object put(Object name, long value) {
+        return this.put(name, new Long(value));
+    }
+
+    /**
+     * <p>Remove a parameter in this {@link Parameters} map.</p>
+     *
+     * @param name the name of the parameter.
+     * @return the value of the parameter or <b>null</b> if the parameter was
+     *         not found.
+     */
+    public Object remove(Object name) {
+        if (name == null) return(null);
+        return(super.remove(name));
+    }
+
+    /**
+     * <p>Returns an unlocked shallow copy of this {@link Parameters}
+     * instance.</p>
+     *
+     * <p>The parameter names and  values themselves are not cloned, and
+     * the returned instance will not be locked.</p>
+     *
+     * @return a new <b>non null</b> cloned {@link Parameters} instance.
+     */
+    public Object clone() {
+        Parameters parameters = (Parameters) super.clone();
+        parameters.locked = false;
+        return(parameters);
+    }
+
+    /* ====================================================================== */
+
+    /**
+     * <p>Return the boolean representation of the specified parameter.</p>
+     *
+     * @param name the name of the parameter to retrieve as a boolean.
+     * @return the boolean value of the parameter.
+     * @throws ConfigurationException if the parameter was not found or could
+     *                                not be converted to a boolean.
+     */
+    public boolean getBoolean(String name)
+    throws ConfigurationException {
+        Object object = this.check(name);
+        if (object instanceof Boolean) return(((Boolean)object).booleanValue());
+        String string = object.toString();
+        if ("0".equals(string)) return(false);
+        if ("1".equals(string)) return(true);
+        if ("false".equalsIgnoreCase(string)) return(false);
+        if ("true".equalsIgnoreCase(string)) return(true);
+        throw this.error(name, "boolean", null);
+    }
+
+    /**
+     * <p>Return the boolean representation of the specified parameter.</p>
+     *
+     * @param name the name of the parameter to retrieve as a boolean.
+     * @param defaultValue the default value to assign if the parameter was
+     *                     not found or could not be converted.
+     * @return the boolean value of the parameter or the specified default.
+     */
+    public boolean getBoolean(String name, boolean defaultValue) {
+        try {
+            return(this.getBoolean(name));
+        } catch(ConfigurationException e) {
+            return(defaultValue);
+        }
+    }
+    
+    /* ====================================================================== */
+    
+    /**
+     * <p>Return the integer representation of the specified parameter.</p>
+     *
+     * @param name the name of the parameter to retrieve as an integer.
+     * @return the integer value of the parameter.
+     * @throws ConfigurationException if the parameter was not found or could
+     *                                not be converted to an integer.
+     */
+    public int getInteger(String name)
+    throws ConfigurationException {
+        Object object = this.check(name);
+        if (object instanceof Number) return(((Number)object).intValue());
+        try {
+            return(Integer.parseInt(object.toString()));
+        } catch (NumberFormatException e) {
+            throw this.error(name, "int", e);
+        }
+    }
+    
+    /**
+     * <p>Return the integer representation of the specified parameter.</p>
+     *
+     * @param name the name of the parameter to retrieve as a integer.
+     * @param defaultValue the default value to assign if the parameter was
+     *                     not found or could not be converted.
+     * @return the integer value of the parameter or the specified default.
+     */
+    public int getInteger(String name, int defaultValue) {
+        try {
+            return(this.getInteger(name));
+        } catch(ConfigurationException e) {
+            return(defaultValue);
+        }
+    }
+    
+    /* ====================================================================== */
+    
+    /**
+     * <p>Return the long integer representation of the specified parameter.</p>
+     *
+     * @param name the name of the parameter to retrieve as a long integer.
+     * @return the long integer value of the parameter.
+     * @throws ConfigurationException if the parameter was not found or could
+     *                                not be converted to a long integer.
+     */
+    public long getLong(String name)
+    throws ConfigurationException {
+        Object object = this.check(name);
+        if (object instanceof Number) return(((Number)object).longValue());
+        try {
+            return(Long.parseLong(object.toString()));
+        } catch (NumberFormatException e) {
+            throw this.error(name, "long", e);
+        }
+    }
+    
+    /**
+     * <p>Return the long integer representation of the specified parameter.</p>
+     *
+     * @param name the name of the parameter to retrieve as a long integer.
+     * @param defaultValue the default value to assign if the parameter was
+     *                     not found or could not be converted.
+     * @return the long integer value of the parameter or the specified default.
+     */
+    public long getLong(String name, long defaultValue) {
+        try {
+            return(this.getLong(name));
+        } catch(ConfigurationException e) {
+            return(defaultValue);
+        }
+    }
+    
+    /* ====================================================================== */
+    
+    /**
+     * <p>Return the float representation of the specified parameter.</p>
+     *
+     * @param name the name of the parameter to retrieve as a float.
+     * @return the float value of the parameter.
+     * @throws ConfigurationException if the parameter was not found or could
+     *                                not be converted to a float.
+     */
+    public float getFloat(String name)
+    throws ConfigurationException {
+        Object object = this.check(name);
+        if (object instanceof Number) return(((Number)object).floatValue());
+        try {
+            return(Float.parseFloat(object.toString()));
+        } catch (NumberFormatException e) {
+            throw this.error(name, "float", e);
+        }
+    }
+
+    /**
+     * <p>Return the float representation of the specified parameter.</p>
+     *
+     * @param name the name of the parameter to retrieve as a float.
+     * @param defaultValue the default value to assign if the parameter was
+     *                     not found or could not be converted.
+     * @return the float value of the parameter or the specified default.
+     */
+    public float getFloat(String name, float defaultValue) {
+        try {
+            return(this.getFloat(name));
+        } catch(ConfigurationException e) {
+            return(defaultValue);
+        }
+    }
+    
+    /* ====================================================================== */
+    
+    /**
+     * <p>Return the double representation of the specified parameter.</p>
+     *
+     * @param name the name of the parameter to retrieve as a double.
+     * @return the double value of the parameter.
+     * @throws ConfigurationException if the parameter was not found or could
+     *                                not be converted to a doube.
+     */
+    public double getDouble(String name)
+    throws ConfigurationException {
+        Object object = this.check(name);
+        if (object instanceof Number) return(((Number)object).doubleValue());
+        try {
+            return(Double.parseDouble(object.toString()));
+        } catch (NumberFormatException e) {
+            throw this.error(name, "double", e);
+        }
+    }
+
+    /**
+     * <p>Return the double representation of the specified parameter.</p>
+     *
+     * @param name the name of the parameter to retrieve as a double.
+     * @param defaultValue the default value to assign if the parameter was
+     *                     not found or could not be converted.
+     * @return the double value of the parameter or the specified default.
+     */
+    public double getDouble(String name, double defaultValue) {
+        try {
+            return(this.getDouble(name));
+        } catch(ConfigurationException e) {
+            return(defaultValue);
+        }
+    }
+    
+    /* ====================================================================== */
+    
+    /**
+     * <p>Return the {@link String} representation of the specified parameter.</p>
+     *
+     * <p>The returned {@link String} will be created invoking the
+     * {@link Object#toString() toString()} method on the value instance.</p>
+     *
+     * @param name the name of the parameter to retrieve as a {@link String}.
+     * @return the {@link String} value of the parameter.
+     * @throws ConfigurationException if the parameter was not found.
+     */
+    public String getString(String name)
+    throws ConfigurationException {
+        return(this.check(name).toString());
+   }
+    
+    /**
+     * <p>Return the {@link String} representation of the specified parameter.</p>
+     *
+     * <p>The returned {@link String} will be created invoking the
+     * {@link Object#toString() toString()} method on the value instance.</p>
+     *
+     * @param name the name of the parameter to retrieve as a {@link String}.
+     * @param defaultValue the default value to assign if the parameter was
+     *                     not found or could not be converted.
+     * @return the {@link String} value of the parameter or the specified default.
+     */
+    public String getString(String name, String defaultValue) {
+        try {
+            return(this.getString(name));
+        } catch(ConfigurationException e) {
+            return(defaultValue);
+        }
+    }
+
+    /* ====================================================================== */
+    
+    /**
+     * <p>Return the {@link Configuration} (complex) value of the specified
+     * parameter.</p>
+     *
+     * <p>The parameter value <b>must</b> be stored as a {@link Configuration}
+     * object in this instance, otherwise this method will fail.</p>
+     *
+     * @param name the name of the {@link Configuration} parameter to retrieve.
+     * @return the {@link Configuration} value of the parameter.
+     * @throws ConfigurationException if the parameter was not found or its
+     *                                value was not a {@link Configuration}.
+     */
+    public Configuration getConfiguration(String name)
+    throws ConfigurationException {
+        try {
+            return((Configuration)this.check(name));
+        } catch (ClassCastException e) {
+            throw this.error(name, "configuration", e);
+        }
+    }
+    
+    /**
+     * <p>Return the {@link Configuration} (complex) value of the specified
+     * parameter.</p>
+     *
+     * <p>The parameter value <b>must</b> be stored as a {@link Configuration}
+     * object in this instance, otherwise this method will return the default
+     * value.</p>
+     *
+     * @param name the name of the {@link Configuration} parameter to retrieve.
+     * @param defaultValue the default value to assign if the parameter was
+     *                     not found or was not a {@link Configuration}.
+     * @return the {@link Configuration} value of the parameter.
+     * @throws ConfigurationException if the parameter was not found or its
+     *                                value was not a {@link Configuration}.
+     */
+    public Configuration getConfiguration(String name,
+                                          Configuration defaultValue) {
+        try {
+            return(this.getConfiguration(name));
+        } catch(ConfigurationException e) {
+            return(defaultValue);
+        }
+    }
+    
+    /* ====================================================================== */
+    
+    /**
+     * <p>Convert this {@link Parameters} instance into {@link Properties}.</p>
+     * 
+     * @return a <b>non null</b> {@link Properties} instance with all parameters
+     *         it was possible to convert into properties.
+     */
+    public Properties toProperties() {
+        Properties properties = new Properties();
+        Iterator iterator = this.keySet().iterator();
+        while (iterator.hasNext()) { 
+            String name = (String)iterator.next();
+            String value = this.getString(name, null);
+            if (value != null) properties.put(name, value);
+        }
+        return(properties);
+    }
+
+    /* ====================================================================== */
+    
+    /**
+     * <p>Verify that the specified parameter is of the specified type.</p>
+     *
+     * @param name the parameter name.
+     * @param type the parameter type.
+     * @return <b>true</b> if the parameter exists and is of the specified
+     *         type, <b>false</b> otherwise.
+     * @throws UnsupportedOperationException if type was unrecognized.
+     */
+    public boolean verify(String name, String type) {
+        try {
+            if ("string".equalsIgnoreCase(type)) {
+                this.getString(name);
+            } else if ("boolean".equalsIgnoreCase(type)) {
+                this.getBoolean(name);
+            } else if ("double".equalsIgnoreCase(type)) {
+                this.getDouble(name);
+            } else if ("float".equalsIgnoreCase(type)) {
+                this.getFloat(name);
+            } else if ("integer".equalsIgnoreCase(type)) {
+                this.getInteger(name);
+            } else if ("long".equalsIgnoreCase(type)) {
+                this.getLong(name);
+            } else if ("configuration".equalsIgnoreCase(type)) {
+                this.getConfiguration(name);
+            } else {
+                throw new UnsupportedOperationException("Unknown type " + type);
+            }
+            /* We got here without exceptions, then all is fine */
+            return(true);
+        } catch (ConfigurationException e) {
+            /* Configuration exception? no value or can't convert */
+            return(false);
+        }
+    }
+
+    /* ====================================================================== */
+
+    /**
+     * <p>Simple method to check the value of a parameter.</p>
+     */
+    private Object check(String name)
+    throws ConfigurationException {
+        if (name == null) throw new ConfigurationException("Null name");
+        Object value = this.get(name);
+        if (value != null) return(value);
+        throw new ConfigurationException("Parameter \"" + name
+                                         + "\" not found");
+    }
+
+    /**
+     * <p>Simple method to throw a nicely formatted exception.</p>
+     */
+    private ConfigurationException error(String n, String t, Throwable x) {
+        return new ConfigurationException("Parameter \"" + n + "\" value \""
+                                          + this.getString(n, "?") + "\" can "
+                                          + "not be converted to a " + t, x);
+    }
+}

Added: cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Block.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Block.java	Sun Oct 31 18:10:16 2004
@@ -0,0 +1,157 @@
+/* =============================================================================== *
+ * 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.description;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.apache.cocoon.kernel.KernelException;
+import org.apache.cocoon.kernel.configuration.Configuration;
+
+/**
+ * <p>An {@link Block} represents an block descriptor.</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 Block extends Descriptor {
+
+    /** <p>The name of the exposed Java interface.</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>Whether the component is a singleton or not.</p> */
+    private boolean singleton = true;
+    /** <p>The array of identifiers of all extended blocks.</p> */
+    private String[] extensions = null;
+    /** <p>The array of identifiers of all implemented interfaces.</p> */
+    private String[] implementations = null;
+
+    /**
+     * <p>Create a new {@link Block} instance.</p>
+     *
+     * @param configuration A {@link Configuration} object enclosing the XML data.
+     * @throws KernelException If an error occurred processing the XML data.
+     */
+    public Block(Configuration configuration)
+    throws KernelException {
+        /* Parse all generic stuff */
+        super(configuration);
+        
+        /* Specific interface stuff */
+        if (! "block".equals(configuration.name())) {
+            throw new KernelException("Invalid root element name for interface "
+                    + " descriptor at " + configuration.location());
+        }
+        
+        /* Provision */
+        Configuration provides = configuration.child(NAMESPACE, "provides");
+        this.clazz = provides.getStringAttribute("component", null);
+        if (this.clazz == null) {
+            throw new KernelException("Provided class name not specified at "
+                    + provides.location());
+        }
+        this.initializer = provides.getStringAttribute("initialize", null);
+        this.destroyer = provides.getStringAttribute("destroy", null);
+        this.singleton = provides.getBooleanAttribute("singleton", true);
+        if ((!singleton) && ((initializer != null) || (destroyer == null))) {
+            throw new KernelException("Non-singleton component declares initializer "
+                    + "or destroyer method at " + provides.location());
+        }
+
+        /* Extensions and implementations */
+        Iterator iterator = null;
+        Set list = null;
+
+        /* Extensions */
+        iterator = configuration.children(NAMESPACE, "extends");
+        list = new HashSet();
+        while (iterator.hasNext()) {
+            Configuration current = (Configuration) iterator.next();
+            String id = current.getStringAttribute("block", null);
+            if (id == null) { 
+                throw new KernelException("Extended block identifier not speci"
+                        + "fied in descriptor at " + configuration.location());
+            }
+            list.add(id);
+        }
+        this.extensions = (String[]) list.toArray(new String[list.size()]);
+
+        /* Implementations */
+        iterator = configuration.children(NAMESPACE, "extends");
+        list = new HashSet();
+        while (iterator.hasNext()) {
+            Configuration current = (Configuration) iterator.next();
+            String id = current.getStringAttribute("block", null);
+            if (id == null) { 
+                throw new KernelException("Extended block identifier not speci"
+                        + "fied in descriptor at " + configuration.location());
+            }
+            list.add(id);
+        }
+        this.implementations = (String[]) list.toArray(new String[list.size()]);
+    }
+
+    /**
+     * <p>Return the class name of the provided Java&trade; class.</p>
+     */
+    public String getComponent() {
+        return(this.clazz);
+    }
+
+    /**
+     * <p>Return the name of the metod to call at initialization.</p>
+     */
+    public String getComponentInitializer() {
+        return(this.initializer);
+    }
+
+    /**
+     * <p>Return the name of the metod to call at destruction.</p>
+     */
+    public String getComponentDestroyer() {
+        return(this.initializer);
+    }
+
+    /**
+     * <p>Checks whether the component of this block is a singleton or not.</p>
+     */
+    public boolean isSingletonComponent() {
+        return(this.singleton);
+    }
+
+    /**
+     * <p>Return an array of all extended block identifers.</p>
+     */
+    public String[] getExtendedBlocks() {
+        return(this.extensions);
+    }
+
+    /**
+     * <p>Return an array of all implemented interface identifers.</p>
+     */
+    public String[] getImplementedInterfaces() {
+        return(this.implementations);
+    }
+
+    /**
+     * <p>Return the type of this descriptor.</p>
+     */
+    public int getType() {
+        return Descriptor.BLOCK;
+    }
+}

Added: cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Descriptor.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Descriptor.java	Sun Oct 31 18:10:16 2004
@@ -0,0 +1,276 @@
+/* =============================================================================== *
+ * 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.description;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.apache.cocoon.kernel.KernelException;
+import org.apache.cocoon.kernel.configuration.Configuration;
+
+/**
+ * <p>A {@link Descriptor} represents a block or interface descriptor.</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 abstract class Descriptor {
+
+    /** <p>The namespace declaration of the XML descriptor.</p> */ 
+    public static final String NAMESPACE =
+                                    "http://www.betaversion.org/tani/descriptor/1.0";
+    /** <p>The type identifying a block descriptor.</p> */
+    public static final int BLOCK = 1;
+    /** <p>The type identifying an interface descriptor.</p> */
+    public static final int INTERFACE = 2;
+
+    /** <p>The full URL of the identifier.</p> */
+    private URL url = null;
+    /** <p>The unversioned part of the identifier.</p> */ 
+    private URL base = null;
+    /** <p>The major version number.</p> */ 
+    private int major = -1;
+    /** <p>The minor version number.</p> */ 
+    private int minor = -1;
+    /** <p>The revision number.</p> */ 
+    private int revision = -1;
+    /** <p>The array of libraries associated with this descriptor.</p> */ 
+    private URL[] libraries = null;
+
+    /**
+     * <p>Create a new {@link Descriptor} instance.</p>
+     *
+     * @param configuration A {@link Configuration} object enclosing the XML data.
+     * @throws KernelException If an error occurred processing the XML data.
+     */
+    protected Descriptor(Configuration configuration)
+    throws KernelException {
+        /* Check the namespace */
+        if (! NAMESPACE.equals(configuration.namespace())) { 
+            throw new KernelException("Invalid namespace \""
+                    + configuration.namespace() + "\" declared for descriptor at "
+                    + configuration.location());
+        }
+
+        /* Parse and setup the ID of this interface or block */
+        String id = configuration.getStringAttribute("id", null);
+        if (id == null) {
+            throw new KernelException("Identifier not specified at "
+                    + configuration.location());
+        }
+
+        try {
+            this.setupIdentifier(new URL(id));
+        } catch (Throwable t) {
+            throw new KernelException("Unable to parse identifier \"" + id + "\""
+                    + " specified at " + configuration.location(), t);
+        }
+
+        /* Resolve libraries locations */
+        URL href = configuration.locationURL();
+        Configuration libraries = configuration.child(NAMESPACE, "libraries");
+        Iterator iterator = libraries.children(NAMESPACE, "library");
+        List urls = new ArrayList();
+        while (iterator.hasNext()) {
+            Configuration current = (Configuration) iterator.next();
+            String url = current.getStringAttribute("href", null);
+            if (url == null) { 
+                throw new KernelException("Library href attribute not specified "
+                        + "in descriptor at " + configuration.location());
+            }
+            try {
+                urls.add(new URL(href, url));
+            } catch (Throwable t) {
+                throw new KernelException("Unable to resolve library URL speci"
+                        + "fied in descriptor at " + configuration.location(), t);
+            }
+        }
+        this.libraries = (URL[]) urls.toArray(new URL[urls.size()]);
+    }
+
+    /**
+     * <p>Return the base identifier (URL without version) of this descriptor.</p>
+     */
+    public URL getBaseIdentifier() {
+        return(this.base);
+    }
+
+    /**
+     * <p>Return the major version number of this descriptor.</p>
+     */
+    public int getMajorVersionNumber() {
+        return(this.major);
+    }
+
+    /**
+     * <p>Return the minor version number of this descriptor.</p>
+     */
+    public int getMinorVersionNumber() {
+        return(this.minor);
+    }
+
+    /**
+     * <p>Return the revision number of this descriptor.</p>
+     */
+    public int getRevisionNumber() {
+        return(this.revision);
+    }
+
+    /**
+     * <p>Compare another {@link Descriptor} instance for equality.</p>
+     */
+    public boolean equals(Object object) {
+        if (object == null) return(false);
+        if (! (object instanceof Descriptor)) return(false);
+        return(this.toURL().equals(((Descriptor)object).toURL()));
+    }
+
+    /**
+     * <p>Compare another {@link Descriptor} instance for compatibility.</p>
+     */
+    public boolean isCompatibleWith(Descriptor descriptor) {
+        if (this.equals(descriptor)) return(true);
+
+        URL this_id = this.getBaseIdentifier();
+        URL desc_id = descriptor.getBaseIdentifier();
+        int this_maj = this.getMajorVersionNumber();
+        int desc_maj = descriptor.getMajorVersionNumber();
+        int this_min = this.getMinorVersionNumber();
+        int desc_min = descriptor.getMinorVersionNumber();
+
+        if (!this_id.equals(desc_id)) return(false);
+        if (this_maj != desc_maj) return(false);
+        if (this_min < desc_min) return(false);
+
+        return(true);
+    }
+    
+    /**
+     * <p>Return the {@link URL} representing the full descriptor identifier.</p>
+     */
+    public URL toURL() {
+        return(this.url);
+    }
+
+    /**
+     * <p>Return the {@link String} representing the full descriptor identifier.</p>
+     */
+    public String toString() {
+        return(this.toURL().toString());
+    }
+    
+    /**
+     * <p>Return a hash code for this instance.</p>
+     */
+    public int hashCode() {
+        return(this.toURL().hashCode());
+    }
+    
+    /**
+     * <p>Return an array of {@link URL}s enclosing all libraries declared in this
+     * descriptor.</p>
+     */
+    public URL[] getLibraries() {
+        return(this.libraries);
+    }
+
+    /* =========================================================================== */
+    /* ABSTRACT METHODS                                                            */
+    /* =========================================================================== */
+    
+    /**
+     * <p>Return the type of this descriptor.</p>
+     */
+    public abstract int getType();
+
+    /* =========================================================================== */
+    /* PRIVATE METHODS                                                             */
+    /* =========================================================================== */
+
+    /**
+     * <p>Set up this {@link Identifier} instance parsing a {@link URL}.</p>
+     *
+     * @param url The {@link URL} to parse.
+     * @throws MalformedURLException if the URL could not be parsed.
+     */
+    private void setupIdentifier(URL url)
+    throws MalformedURLException {
+        /* Get the path */
+        String path = url.getPath();
+
+        /* Check that url is something like http://somewhere/... */
+        if (path.indexOf('/') != 0)
+            throw new MalformedURLException("URL doesn't specify path");
+
+        /* Retrieve version info out of the URL */
+        String version = path.substring(path.lastIndexOf('/') + 1);
+        if (version.length() == 0) 
+            throw new MalformedURLException("URL doesn't specify version");
+        if (path.lastIndexOf('/') < 1)
+            throw new MalformedURLException("URL doesn't specify version");
+
+        /* Retrieve the block path out of the URL */
+        path = path.substring(1, path.lastIndexOf('/'));
+        if (path.length() == 0)
+            throw new MalformedURLException("URL doesn't specify base path");
+
+        /* Parse the version string */
+        StringTokenizer tokenizer = new StringTokenizer(version, ".");
+        if (!tokenizer.hasMoreTokens())
+            throw new MalformedURLException("Major version not specified");
+        String major = tokenizer.nextToken();
+            if (!tokenizer.hasMoreTokens())
+                throw new MalformedURLException("Minor version not specified");
+        String minor = tokenizer.nextToken();
+        String revision = null;
+        if (tokenizer.hasMoreTokens()) revision = tokenizer.nextToken();
+    
+        /* Parse numbers in version */
+        try {
+            /* Parse and check major version number */
+            this.major = Integer.parseInt(major);
+            if ((this.major < 0) || (this.minor > 254)) {
+                throw new MalformedURLException("0 <= Major version <= 254");
+            }
+
+            /* Parse and check minor version number */
+            this.minor = Integer.parseInt(minor); {
+            if ((this.minor < 0) || (this.minor > 254))
+                throw new MalformedURLException("0 <= Minor version <= 254");
+            }
+
+            /* Parse and check revision number */
+            if (revision != null) {
+                this.revision = Integer.parseInt(revision);
+                if ((this.revision < 0) || (this.revision > 254)) {
+                    throw new MalformedURLException("0 <= Revision <= 254");
+                }
+            }
+        } catch (NumberFormatException e) {
+            throw new MalformedURLException("Invalid version number "+ version);
+        }
+
+        /* Reconstruct the URL and check */
+        this.base = new URL(url, '/' + path + '/');
+        this.url = new URL(url, '/' + path + '/' + this.major + '.' + this.minor
+                           + (this.revision < 0 ? "" : ("." + this.revision)));
+        if (!this.url.toString().equals(url.toString()))
+            throw new MalformedURLException("Parsing versioned URL " + url
+                                            + " returned invalid " + this.url);
+    }
+}

Added: cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Interface.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Interface.java	Sun Oct 31 18:10:16 2004
@@ -0,0 +1,68 @@
+/* =============================================================================== *
+ * 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.description;
+
+import org.apache.cocoon.kernel.KernelException;
+import org.apache.cocoon.kernel.configuration.Configuration;
+
+/**
+ * <p>An {@link Interface} represents an interface descriptor.</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 Interface extends Descriptor {
+
+    /** <p>The name of the exposed Java interface.</p> */ 
+    private String clazz = null;
+
+    /**
+     * <p>Create a new {@link Interface} instance.</p>
+     *
+     * @param configuration A {@link Configuration} object enclosing the XML data.
+     * @throws KernelException If an error occurred processing the XML data.
+     */
+    public Interface(Configuration configuration)
+    throws KernelException {
+        /* Parse all generic stuff */
+        super(configuration);
+        
+        /* Specific interface stuff */
+        if (! "interface".equals(configuration.name())) {
+            throw new KernelException("Invalid root element name for interface "
+                    + " descriptor at " + configuration.location());
+        }
+        
+        Configuration exposes = configuration.child(NAMESPACE, "exposes");
+        this.clazz = exposes.getStringAttribute("interface", null);
+        if (this.clazz == null) {
+            throw new KernelException("Exposed interface name not specified at "
+                    + exposes.location());
+        }
+    }
+    
+    /**
+     * <p>Return the class name of the exposed Java&trade; interface.</p>
+     */
+    public String getInterface() {
+        return(this.clazz);
+    }
+
+    /**
+     * <p>Return the type of this descriptor.</p>
+     */
+    public int getType() {
+        return Descriptor.INTERFACE;
+    }
+}

Added: cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Library.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Library.java	Sun Oct 31 18:10:16 2004
@@ -0,0 +1,129 @@
+/* =============================================================================== *
+ * 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.description;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.HashSet;
+import java.util.NoSuchElementException;
+
+import org.apache.cocoon.kernel.KernelException;
+
+/**
+ * <p>The {@link Library} class defines a collection of {@link Descriptor} objects
+ * enclosed in a simple {@link HashSet}.</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 Library extends HashSet {
+
+    /**
+     * <p>Create a new {@link Library} instance.</p>
+     */
+    public Library() {
+        super();
+    }
+
+    /**
+     * <p>Add a new {@link Descriptor} to this {@link Library}.</p>
+     *
+     * @throws ClassCastException If the {@link Object} is not a {@link Descriptor}.
+     */
+    public boolean add(Object object) {
+        return(super.add((Descriptor) object));
+    }
+
+    /**
+     * <p>Returns an {@link Iterator} over all descriptors of a specified type.</p>
+     *
+     * @throws IllegalArgumentException If the type was not recognized.
+     */
+    public Iterator iterator(int type) {
+        return new LibraryIterator(type, this.iterator()); 
+    }
+
+    /**
+     * <p>Returns the {@link Descriptor} associated with a specified identifier.</p>
+     *
+     * @return A {@link Descriptor} instance or <b>null</b> if not found.
+     */
+    public Descriptor get(String identifier)
+    throws KernelException {
+        if (identifier == null) throw new NullPointerException("Null identifier");
+        try {
+            return this.get(new URL(identifier));
+        } catch (MalformedURLException e) {
+            throw new KernelException("Invalid descriptor " + identifier, e); 
+        }
+    }
+
+    /**
+     * <p>Returns the {@link Descriptor} associated with a specified identifier.</p>
+     *
+     * @return A {@link Descriptor} instance or <b>null</b> if not found.
+     */
+    public Descriptor get(URL identifier) {
+        if (identifier == null) throw new NullPointerException("Null identifier");
+        Iterator iterator = this.iterator();
+        while (iterator.hasNext()) {
+            Descriptor current = (Descriptor) iterator.next();
+            if (identifier.equals(current.toURL())) return(current);
+        }
+        return(null);
+    }
+
+    /**
+     * <p>A simple {@link Iterator} implementation returning {@link Descriptor}s of
+     * a specified type from a given {@link Iterator}.</p> 
+     */
+    private static final class LibraryIterator implements Iterator {
+        private Iterator iterator = null;
+        private Descriptor next = null;
+        private int type = 0;
+
+        private LibraryIterator(int type, Iterator iterator) {
+            if ((type == Descriptor.BLOCK) || (type == Descriptor.INTERFACE)) {
+                this.type = type;
+            } else {
+                throw new IllegalArgumentException("Invalid type " + type);
+            }
+            this.iterator = iterator;
+        }
+        
+        public boolean hasNext() {
+            if (this.next != null) return(true);
+            while (this.iterator.hasNext()) {
+                Descriptor current = (Descriptor) iterator.next();
+                if (this.type != current.getType()) continue;
+                this.next = current;
+                return(true);
+            }
+            return(false);
+        }
+        
+        public Object next() {
+            if (next == null) this.hasNext();
+            if (next == null) throw new NoSuchElementException();
+            Object current = this.next;
+            this.next = null;
+            return(current);
+        }
+        
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
+}

Added: cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/Deployer.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/Deployer.java	Sun Oct 31 18:10:16 2004
@@ -0,0 +1,190 @@
+/* =============================================================================== *
+ * 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.runtime;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+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.Library;
+
+/**
+ * <p>The {@link Deployer} class is the main access point of the framework, providing
+ * ways to locate, instantiate, configure and deploy blocks and their components.</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 Deployer implements Kernel {
+
+    /** <p>An empty array of {@link Object}s to be using in reflection.</p> */
+    private static final Object NULL[] = new Object[0];
+
+    /** <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>Create a new {@link Deployer} instance.</p>
+     */
+    public Deployer() {
+        this.library = new Library();
+        this.runtime = new Runtime(this.getClass().getClassLoader(), this.library);
+    }
+
+    /**
+     * <p>Initialize this deployer using the specified {@link Configuration}.</p>
+     * 
+     * @param configuration A {@link Configuration} containing descriptors locations
+     *                      and block instances.
+     */
+    public void initialize(Configuration configuration)
+    throws KernelException {
+        this.initialize(configuration, configuration);
+    }
+
+    /**
+     * <p>Initialize this deployer using the specified {@link Configuration}s.</p>
+     * 
+     * @param descriptors A {@link Configuration} containing descriptors locations.
+     * @param instances A {@link Configuration} containing block instances.
+     */
+    public void initialize(Configuration descriptors, Configuration instances)
+    throws KernelException {
+        Factory.configure(this.library, descriptors);
+        Factory.configure(this.runtime, instances);
+
+        /* Initialize all singletons */
+        Iterator iterator = this.runtime.iterator();
+        while (iterator.hasNext()) {
+            /* Retrieve the instance and configuration */
+            String name = (String) iterator.next();
+            this.singletons.put(name, this.instantiate(name));
+        }
+    }
+
+    /**
+     * <p>Destroy this deployer and all block instances.</p>
+     */
+    public void destroy() {
+        Iterator iterator = this.singletons.keySet().iterator();
+        while (iterator.hasNext()) {
+            String current = (String) iterator.next();
+            Object component = this.singletons.get(current);
+            Instance instance = this.runtime.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);
+            }
+        }
+    }
+
+    /**
+     * <p>Returns the instance of a component deployed by the {@link Kernel}.</p>
+     */
+    public Object lookup(String name)
+    throws KernelException {
+        /* Retrieve and check the instance */
+        Instance instance = this.runtime.getInstance(name);
+        if (instance == null) {
+            throw new KernelException("Invalid instance name \"" + name + "\"");
+        }
+
+        /* Prepare wiring and component */
+        Object component = this.singletons.get(instance);
+        if (component == null) this.instantiate(name, instance);
+        Wiring wiring = new Wiring(component); 
+
+        /* Create and return the proxy instance */
+        Class interfaces[] = instance.getImplementedInterfaces();
+        try {
+            return Proxy.newProxyInstance(this.runtime, interfaces, wiring);
+        } catch (Throwable t) {
+            throw new KernelException("Unable to create proxy for " + name, t);
+        }
+    }
+
+    /**
+     * <p>Return the {@link Runtime} instance associated with this.</p>
+     */
+    protected Runtime getRuntime() {
+        return this.runtime;
+    }
+
+    /**
+     * <p>Instantiate a new component given its block instance name.</p>
+     */
+    private Object instantiate(String name)
+    throws KernelException {
+        return this.instantiate(name, this.runtime.getInstance(name));
+    }
+
+    /**
+     * <p>Instantiate a new component given its block instance and name.</p>
+     */
+    private Object instantiate(String name, Instance instance)
+    throws KernelException {
+        if (instance == null) {
+            throw new KernelException("Invalid instance \"" + name + "\"");
+        }
+
+        /* Prepare a new instance */
+        Object component = null;
+        Class clazz = instance.getComponentClass();
+        try {
+            component = clazz.newInstance();
+        } catch (Throwable t) {
+            throw new KernelException("Can't instantiate " + clazz.getName(), t);
+        }
+
+        /* Configure this component instance */
+        Configuration configuration = this.runtime.getConfiguration(name);
+        if (this.initializing.contains(name)) {
+            throw new KernelException("Circular dependancy found initializing "
+                    + "instance \"" + name + "\"");
+        } else {
+            this.initializing.add(name);
+            Factory.configure(component, this, configuration);
+            this.initializing.remove(name);
+        }
+
+        /* Initialize the component and prepare the wiring */
+        Method initializer = instance.getComponentInitializerMethod();
+        try {
+            /* Non singletons will never have an initializer method set */
+            if (initializer != null) initializer.invoke(component, NULL);
+        } catch (Throwable t) {
+            throw new KernelException("Can't initialize component " + name, t);
+        }
+
+        /* Return the initialized component */
+        return (component);
+    }
+}

Added: cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/Factory.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/Factory.java	Sun Oct 31 18:10:16 2004
@@ -0,0 +1,174 @@
+/* =============================================================================== *
+ * 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.runtime;
+
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Proxy;
+import java.net.URL;
+import java.util.Iterator;
+
+import org.apache.cocoon.kernel.Kernel;
+import org.apache.cocoon.kernel.KernelException;
+import org.apache.cocoon.kernel.configuration.Configuration;
+import org.apache.cocoon.kernel.configuration.ConfigurationBuilder;
+import org.apache.cocoon.kernel.description.Block;
+import org.apache.cocoon.kernel.description.Descriptor;
+import org.apache.cocoon.kernel.description.Interface;
+import org.apache.cocoon.kernel.description.Library;
+
+/**
+ * <p>The {@link Factory} class is a utility class containing methods to
+ * configure {@link Library} and {@link Runtime} instances from XML files.</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 Factory {
+
+    /** <p>Deny construction.</p> */
+    private Factory() {
+        super();
+    }
+
+    /**
+     * <p>Configure the specified {@link Library} from a {@link Configuration}.</p>
+     */
+    public static void configure(Library library, Configuration config)
+    throws KernelException {
+        if (library == null) throw new NullPointerException("Null library");
+        if (config == null) throw new NullPointerException("Null configuration");
+
+        Iterator iterator = config.children("descriptor");
+        Configuration current = config;
+        while (iterator.hasNext()) try {
+            current = (Configuration) iterator.next(); 
+            String href = current.getStringAttribute("href");
+            URL url = new URL(config.locationURL(), href);
+            Configuration descriptor = ConfigurationBuilder.parse(url);
+            if ("block".equals(descriptor.name())) {
+                library.add(new Block(descriptor));
+            } else if ("interface".equals(descriptor.name())) {
+                library.add(new Interface(descriptor));
+            } else {
+                throw new KernelException("Invalid descriptor root element \""
+                        + descriptor.name() + "\" found in descriptor at"
+                        + descriptor.location());
+            }
+        } catch (KernelException e) {
+            throw e;
+        } catch (Throwable t) {
+            throw new KernelException("Error processing descriptor at "
+                    + current.location(), t);
+        }
+    }
+
+    /**
+     * <p>Configure the specified {@link Runtime} from a {@link Configuration}.</p>
+     */
+    public static void configure(Runtime runtime, Configuration config)
+    throws KernelException {
+        if (runtime == null) throw new NullPointerException("Null runtime");
+        if (config == null) throw new NullPointerException("Null configuration");
+
+        Iterator iterator = config.children("instance");
+        Configuration current = config;
+        while (iterator.hasNext()) try {
+            current = (Configuration) iterator.next(); 
+            String name = current.getStringAttribute("name");
+            String block = current.getStringAttribute("block");
+
+            Descriptor descriptor = runtime.getLibrary().get(block);
+            if (descriptor == null) {
+                throw new KernelException("Unable to retrieve descriptor for "
+                        + "block \"" + block + " declared at " + current.location());
+            }
+            if (descriptor.getType() != Descriptor.BLOCK) {
+                throw new KernelException("Unable to instantiate non-block \""
+                        + block + " declared at " + current.location());
+            }
+            Instance instance = new Instance(runtime, (Block) descriptor);
+            runtime.add(name, instance, current);
+        } catch (KernelException e) {
+            throw e;
+        } catch (Throwable t) {
+            throw new KernelException("Unable to create block instance "
+                    + "declared at " + current.location(), t);
+        }
+    }
+
+    /**
+     * <p>Configure the specified component from a {@link Configuration}.</p>
+     */
+    public static void configure(Object o, Deployer deployer, Configuration config)
+    throws KernelException {
+        Iterator iterator = config.children("set");
+        while (iterator.hasNext()) {
+
+            /* Look up the configurator and figure out the property name */
+            Configuration current = (Configuration) iterator.next();
+            String property = current.getStringAttribute("property", null);
+            if (property == null) {
+                throw new KernelException("Property name not specified at "
+                        + current.location());
+            }
+
+            /* Using beans, access the property descriptor */
+            PropertyDescriptor descriptor = null;
+            try {
+                String s = "set" + property.substring(0, 1).toUpperCase()
+                        + property.substring(1);
+                descriptor = new PropertyDescriptor(property, o.getClass(), null, s);
+            } catch (Throwable t) {
+                throw new KernelException("Unable to retrieve setter method for pro"
+                        + "perty \"" + property + "\" at " + current.location(), t);
+            }
+
+            /* Do we have to set a value? */
+            if (current.hasAttribute("value")) try {
+                Class type = descriptor.getPropertyType();
+                Object value = current.getAttributeAs(property, type);
+                descriptor.getWriteMethod().invoke(o, new Object[] { value });
+                continue;
+            } catch (Throwable t) {
+                throw new KernelException("Unable to set value for property \""
+                        + property + "\" specified at " + current.location(), t);
+            }
+
+            /* Do we have to set a component? */
+            if (current.hasAttribute("component")) try {
+                Object value = deployer.lookup(current.getStringAttribute("component"));
+                descriptor.getWriteMethod().invoke(o, new Object[] { value });
+                continue;
+            } catch (Throwable t) {
+                throw new KernelException("Unable to set component for property \""
+                        + property + "\" specified at " + current.location(), t);
+            }
+
+            /* Do we have to set the kernel itself? */
+            if (current.getBooleanAttribute("kernel", false)) try {
+                Wiring w = new Wiring(deployer);
+                Class i[] = new Class[] { Kernel.class };
+                Object value = Proxy.newProxyInstance(deployer.getRuntime(), i, w);
+                descriptor.getWriteMethod().invoke(o, new Object[] { value });
+                continue;
+            } catch (Throwable t) {
+                throw new KernelException("Unable to set kernel for property \""
+                        + property + "\" specified at " + current.location(), t);
+            }
+            
+            /* We haven't continue(d), something bad happened */
+            throw new KernelException("Invalid declaration at " + current.location());
+        }
+    }
+}

Added: cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/Instance.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/Instance.java	Sun Oct 31 18:10:16 2004
@@ -0,0 +1,217 @@
+/* =============================================================================== *
+ * 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.runtime;
+
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.cocoon.kernel.KernelException;
+import org.apache.cocoon.kernel.description.Block;
+import org.apache.cocoon.kernel.description.Descriptor;
+import org.apache.cocoon.kernel.description.Interface;
+import org.apache.cocoon.kernel.description.Library;
+
+/**
+ * <p>The {@link Instance} class represents a simple {@link Block} instance.</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 Instance extends URLClassLoader {
+
+    /** <p>The component class.</p> */
+    private Class component = null;
+    /** <p>The implemented interfaces.</p> */
+    private Class interfaces[] = null;
+    /** <p>The component initializer method, if any.</p> */
+    private Method initializer = null;
+    /** <p>The component destroyer method, if any.</p> */
+    private Method destroyer = null;
+    /** <p>The {@link Block} instance associated with this {@link Instance}.</p> */
+    private Block block = null;
+
+    /**
+     * <p>Create a new {@link Instance} instance.</p>
+     */
+    public Instance(Runtime runtime, Block block)
+    throws KernelException {
+        super(block.getLibraries(), runtime);
+        Library library = runtime.getLibrary();
+        
+        /* Add all interfaces that must be implemented directly by this block */
+        Set interfaces = new HashSet();
+        String implementations[] = block.getImplementedInterfaces();
+        for (int k = 0; k < implementations.length; k++) {
+            Descriptor descriptor = library.get(implementations[k]);
+            if (descriptor == null) {
+                throw new KernelException("Block " + block.toString()
+                        + " implements unknown block " + implementations[k]);
+            }
+            if (descriptor.getType() != Descriptor.BLOCK) {
+                throw new KernelException("Block " + block.toString()
+                        + " implements non-interface " + descriptor.toString());
+            }
+
+            String clazz = ((Interface) descriptor).getInterface();
+            try {
+                interfaces.add(runtime.loadClass(clazz));
+            } catch (ClassNotFoundException e) {
+                throw new KernelException("Cant find class " + clazz + " exposed by "
+                        + "interface " + descriptor.toString() + " implemented by "
+                        + block.toString());
+            }
+        }
+
+        /* Add the libraries of all extended blocks and check for indirect implems */
+        Set collector = new HashSet();
+        String extensions[] = block.getExtendedBlocks();
+        for (int k = 0; k < extensions.length; k++) {
+            Descriptor descriptor = library.get(extensions[k]);
+            if (descriptor == null) {
+                throw new KernelException("Block " + block.toString()
+                        + " extends unknown block " + extensions[k]);
+            }
+            if (descriptor.getType() != Descriptor.BLOCK) {
+                throw new KernelException("Block " + block.toString()
+                        + " extends non-block " + descriptor.toString());
+            }
+            collector.add(block);
+            this.process(library, (Block) descriptor, collector, interfaces);
+        }
+        
+        /* Resolve the component class and verify that it implements what it must */
+        try {
+            this.component = this.loadClass(block.getComponent());
+        } catch (ClassNotFoundException e) {
+            throw new KernelException("Unable to resolve component class "
+                    + block.getComponent() + " for block " + block.toString(), e);
+        }
+        this.interfaces = (Class[])interfaces.toArray(new Class[interfaces.size()]);
+        for (int k = 0; k < this.interfaces.length; k++) {
+            if (this.component.isAssignableFrom(this.interfaces[k])) continue;
+            throw new KernelException("Component class \"" + this.component.getName()
+                    + "\" is not assignable from \"" + this.interfaces[k] + "\"");
+        }
+
+        /* Resolve the initializer and destroyer methods */
+        String initializer = block.getComponentInitializer();
+        if (initializer != null) try {
+            this.initializer = this.component.getMethod(initializer, new Class[0]);
+        } catch (NoSuchMethodException e) {
+            throw new KernelException("Initializer method \"" + initializer
+                    + "\" for component \"" + block.getComponent() + "\" not found");
+        }
+        String destroyer = block.getComponentInitializer();
+        if (destroyer != null) try {
+            this.initializer = this.component.getMethod(destroyer, new Class[0]);
+        } catch (NoSuchMethodException e) {
+            throw new KernelException("Initializer method \"" + destroyer
+                    + "\" for component \"" + block.getComponent() + "\" not found");
+        }
+        
+        /* Remember where we're coming from */
+        this.block = block;
+    }
+
+    /**
+     * <p>Return the {@link Block} associated with this {@link Instance}.</p>
+     */
+    public Block getBlock() {
+        return(this.block);
+    }
+
+    /**
+     * <p>Return the {@link Class} of the component provided by this {@link Block}
+     * {@link Instance}.</p>
+     */
+    public Class getComponentClass() {
+        return(this.component);
+    }
+
+    /**
+     * <p>Return the {@link Method} to call upon intialization of the component.</p>
+     */
+    public Method getComponentInitializerMethod() {
+        return(this.initializer);
+    }
+
+    /**
+     * <p>Return the {@link Method} to call upon destruction of the component.</p>
+     */
+    public Method getComponentDestroyerMethod() {
+        return(this.destroyer);
+    }
+
+    /**
+     * <p>Return an array of {@link Class}es of all interfaces declared to be
+     * implemented by the component of this {@link Block} {@link Instance}.</p>
+     */
+    public Class[] getImplementedInterfaces() {
+        return(this.interfaces);
+    }
+
+    /**
+     * <p>Add all libraries provided by a given block and its super-blocks.</p>
+     */
+    private void process(Library library, Block block, Set collector, Set interfaces)
+    throws KernelException {
+        /* Check circularities */
+        if (collector.contains(block)) {
+            throw new KernelException("Circularity exception analysing "
+                    + "extensions for block " + block.toString());
+        }
+        collector.add(block);
+
+        /* Process interfaces */
+        String implementations[] = block.getImplementedInterfaces();
+        for (int k = 0; k < implementations.length; k++) {
+            Descriptor descriptor = library.get(implementations[k]);
+            if (descriptor == null) {
+                throw new KernelException("Block " + block.toString()
+                        + " implements unknown block " + implementations[k]);
+            }
+            if (descriptor.getType() != Descriptor.BLOCK) {
+                throw new KernelException("Block " + block.toString()
+                        + " implements non-interface " + descriptor.toString());
+            }
+
+            String clazz = ((Interface) descriptor).getInterface();
+            try {
+                interfaces.add(this.getParent().loadClass(clazz));
+            } catch (ClassNotFoundException e) {
+                throw new KernelException("Cant find class " + clazz + " exposed by "
+                        + "interface " + descriptor.toString() + " implemented by "
+                        + block.toString());
+            }
+        }
+
+        /* Process libraries */
+        URL libraries[] = block.getLibraries();
+        for (int k = 0; k < libraries.length; k++) {
+            super.addURL(libraries[k]);
+        }
+        String extensions[] = block.getExtendedBlocks();
+        for (int k = 0; k < extensions.length; k++) {
+            Descriptor descriptor = library.get(extensions[k]);
+            if (descriptor.getType() != Descriptor.BLOCK) {
+                throw new KernelException("Block " + block.toString()
+                        + " extends non-block " + descriptor.toString());
+            }
+            this.process(library, (Block) descriptor, collector, interfaces);
+        }
+    }
+}

Added: cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/Runtime.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/Runtime.java	Sun Oct 31 18:10:16 2004
@@ -0,0 +1,109 @@
+/* =============================================================================== *
+ * 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.runtime;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+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.Library;
+
+/**
+ * <p>The {@link Runtime} class represents a collection of several {@link Block}
+ * {@link Instance}s.</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 Runtime extends URLClassLoader {
+
+    private Library library = null;
+    private Map wrappers = new HashMap();
+
+    /**
+     * <p>Create a new {@link Runtime} instance.</p>
+     */
+    public Runtime(ClassLoader parent, Library library) {
+        super(new URL[0], parent);
+        this.library = library;
+        Iterator iterator = library.iterator(Descriptor.INTERFACE);
+        while (iterator.hasNext()) {
+            URL libraries[] = ((Descriptor) iterator.next()).getLibraries();
+            for (int k = 0; k < libraries.length; k++) super.addURL(libraries[k]);
+        }
+    }
+    
+    /**
+     * <p>Return the {@link Library} associated with this {@link Runtime}.</p>
+     */
+    public Library getLibrary() {
+        return(this.library);
+    }
+    
+    /**
+     * <p>Push a new {@link Block} {@link Instance} into this {@link Runtime}.</p>
+     */
+    protected void add(String name, Instance instance, Configuration configuration) {
+        if (name == null) throw new NullPointerException("Null name");
+        this.wrappers.put(name, new Wrapper(instance, configuration));
+    }
+
+    /**
+     * <p>Return an {@link Iterator} over all {@link Instance} names configured.</p>
+     */
+    public Iterator iterator() {
+        return(this.wrappers.keySet().iterator());
+    }
+
+    /**
+     * <p>Return the {@link Block} associated with the given name.</p>
+     */
+    public Block getBlock(String name) {
+        return ((Wrapper)this.wrappers.get(name)).instance.getBlock();
+    }
+
+    /**
+     * <p>Return the {@link Instance} associated with the given name.</p>
+     */
+    public Instance getInstance(String name) {
+        return ((Wrapper)this.wrappers.get(name)).instance;
+    }
+
+    /**
+     * <p>Return the {@link Configuration} associated with the given name.</p>
+     */
+    public Configuration getConfiguration(String name) {
+        return ((Wrapper)this.wrappers.get(name)).configuration;
+    }
+    
+    /**
+     * <p>A simple class wrapping aroung a {@link Block} {@link Instance} and its
+     * {@link Configuration}s.</p>
+     */
+    private static final class Wrapper {
+        private Instance instance = null;
+        private Configuration configuration = null;
+        private Wrapper(Instance instance, Configuration config) {
+            if (instance == null) throw new NullPointerException("Null instance");
+            if (config == null) throw new NullPointerException("Null configuration");
+            this.instance = instance;
+            this.configuration = config;
+        }
+    }
+}

Added: cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/Wiring.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/Wiring.java	Sun Oct 31 18:10:16 2004
@@ -0,0 +1,45 @@
+/* =============================================================================== *
+ * 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.runtime;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+/**
+ * <p>A simple {@link InvocationHandler} managing proxied object instances.</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 Wiring implements InvocationHandler {
+
+    /** <p>The instance of the proxied object.</p> */
+    private Object instance = null;
+
+    /**
+     * <p>Create a new {@link Wiring} instance.</p>
+     */
+    public Wiring(Object instance) {
+        if (instance == null) throw new NullPointerException("Null proxy instance");
+        this.instance = instance;
+    }
+
+    /**
+     * <p>Invoke the method over the remote proxied object instance.</p>
+     */
+    public Object invoke(Object proxy, Method method, Object[] parameters)
+    throws Throwable {
+        return(method.invoke(null, parameters));
+    }
+}

Added: cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/startup/Main.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/startup/Main.java	Sun Oct 31 18:10:16 2004
@@ -0,0 +1,87 @@
+/* =============================================================================== *
+ * 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.startup;
+
+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.runtime.Deployer;
+
+/**
+ * <p>A simple class initializing a {@link Kernel} from a the command line.</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 Main implements Runnable {
+
+    /** <p>The current {@link Deployer} instance.</p> */
+    private Deployer deployer = null;
+
+    /**
+     * <p>Create a new {@link Main} instance.</p>
+     */
+    private Main(Deployer deployer) {
+        if (deployer == null) throw new NullPointerException("Null deployer");
+        this.deployer = deployer;
+    }
+    
+    /**
+     * <p>Called upon shutdown by the {@link Runtime}, this method will destroy the
+     * configured {@link Deployer} instance before the JVM is terminated.</p>
+     */
+    public void run() {
+        this.deployer.destroy();
+    }
+
+    /**
+     * <p>Initialize from the command line.</p>
+     */
+    public static void main(String args[])
+    throws Throwable {
+        if ((args.length < 1) || (args.length > 2)) { 
+            String name = Main.class.getName();
+            System.err.println("Usage:");
+            System.err.println("    " + name + " <conf-file>");
+            System.err.println("  or");
+            System.err.println("    " + name + " <desc-file> <inst-file>");
+            System.err.println();
+            System.err.println("  <conf-file> Combined descriptor/instances XML");
+            System.err.println("  <desc-file> Descriptors locator XML");
+            System.err.println("  <inst-file> Instances deployment XML");
+            System.err.println();
+            System.exit(1);
+            return;
+        }
+
+        /* Parse the (possibly two) configurations */
+        Configuration descriptors = ConfigurationBuilder.parse(args[0]);
+        Configuration instances = (args.length == 1 ? descriptors : 
+                ConfigurationBuilder.parse(args[0]));
+        
+        /* Create and initialize a new deployer */
+        Deployer deployer = new Deployer();
+        deployer.initialize(descriptors, instances);
+        
+        /* Add the shutdown hook */
+        Runtime.getRuntime().addShutdownHook(new Thread(new Main(deployer)));
+
+        /* 
+         * If non-daemon threads are still running, this thread will siply exit but
+         * the Java Virtual Machine will remain alive-and-kicking. If there are no
+         * other threads, the previously registered shutdown hook will be run and
+         * the whole shabang will die gracefully... Oh, how nice this is!
+         */
+    }
+}

Re: svn commit: rev 56181 - in cocoon/whiteboard/kernel: . src src/org src/org/apache src/org/apache/cocoon src/org/apache/cocoon/kernel src/org/apache/cocoon/kernel/configuration src/org/apache/cocoon/kernel/description src/org/apache/cocoon/kernel/runtime src/org/apache/cocoon/kernel/startup

Posted by Pier Fumagalli <pi...@betaversion.org>.
On 1 Nov 2004, at 21:42, Ugo Cei wrote:

> Il giorno 01/nov/04, alle 12:16, Pier Fumagalli ha scritto:
>
>> Maybe KernelException should be unchecked, well, done anyway!
>
> Fine. Another small observation, if you don't mind. The name of the 
> "Abstract" class is a little vague. Can't we find a better name?

Stefano suggested "Module"... I'll switch it and rewrite a couple of 
things he hinted...

	Pier

Re: svn commit: rev 56181 - in cocoon/whiteboard/kernel: . src src/org src/org/apache src/org/apache/cocoon src/org/apache/cocoon/kernel src/org/apache/cocoon/kernel/configuration src/org/apache/cocoon/kernel/description src/org/apache/cocoon/kernel/runtime src/org/apache/cocoon/kernel/startup

Posted by Ugo Cei <ug...@apache.org>.
Il giorno 01/nov/04, alle 12:16, Pier Fumagalli ha scritto:

> Maybe KernelException should be unchecked, well, done anyway!

Fine. Another small observation, if you don't mind. The name of the 
"Abstract" class is a little vague. Can't we find a better name?

	Ugo

-- 
Ugo Cei - http://beblogging.com/

Re: svn commit: rev 56181 - in cocoon/whiteboard/kernel: . src src/org src/org/apache src/org/apache/cocoon src/org/apache/cocoon/kernel src/org/apache/cocoon/kernel/configuration src/org/apache/cocoon/kernel/description src/org/apache/cocoon/kernel/runtime src/org/apache/cocoon/kernel/startup

Posted by Pier Fumagalli <pi...@betaversion.org>.
On 1 Nov 2004, at 09:20, Ugo Cei wrote:

> Il giorno 01/nov/04, alle 03:16, Pier Fumagalli ha scritto:
>
>> Just finished writing, please, no comments as of yet... It will MOST 
>> DEFINITELY not work, as it's something put together over a couple of 
>> lazy afternoons while the girlfriend was at some extremely odd 
>> park/garden in South London.
>
> If you didn't want any comments, you shouldn't have committed it ;-)
>
> I did a cursory examination of the code, and without even trying to 
> understand how it is supposed to work, I have just one point to make: 
> exceptions like ConfigurationException should *really* be unchecked, 
> as there is typically no other way to react to a miisconfiguration 
> than fail as early as possible. How could you recover from it?
>
> Furthermore, all exceptions should inherit from a common root 
> exception class. This simplifies exception handling for clients 
> wanting to  deal with them, as they are not forced to write a catch 
> clause for every possible exception, but can just catch the root one.

ConfigurationException and all the o.a.c.kernel.configuration package 
are internal to the kernel implementation itself. They will not be 
exposed to blocks. It's a checked extension because the kernel 
internals _must_ react to a misconfiguration.

The only exception which could be exposed to the block is 
KernelException (another unchecked exception) which gets thrown by the 
Kernel interface in the lookup() method. The Kernel interface is the 
only one who MIGHT be used by a block when the block wants to have 
access to the kernel internals (things like monitors, or weird block 
who need to have access to all deployed block instances).

Maybe KernelException should be unchecked, well, done anyway!

	Pier


Re: svn commit: rev 56181 - in cocoon/whiteboard/kernel: . src src/org src/org/apache src/org/apache/cocoon src/org/apache/cocoon/kernel src/org/apache/cocoon/kernel/configuration src/org/apache/cocoon/kernel/description src/org/apache/cocoon/kernel/runtime src/org/apache/cocoon/kernel/startup

Posted by Ugo Cei <ug...@apache.org>.
Il giorno 01/nov/04, alle 03:16, Pier Fumagalli ha scritto:

> Just finished writing, please, no comments as of yet... It will MOST 
> DEFINITELY not work, as it's something put together over a couple of 
> lazy afternoons while the girlfriend was at some extremely odd 
> park/garden in South London.

If you didn't want any comments, you shouldn't have committed it ;-)

I did a cursory examination of the code, and without even trying to 
understand how it is supposed to work, I have just one point to make: 
exceptions like ConfigurationException should *really* be unchecked, as 
there is typically no other way to react to a miisconfiguration than 
fail as early as possible. How could you recover from it?

Furthermore, all exceptions should inherit from a common root exception 
class. This simplifies exception handling for clients wanting to  deal 
with them, as they are not forced to write a catch clause for every 
possible exception, but can just catch the root one.

	Ugo

-- 
Ugo Cei - http://beblogging.com/

Re: svn commit: rev 56181 - in cocoon/whiteboard/kernel: . src src/org src/org/apache src/org/apache/cocoon src/org/apache/cocoon/kernel src/org/apache/cocoon/kernel/configuration src/org/apache/cocoon/kernel/description src/org/apache/cocoon/kernel/runtime src/org/apache/cocoon/kernel/startup

Posted by Pier Fumagalli <pi...@betaversion.org>.
On 1 Nov 2004, at 02:10, pier@apache.org wrote:

> Author: pier
> Date: Sun Oct 31 18:10:16 2004
> New Revision: 56181
>
> Log:
> Adding new dependancy-injection based Kernel

Just finished writing, please, no comments as of yet... It will MOST 
DEFINITELY not work, as it's something put together over a couple of 
lazy afternoons while the girlfriend was at some extremely odd 
park/garden in South London.

Only thing I want to point out is the number of interfaces in the whole 
kernel that blocks _might_ want to use: 1, the Kernel interface which 
gets set into blocks willing to do stuff with the kernel internals 
itself...

Oh, and, BTW, for now, no logging whatsoever! :-P

	Pier