cocoon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From p...@apache.org
Subject 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
Date Mon, 01 Nov 2004 02:10:17 GMT
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!
+         */
+    }
+}

Mime
View raw message