Return-Path: Delivered-To: apmail-cocoon-cvs-archive@www.apache.org Received: (qmail 86226 invoked from network); 1 Nov 2004 02:11:04 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur-2.apache.org with SMTP; 1 Nov 2004 02:11:04 -0000 Received: (qmail 28097 invoked by uid 500); 1 Nov 2004 02:10:48 -0000 Delivered-To: apmail-cocoon-cvs-archive@cocoon.apache.org Received: (qmail 27923 invoked by uid 500); 1 Nov 2004 02:10:43 -0000 Mailing-List: contact cvs-help@cocoon.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@cocoon.apache.org list-help: list-unsubscribe: list-post: Delivered-To: mailing list cvs@cocoon.apache.org Received: (qmail 27841 invoked by uid 99); 1 Nov 2004 02:10:41 -0000 X-ASF-Spam-Status: No, hits=-10.0 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [209.237.227.194] (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.28) with SMTP; Sun, 31 Oct 2004 18:10:28 -0800 Received: (qmail 85827 invoked by uid 65534); 1 Nov 2004 02:10:17 -0000 Date: 1 Nov 2004 02:10:17 -0000 Message-ID: <20041101021017.85825.qmail@minotaur.apache.org> From: pier@apache.org To: cvs@cocoon.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 X-Virus-Checked: Checked X-Spam-Rating: minotaur-2.apache.org 1.6.2 0/1000/N 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 . * + * * + * 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; + +/** + *

The {@link Kernel} interface describes the unique contract between the + * kernel internals and its blocks.

+ * + *

Note that normally blocks deployed by this {@link Kernel} won't have + * to know about this interface, as all configuration is done through dependancy + * injection using "Plain Old Java Objects" setters and getters.

+ * + *

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 setKernel(Kernel kernel) setter method which (when correctly + * configured) will be called with an instance of this interface.

+ * + * @author Pier Fumagalli + * @author Copyright © 2000-2004 The Apache + * Software Foundation. All rights reserved. + */ +public interface Kernel { + + /** + *

Returns the instance of a component deployed by the {@link Kernel}.

+ * + * @param name The name of the block instance deployed by this {@link Kernel}. + * @return A non-null 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 . * + * * + * 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; + +/** + *

A {@link KernelException} is thrown whenever an error occurred in the lookup + * operation performed by the {@link Kernel}.

+ * + * @author Pier Fumagalli + * @author Copyright © 2000-2004 The Apache + * Software Foundation. All rights reserved. + */ +public class KernelException extends Exception { + + /** + *

Create a new {@link KernelException} instance.

+ */ + public KernelException(String message) { + super(message); + } + + /** + *

Create a new {@link KernelException} instance.

+ */ + 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 . * + * * + * 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; + +/** + *

The {@link Configuration} class provides an XML/DOM-like view over a + * set of configurable {@link Parameters}.

+ * + *

In the context of a {@link Configuration}, {@link Parameters} are seen + * as "attributes" of the configuration element itself.

+ * + *

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}.

+ * + *

This is not 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 does not support attribute + * name spaces.

+ * + * @author Pier Fumagalli + * @author Copyright © 2000-2004 The Apache + * Software Foundation. All rights reserved. + */ +public class Configuration extends ArrayList { + + /**

Whether this instance is locked or not.

*/ + private boolean locked = false; + + /**

The name of this {@link Configuration} element. */ + private String name = null; + + /**

The namespace associated with this {@link Configuration} element. */ + private String namespace = null; + + /**

The value of {@link Configuration} element. */ + private Object value = null; + + /**

The {@link Parameters} instance to use as attributes. */ + private Parameters attributes = null; + + /**

The configuration location (if any).

*/ + private String location = null; + + /**

The configuration location URL (if any).

*/ + private URL url = null; + + /**

The hash code of this instance.

*/ + private int hash = 0; + + /* ====================================================================== */ + + /** + *

Create a new empty {@link Configuration} element to be used only + * when returning unavailable children.

+ */ + private Configuration() { + super(); + this.name = ""; + this.namespace = null; + this.attributes = new Parameters(); + this.lock(); + this.hash = 0; + } + + /** + *

Create a new {@link Configuration} element with a specified name.

+ * + * @param name this {@link Configuration} element name. + * @throws NullPointerException if the specified name was null. + * @throws IllegalArgumentException if the specified name was empty. + */ + public Configuration(String name) { + this(null, name, null); + } + + /** + *

Create a new {@link Configuration} element with a specified name and + * an optional namespace associated with it.

+ * + * @param name this {@link Configuration} element name. + * @param namespace the name space associated with the element name. + * @throws NullPointerException if the specified name was null. + * @throws IllegalArgumentException if the specified name was empty. + */ + public Configuration(String namespace, String name) { + this(namespace, name, null); + } + + /** + *

Create a new {@link Configuration} element with a specified name and + * a {@link Parameters} instance to use as element attributes.

+ * + * @param name this {@link Configuration} element name. + * @param attributes the {@link Parameters} instance to use as attributes. + * @throws NullPointerException if the specified name was null. + * @throws IllegalArgumentException if the specified name was empty. + */ + public Configuration(String name, Parameters attributes) { + this(null, name, attributes); + } + + /** + *

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.

+ * + * @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 null. + * @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(); + } + + /* ====================================================================== */ + + /** + *

Lock this {@link Configuration} instance.

+ * + *

After this method is called, no further modifications are allowed + * into this {@link Configuration} instance, and any modification operation + * will throw a {@link ConfigurationException}.

+ * + * @return this {@link Configuration} instance. + */ + public Configuration lock() { + this.locked = true; + return(this); + } + + /* ====================================================================== */ + + /** + *

Return the name of this {@link Configuration} element.

+ */ + public String name() { + return(this.name); + } + + /** + *

Return the namespace declaration (if any) associated with this + * {@link Configuration} element.

+ */ + public String namespace() { + return(this.namespace); + } + + /** + *

Return the {@link Parameters} instance backing up attribute names + * and values.

+ */ + public Parameters attributes() { + return(this.attributes); + } + + /* ====================================================================== */ + + /** + *

Add the specified {@link Configuration} instance as a child of this + * instance at the end of this list.

+ * + * @param child the child {@link Configuration} + * @return true if this list was modified, false otherwise. + * @throws NullPointerException if the child was null. + * @throws ClassCastException if the child was not a {@link Configuration}. + */ + public boolean add(Object child) { + this.check(child); + return(super.add(child)); + } + + /** + *

Add the specified {@link Configuration} instance as a child of this + * instance at the specified offset.

+ * + * @param index the offset where the child must be added. + * @param child the child {@link Configuration} + * @return true if this list was modified, false otherwise. + * @throws NullPointerException if the child was null. + * @throws ClassCastException if the child was not a {@link Configuration}. + */ + public void add(int index, Object child) { + this.check(child); + super.add(index, child); + } + + /** + *

Add the specified collection of {@link Configuration} instances as + * children of this instance at the end of this list.

+ * + * @param children the collection of children {@link Configuration} + * @return true if this list was modified, false otherwise. + * @throws NullPointerException if any of the children was null. + * @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)); + } + + /** + *

Add the specified collection of {@link Configuration} instances as + * children of this instance at the specified offset.

+ * + * @param index the offset where the children must be added. + * @param children the collection of children {@link Configuration} + * @return true if this list was modified, false otherwise. + * @throws NullPointerException if any of the children was null. + * @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)); + } + + /** + *

Returns an unlocked deep copy of this {@link Configuration} + * instance.

+ * + *

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.

+ * + *

The returned instance will not be locked.

+ * + * @return a new non null 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); + } + + + + /* ====================================================================== */ + + /** + *

Return an {@link Iterator} over all children of this + * {@link Configuration} with a specified name.

+ * + * @param name the name of all returned configuration children. + * @return a non null {@link Iterator}. + */ + public Iterator children(String name) { + return(new ConfigurationIterator(this, null, name)); + } + + /** + *

Return an {@link Iterator} over all children of this + * {@link Configuration} with a specified name and namespace.

+ * + * @param name the name of all returned configuration children. + * @param namespace the namespace of all returned configuration children. + * @return a non null {@link Iterator}. + */ + public Iterator children(String namespace, String name) { + return(new ConfigurationIterator(this, namespace, name)); + } + + /** + *

Return the first child {@link Configuration} instance with the + * specified name.

+ * + *

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:

+ * + *
+     * Configuration conf = configuration.child(name);
+     * if (!configuration.name().equals(name)) {
+     *   // There is no child with this name.
+     * }
+ * + *

The empty {@link Configuration} element is returned to allow + * constructs such as:

+ * + *
+     * Configuration conf = configuration.child(name).child(name2).child(namex);
+     * 
+ * + * @param name the name of the returned configuration child. + * @return a non null {@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); + } + + /** + *

Return the first child {@link Configuration} instance with the + * specified namespace and name.

+ * + *

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:

+ * + *
+     * Configuration conf = configuration.child(namespace, name);
+     * if (!configuration.name().equals(name)) {
+     *   // There is no child with this name.
+     * }
+ * + *

The empty {@link Configuration} element is returned to allow + * constructs such as:

+ * + *
+     * Configuration conf = configuration.child(name).child(name2).child(namex);
+     * 
+ * + * @param name the name of the returned configuration child. + * @param namespace the namespace of the returned configuration child. + * @return a non null {@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); + } + + /* ====================================================================== */ + + /** + *

Create and return a {@link String} describing the location of this + * {@link Configuration} element, if known.

+ * + *

The returned string will assume the following format: + * file@line,column.

+ * + * @return a non null {@link String} describing the location. + */ + public String location() { + return(this.location); + } + + /** + *

Return (if possible) a URL absolutely locating this + * {@link Configuration} as a file or resource.

+ * + * @return a {@link URL} instance or null 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); + } + + /* ====================================================================== */ + + /** + *

Return the value of this {@link Configuration} element.

+ * + * @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); + } + + /** + *

Return the value of this {@link Configuration} element.

+ * + * @return the value of this configuration or the specified default. + */ + public Object getValue(Object defaultValue) { + return(this.value == null? defaultValue: value); + } + + /** + *

Set the value of this {@link Configuration} element.

+ * + * @param value the value of this configuration element. + * @return the value of this configuration. + * @throws NullPointerException if the specified value was null. + */ + public Object setValue(Object value) { + if (value == null) throw new NullPointerException("Null value"); + Object old = this.value; + this.value = value; + return(old); + } + + /** + *

Set the boolean value of this {@link Configuration} element.

+ * + * @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)); + } + + /** + *

Set the double value of this {@link Configuration} element.

+ * + * @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)); + } + + /** + *

Set the float value of this {@link Configuration} element.

+ * + * @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)); + } + + /** + *

Set the int value of this {@link Configuration} element.

+ * + * @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)); + } + + /** + *

Set the long value of this {@link Configuration} element.

+ * + * @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)); + } + + /** + *

Remove the value of this {@link Configuration} element.

+ * + * @return the value of this configuration or null. + */ + public Object removeValue() { + Object old = this.value; + this.value = null; + return(old); + } + + /* ====================================================================== */ + + /** + *

Return the boolean representation of this element value.

+ * + * @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); + } + + /** + *

Return the boolean representation of this element value.

+ * + * @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); + } + } + + /* ====================================================================== */ + + /** + *

Return the integer representation of this element value.

+ * + * @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); + } + } + + /** + *

Return the integer representation of this element value.

+ * + * @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); + } + } + + /* ====================================================================== */ + + /** + *

Return the long integer representation of this element value.

+ * + * @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); + } + } + + /** + *

Return the long integer representation of this element value.

+ * + * @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); + } + } + + /* ====================================================================== */ + + /** + *

Return the float representation of this element value.

+ * + * @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); + } + } + + /** + *

Return the float representation of this element value.

+ * + * @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); + } + } + + /* ====================================================================== */ + + /** + *

Return the double representation of this element value.

+ * + * @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); + } + } + + /** + *

Return the double representation of this element value.

+ * + * @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); + } + } + + /* ====================================================================== */ + + /** + *

Return the {@link String} representation of this element value.

+ * + *

The returned {@link String} will be created invoking the + * {@link Object#toString() toString()} method on the value instance.

+ * + * @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()); + } + + /** + *

Return the {@link String} representation of this element value.

+ * + *

The returned {@link String} will be created invoking the + * {@link Object#toString() toString()} method on the value instance.

+ * + * @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); + } + } + + /* ====================================================================== */ + + /** + *

Return the value as a specific type.

+ * + * @param type the {@link Class} type of the value to return. + * @return a non null 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()); + } + + /* ====================================================================== */ + + /** + *

Check if this configuration contains the specified attribute.

+ * + * @param name the name of the attribute to check. + * @return true if the attribute was found, false otherwise. + */ + public boolean hasAttribute(String name) { + return(this.attributes.containsKey(name)); + } + + /* ====================================================================== */ + + /** + *

Return the attribute value.

+ * + * @param name the name of the attribute to retrieve. + * @return the value of the attribute or null if the attribute was + * not found. + */ + public Object getAttribute(String name) { + return(this.attributes.get(name)); + } + + /** + *

Return the attribute value.

+ * + * @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)); + } + + /* ====================================================================== */ + + /** + *

Return the boolean representation of the specified attribute.

+ * + * @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); + } + } + + /** + *

Return the boolean representation of the specified attribute.

+ * + * @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)); + } + + /* ====================================================================== */ + + /** + *

Return the integer representation of the specified attribute.

+ * + * @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); + } + } + + /** + *

Return the integer representation of the specified attribute.

+ * + * @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)); + } + + /* ====================================================================== */ + + /** + *

Return the long integer representation of the specified attribute.

+ * + * @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); + } + } + + /** + *

Return the long integer representation of the specified attribute.

+ * + * @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)); + } + + /* ====================================================================== */ + + /** + *

Return the float representation of the specified attribute.

+ * + * @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); + } + } + + /** + *

Return the float representation of the specified attribute.

+ * + * @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)); + } + + /* ====================================================================== */ + + /** + *

Return the double representation of the specified attribute.

+ * + * @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); + } + } + + /** + *

Return the double representation of the specified attribute.

+ * + * @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)); + } + + /* ====================================================================== */ + + /** + *

Return the {@link String} representation of the specified attribute.

+ * + *

The returned {@link String} will be created invoking the + * {@link Object#toString() toString()} method on the value instance.

+ * + * @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); + } + } + + /** + *

Return the {@link String} representation of the specified attribute.

+ * + *

The returned {@link String} will be created invoking the + * {@link Object#toString() toString()} method on the value instance.

+ * + * @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)); + } + + /* ====================================================================== */ + + /** + *

Return the specified attribute value as a specific type.

+ * + * @param name the name of the attribute to return. + * @param type the {@link Class} type of the value to return. + * @return a non null 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()); + } + + /* ====================================================================== */ + + /** + *

Return a human readable {@link String} representation of this + * {@link Configuration} instance.

+ * + * @return a non null {@link String}. + */ + public String toString() { + String value = getClass().getName() + "[" + name() + "]@" + hashCode(); + return(value); + } + + /** + *

Return the hash code of this {@link Configuration} instance.

+ * + * @return the hash code. + */ + public int hashCode() { + return(this.hash); + } + + /** + *

Compare an {@link Object} for equality.

+ * + * @param o an {@link Object} to compare for equality. + * @return true if the object equals this, false otherwise. + */ + public boolean equals(Object o) { + /* Simple check */ + if (o == null) return (false); + if (o == this) return (true); + return(false); + } + + /* ====================================================================== */ + + /** + *

Simple method to check the value of a child.

+ */ + 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"); + } + + /** + *

Simple method to throw a nicely formatted exception.

+ */ + private ConfigurationException error(String type, Throwable throwable) { + return new ConfigurationException("Value \""+ this.getStringValue("?") + + "\" can "+ "not be converted to a " + + type, this, throwable); + } + + /** + *

A simple iterator over children configurations.

+ */ + private static class ConfigurationIterator implements Iterator { + /**

The next configuration element.

*/ + private Configuration configuration = null; + + /**

The sub-iterator from where to fetch elements.

*/ + private Iterator iterator = null; + + /**

The namespace of the {@link Configuration}s to return.

*/ + private String namespace = null; + + /**

The name of the {@link Configuration}s to return.

*/ + private String name = null; + + /** + *

Create a new {@link ConfigurationIterator} returning a selected + * part of the children of a specified {@link Configuration}.

+ * + * @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; + } + + /** + *

Check if this {@link Iterator} can return the next element.

+ * + * @author Pier Fumagalli + * @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); + } + + /** + *

Return the next {@link Configuration} element available to this + * {@link ConfigurationIterator}.

+ */ + 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); + } + + /** + *

Block anyone attempting to remove only children.

+ */ + 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 . * + * * + * 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; + +/** + *

The {@link ConfigurationBuilder} builds {@link Configuration} instances + * from XML data.

+ * + *

This class can be instantiated and used directly as a SAX + * {@link DefaultHandler} to use with any SAX-2 compliant parser.

+ * + *

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.

+ * + * @author Pier Fumagalli + * @author Copyright © 2000-2004 The Apache + * Software Foundation. All rights reserved. + */ +public class ConfigurationBuilder extends DefaultHandler { + + /**

The returnable {@link Configuration} element.

*/ + private Configuration configuration = null; + + /**

The current {@link Configuration} element.

*/ + private Configuration current = null; + + /**

The stack of {@link Configuration} elements.

*/ + private List stack = new ArrayList(); + + /**

The buffer holding element values.

*/ + private StringBuffer buffer = null; + + /**

The current {@link Locator}.

*/ + private Locator locator = null; + + /** + *

Create a new {@link ConfigurationBuilder} instance.

+ */ + public ConfigurationBuilder() { + super(); + } + + /** + *

Return the parsed {@link Configuration} instance.

+ * + * @return the parsed {@link Configuration} or null. + */ + public Configuration configuration() { + return(this.configuration); + } + + /** + *

Receive a {@link Locator} object to locate the different document + * events.

+ * + * @param locator a non null {@link Locator} instance. + */ + public void setDocumentLocator (Locator locator) { + this.locator = locator; + } + + /** + *

Receive notification of the beginning of the document.

+ * + *

This method will effectively reset the {@link Configuration} item + * being parsed.

+ */ + public void startDocument () + throws SAXException { + this.current = null; + } + + /** + *

Receive notification of the end of the document.

+ * + *

This method will effectively mark the {@link Configuration} item + * being parsed as returnable by the {@link #configuration()} method.

+ */ + public void endDocument () + throws SAXException { + this.configuration = this.current; + } + + /** + *

Receive notification of the start of an element.

+ * + * @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); + } + + /** + *

Receive notification of the end of an element.

+ * + * @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); + } + } + + /** + *

Receive notification of some character data.

+ * + * @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); + } + } + } + + /** + *

Parse an XML file returning a {@link Configuration} instance.

+ * + * @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())); + } + + /** + *

Parse an XML file returning a {@link Configuration} instance.

+ * + * @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())); + } + + /** + *

Parse an XML file returning a {@link Configuration} instance.

+ * + * @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))); + } + + /** + *

Parse an XML file returning a {@link Configuration} instance.

+ * + * @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 . * + * * + * 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; + +/** + *

An exception identifying an error in a configuration operation.

+ * + * @author Pier Fumagalli + * @author Copyright © 2000-2004 The Apache + * Software Foundation. All rights reserved. + */ +public class ConfigurationException extends Exception { + + /**

The associated {@link Configuration} element.

*/ + private Configuration configuration = null; + + /** + *

Create a new {@link ConfigurationException} instance.

+ */ + public ConfigurationException() { + super(); + } + + /** + *

Create a new {@link ConfigurationException} instance with a + * specified detail message.

+ * + * @param message the detail message of this exception. + */ + public ConfigurationException(String message) { + super(message); + } + + /** + *

Create a new {@link ConfigurationException} instance with a + * specified detail message and a related {@link Configuration}.

+ * + * @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() + "]")); + } + + /** + *

Create a new {@link ConfigurationException} instance with a + * specified detail message and cause.

+ * + * @param message the detail message of this exception. + * @param cause the cause of this exception. + */ + public ConfigurationException(String message, Throwable cause) { + super(message, cause); + } + + /** + *

Create a new {@link ConfigurationException} instance with a + * specified detail message and cause.

+ * + * @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); + } + + /** + *

Create a new {@link ConfigurationException} instance with a + * specified cause.

+ * + * @param cause the cause of this exception. + */ + public ConfigurationException(Throwable cause) { + super((cause == null ? null : cause.toString()), cause); + } + + /** + *

Return the associated {@link Configuration} element.

+ * + * @return a {@link Configuration} element or null. + */ + public Configuration getConfiguration() { + return(this.configuration); + } + + /** + *

Return the associated {@link Configuration} location if known.

+ * + * @see Configuration#location() + * @return a non null 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; + +/** + *

The {@link ConfigurationSerializer} serializes {@link Configuration} + * instances as XML data.

+ * + *

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.

+ * + * @author Pier Fumagalli + * @version 1.0 (CVS $Revision: 1.5 $) + */ +public class ConfigurationSerializer { + + /**

The character array used for indenting.

*/ + private static final char indent[] = " ".toCharArray(); + + /**

The character array used for newlines.

*/ + private static final char newline [] = + System.getProperty("line.separator").toCharArray(); + + /**

Deny creation of {@link ConfigurationSerializer} instances.

*/ + public ConfigurationSerializer() { + super(); + } + + /** + *

Serialize a {@link Configuration} instance as an XML document to + * the specified {@link OutputStream}.

+ * + * @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); + } + } + + /** + *

Serialize a {@link Configuration} instance to a specified + * SAX-2 {@link ContentHandler}.

+ * + * @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(); + } + + /** + *

Simple method to recursively serialize a {@link Configuration} + * element and all its children.

+ * + * @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(""); + } + + /** + *

Simple method to indent text in a {@link ContentHandler}.

+ * + * @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 . * + * * + * 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; + +/** + *

The {@link Parameters} class defines a simple {@link Map} that can + * be used to configure components.

+ * + *

A {@link Parameters} map differs from a regular {@link HashMap} in the + * sense that no null keys or values are accepted, and that keys can + * only be {@link String} instances.

+ * + *

This class also provides simple methods for resolving values to some + * of the Java™ primitive types: boolean, int, long, float, double and + * {@link String}.

+ * + *

Validation of {@link Parameters} instances can be performed using the + * {@link Parameters} object.

+ * + * @author Pier Fumagalli + * @author Copyright © 2000-2004 The Apache + * Software Foundation. All rights reserved. + */ +public class Parameters extends HashMap implements Map { + + /**

Whether this instance is locked or not.

*/ + private boolean locked = false; + + /** + *

Create a new empty {@link Parameters} instance.

+ */ + public Parameters() { + super(); + } + + /** + *

Create a new {@link Parameters} instance parsing all elements of a + * {@link Configuration} instance.

+ * + *

Elements of the configuration that will be parsed must look like + * this:

+ * + *

<parameter + * name="name" + * value="value" + * type="type identifier"/>

+ * + * @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); + } + } + + /** + *

Lock this {@link Parameters} instance.

+ * + *

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}.

+ * + * @return this {@link Parameters} instance. + */ + public Parameters lock() { + this.locked = true; + return(this); + } + + /* ====================================================================== */ + + /** + *

Return the parameter value.

+ * + * @param name the name of the parameter to retrieve. + * @return the value of the parameter or null if the parameter was + * not found. + */ + public Object get(Object name) { + if (name == null) return(null); + return(super.get(name)); + } + + /** + *

Return the parameter value.

+ * + * @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); + } + + /** + *

Put a new parameter in this {@link Parameters} map.

+ * + * @param name the name of the parameter. + * @param value the value of the parameter. + * @throws NullPointerException if either name or value are null. + * @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"); + } + + /** + *

Put a new boolean parameter in this {@link Parameters} map.

+ * + * @param name the name of the parameter. + * @param value the value of the parameter. + * @throws NullPointerException if the name was null. + * @throws UnsupportedOperationException if this instance is locked. + */ + public Object put(Object name, boolean value) { + return this.put(name, new Boolean(value)); + } + + /** + *

Put a new double parameter in this {@link Parameters} map.

+ * + * @param name the name of the parameter. + * @param value the value of the parameter. + * @throws NullPointerException if the name was null. + * @throws UnsupportedOperationException if this instance is locked. + */ + public Object put(Object name, double value) { + return this.put(name, new Double(value)); + } + + /** + *

Put a new float parameter in this {@link Parameters} map.

+ * + * @param name the name of the parameter. + * @param value the value of the parameter. + * @throws NullPointerException if the name was null. + * @throws UnsupportedOperationException if this instance is locked. + */ + public Object put(Object name, float value) { + return this.put(name, new Float(value)); + } + + /** + *

Put a new int parameter in this {@link Parameters} map.

+ * + * @param name the name of the parameter. + * @param value the value of the parameter. + * @throws NullPointerException if the name was null. + * @throws UnsupportedOperationException if this instance is locked. + */ + public Object put(Object name, int value) { + return this.put(name, new Integer(value)); + } + + /** + *

Put a new long parameter in this {@link Parameters} map.

+ * + * @param name the name of the parameter. + * @param value the value of the parameter. + * @throws NullPointerException if the name was null. + * @throws UnsupportedOperationException if this instance is locked. + */ + public Object put(Object name, long value) { + return this.put(name, new Long(value)); + } + + /** + *

Remove a parameter in this {@link Parameters} map.

+ * + * @param name the name of the parameter. + * @return the value of the parameter or null if the parameter was + * not found. + */ + public Object remove(Object name) { + if (name == null) return(null); + return(super.remove(name)); + } + + /** + *

Returns an unlocked shallow copy of this {@link Parameters} + * instance.

+ * + *

The parameter names and values themselves are not cloned, and + * the returned instance will not be locked.

+ * + * @return a new non null cloned {@link Parameters} instance. + */ + public Object clone() { + Parameters parameters = (Parameters) super.clone(); + parameters.locked = false; + return(parameters); + } + + /* ====================================================================== */ + + /** + *

Return the boolean representation of the specified parameter.

+ * + * @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); + } + + /** + *

Return the boolean representation of the specified parameter.

+ * + * @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); + } + } + + /* ====================================================================== */ + + /** + *

Return the integer representation of the specified parameter.

+ * + * @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); + } + } + + /** + *

Return the integer representation of the specified parameter.

+ * + * @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); + } + } + + /* ====================================================================== */ + + /** + *

Return the long integer representation of the specified parameter.

+ * + * @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); + } + } + + /** + *

Return the long integer representation of the specified parameter.

+ * + * @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); + } + } + + /* ====================================================================== */ + + /** + *

Return the float representation of the specified parameter.

+ * + * @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); + } + } + + /** + *

Return the float representation of the specified parameter.

+ * + * @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); + } + } + + /* ====================================================================== */ + + /** + *

Return the double representation of the specified parameter.

+ * + * @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); + } + } + + /** + *

Return the double representation of the specified parameter.

+ * + * @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); + } + } + + /* ====================================================================== */ + + /** + *

Return the {@link String} representation of the specified parameter.

+ * + *

The returned {@link String} will be created invoking the + * {@link Object#toString() toString()} method on the value instance.

+ * + * @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()); + } + + /** + *

Return the {@link String} representation of the specified parameter.

+ * + *

The returned {@link String} will be created invoking the + * {@link Object#toString() toString()} method on the value instance.

+ * + * @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); + } + } + + /* ====================================================================== */ + + /** + *

Return the {@link Configuration} (complex) value of the specified + * parameter.

+ * + *

The parameter value must be stored as a {@link Configuration} + * object in this instance, otherwise this method will fail.

+ * + * @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); + } + } + + /** + *

Return the {@link Configuration} (complex) value of the specified + * parameter.

+ * + *

The parameter value must be stored as a {@link Configuration} + * object in this instance, otherwise this method will return the default + * value.

+ * + * @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); + } + } + + /* ====================================================================== */ + + /** + *

Convert this {@link Parameters} instance into {@link Properties}.

+ * + * @return a non null {@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); + } + + /* ====================================================================== */ + + /** + *

Verify that the specified parameter is of the specified type.

+ * + * @param name the parameter name. + * @param type the parameter type. + * @return true if the parameter exists and is of the specified + * type, false 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); + } + } + + /* ====================================================================== */ + + /** + *

Simple method to check the value of a parameter.

+ */ + 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"); + } + + /** + *

Simple method to throw a nicely formatted exception.

+ */ + 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 . * + * * + * 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; + +/** + *

An {@link Block} represents an block descriptor.

+ * + * @author Pier Fumagalli + * @author Copyright © 2000-2004 The Apache + * Software Foundation. All rights reserved. + */ +public class Block extends Descriptor { + + /**

The name of the exposed Java interface.

*/ + private String clazz = null; + /**

The name (if any) of the initializer method.

*/ + private String initializer = null; + /**

The name (if any) of the destroyer method.

*/ + private String destroyer = null; + /**

Whether the component is a singleton or not.

*/ + private boolean singleton = true; + /**

The array of identifiers of all extended blocks.

*/ + private String[] extensions = null; + /**

The array of identifiers of all implemented interfaces.

*/ + private String[] implementations = null; + + /** + *

Create a new {@link Block} instance.

+ * + * @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()]); + } + + /** + *

Return the class name of the provided Java™ class.

+ */ + public String getComponent() { + return(this.clazz); + } + + /** + *

Return the name of the metod to call at initialization.

+ */ + public String getComponentInitializer() { + return(this.initializer); + } + + /** + *

Return the name of the metod to call at destruction.

+ */ + public String getComponentDestroyer() { + return(this.initializer); + } + + /** + *

Checks whether the component of this block is a singleton or not.

+ */ + public boolean isSingletonComponent() { + return(this.singleton); + } + + /** + *

Return an array of all extended block identifers.

+ */ + public String[] getExtendedBlocks() { + return(this.extensions); + } + + /** + *

Return an array of all implemented interface identifers.

+ */ + public String[] getImplementedInterfaces() { + return(this.implementations); + } + + /** + *

Return the type of this descriptor.

+ */ + 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 . * + * * + * 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; + +/** + *

A {@link Descriptor} represents a block or interface descriptor.

+ * + * @author Pier Fumagalli + * @author Copyright © 2000-2004 The Apache + * Software Foundation. All rights reserved. + */ +public abstract class Descriptor { + + /**

The namespace declaration of the XML descriptor.

*/ + public static final String NAMESPACE = + "http://www.betaversion.org/tani/descriptor/1.0"; + /**

The type identifying a block descriptor.

*/ + public static final int BLOCK = 1; + /**

The type identifying an interface descriptor.

*/ + public static final int INTERFACE = 2; + + /**

The full URL of the identifier.

*/ + private URL url = null; + /**

The unversioned part of the identifier.

*/ + private URL base = null; + /**

The major version number.

*/ + private int major = -1; + /**

The minor version number.

*/ + private int minor = -1; + /**

The revision number.

*/ + private int revision = -1; + /**

The array of libraries associated with this descriptor.

*/ + private URL[] libraries = null; + + /** + *

Create a new {@link Descriptor} instance.

+ * + * @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()]); + } + + /** + *

Return the base identifier (URL without version) of this descriptor.

+ */ + public URL getBaseIdentifier() { + return(this.base); + } + + /** + *

Return the major version number of this descriptor.

+ */ + public int getMajorVersionNumber() { + return(this.major); + } + + /** + *

Return the minor version number of this descriptor.

+ */ + public int getMinorVersionNumber() { + return(this.minor); + } + + /** + *

Return the revision number of this descriptor.

+ */ + public int getRevisionNumber() { + return(this.revision); + } + + /** + *

Compare another {@link Descriptor} instance for equality.

+ */ + public boolean equals(Object object) { + if (object == null) return(false); + if (! (object instanceof Descriptor)) return(false); + return(this.toURL().equals(((Descriptor)object).toURL())); + } + + /** + *

Compare another {@link Descriptor} instance for compatibility.

+ */ + 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); + } + + /** + *

Return the {@link URL} representing the full descriptor identifier.

+ */ + public URL toURL() { + return(this.url); + } + + /** + *

Return the {@link String} representing the full descriptor identifier.

+ */ + public String toString() { + return(this.toURL().toString()); + } + + /** + *

Return a hash code for this instance.

+ */ + public int hashCode() { + return(this.toURL().hashCode()); + } + + /** + *

Return an array of {@link URL}s enclosing all libraries declared in this + * descriptor.

+ */ + public URL[] getLibraries() { + return(this.libraries); + } + + /* =========================================================================== */ + /* ABSTRACT METHODS */ + /* =========================================================================== */ + + /** + *

Return the type of this descriptor.

+ */ + public abstract int getType(); + + /* =========================================================================== */ + /* PRIVATE METHODS */ + /* =========================================================================== */ + + /** + *

Set up this {@link Identifier} instance parsing a {@link URL}.

+ * + * @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 . * + * * + * 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; + +/** + *

An {@link Interface} represents an interface descriptor.

+ * + * @author Pier Fumagalli + * @author Copyright © 2000-2004 The Apache + * Software Foundation. All rights reserved. + */ +public class Interface extends Descriptor { + + /**

The name of the exposed Java interface.

*/ + private String clazz = null; + + /** + *

Create a new {@link Interface} instance.

+ * + * @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()); + } + } + + /** + *

Return the class name of the exposed Java™ interface.

+ */ + public String getInterface() { + return(this.clazz); + } + + /** + *

Return the type of this descriptor.

+ */ + 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 . * + * * + * 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; + +/** + *

The {@link Library} class defines a collection of {@link Descriptor} objects + * enclosed in a simple {@link HashSet}.

+ * + * @author Pier Fumagalli + * @author Copyright © 2000-2004 The Apache + * Software Foundation. All rights reserved. + */ +public class Library extends HashSet { + + /** + *

Create a new {@link Library} instance.

+ */ + public Library() { + super(); + } + + /** + *

Add a new {@link Descriptor} to this {@link Library}.

+ * + * @throws ClassCastException If the {@link Object} is not a {@link Descriptor}. + */ + public boolean add(Object object) { + return(super.add((Descriptor) object)); + } + + /** + *

Returns an {@link Iterator} over all descriptors of a specified type.

+ * + * @throws IllegalArgumentException If the type was not recognized. + */ + public Iterator iterator(int type) { + return new LibraryIterator(type, this.iterator()); + } + + /** + *

Returns the {@link Descriptor} associated with a specified identifier.

+ * + * @return A {@link Descriptor} instance or null 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); + } + } + + /** + *

Returns the {@link Descriptor} associated with a specified identifier.

+ * + * @return A {@link Descriptor} instance or null 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); + } + + /** + *

A simple {@link Iterator} implementation returning {@link Descriptor}s of + * a specified type from a given {@link Iterator}.

+ */ + 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 . * + * * + * 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; + +/** + *

The {@link Deployer} class is the main access point of the framework, providing + * ways to locate, instantiate, configure and deploy blocks and their components.

+ * + * @author Pier Fumagalli + * @author Copyright © 2000-2004 The Apache + * Software Foundation. All rights reserved. + */ +public class Deployer implements Kernel { + + /**

An empty array of {@link Object}s to be using in reflection.

*/ + private static final Object NULL[] = new Object[0]; + + /**

The {@link Library} of all {@link Block}s and {@link Interface}s.

*/ + private Library library = null; + /**

The {@link Runtime} of all available {@link Instance}s.

*/ + private Runtime runtime = null; + /**

A {@link Map} of all initialized singleton components.

*/ + private Map singletons = new HashMap(); + /**

A {@link Set} containing all components being initialized.

*/ + private Set initializing = new HashSet(); + + /** + *

Create a new {@link Deployer} instance.

+ */ + public Deployer() { + this.library = new Library(); + this.runtime = new Runtime(this.getClass().getClassLoader(), this.library); + } + + /** + *

Initialize this deployer using the specified {@link Configuration}.

+ * + * @param configuration A {@link Configuration} containing descriptors locations + * and block instances. + */ + public void initialize(Configuration configuration) + throws KernelException { + this.initialize(configuration, configuration); + } + + /** + *

Initialize this deployer using the specified {@link Configuration}s.

+ * + * @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)); + } + } + + /** + *

Destroy this deployer and all block instances.

+ */ + 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); + } + } + } + + /** + *

Returns the instance of a component deployed by the {@link Kernel}.

+ */ + 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); + } + } + + /** + *

Return the {@link Runtime} instance associated with this.

+ */ + protected Runtime getRuntime() { + return this.runtime; + } + + /** + *

Instantiate a new component given its block instance name.

+ */ + private Object instantiate(String name) + throws KernelException { + return this.instantiate(name, this.runtime.getInstance(name)); + } + + /** + *

Instantiate a new component given its block instance and name.

+ */ + 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 . * + * * + * 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; + +/** + *

The {@link Factory} class is a utility class containing methods to + * configure {@link Library} and {@link Runtime} instances from XML files.

+ * + * @author Pier Fumagalli + * @author Copyright © 2000-2004 The Apache + * Software Foundation. All rights reserved. + */ +public class Factory { + + /**

Deny construction.

*/ + private Factory() { + super(); + } + + /** + *

Configure the specified {@link Library} from a {@link Configuration}.

+ */ + 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); + } + } + + /** + *

Configure the specified {@link Runtime} from a {@link Configuration}.

+ */ + 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); + } + } + + /** + *

Configure the specified component from a {@link Configuration}.

+ */ + 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 . * + * * + * 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; + +/** + *

The {@link Instance} class represents a simple {@link Block} instance.

+ * + * @author Pier Fumagalli + * @author Copyright © 2000-2004 The Apache + * Software Foundation. All rights reserved. + */ +public class Instance extends URLClassLoader { + + /**

The component class.

*/ + private Class component = null; + /**

The implemented interfaces.

*/ + private Class interfaces[] = null; + /**

The component initializer method, if any.

*/ + private Method initializer = null; + /**

The component destroyer method, if any.

*/ + private Method destroyer = null; + /**

The {@link Block} instance associated with this {@link Instance}.

*/ + private Block block = null; + + /** + *

Create a new {@link Instance} instance.

+ */ + 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; + } + + /** + *

Return the {@link Block} associated with this {@link Instance}.

+ */ + public Block getBlock() { + return(this.block); + } + + /** + *

Return the {@link Class} of the component provided by this {@link Block} + * {@link Instance}.

+ */ + public Class getComponentClass() { + return(this.component); + } + + /** + *

Return the {@link Method} to call upon intialization of the component.

+ */ + public Method getComponentInitializerMethod() { + return(this.initializer); + } + + /** + *

Return the {@link Method} to call upon destruction of the component.

+ */ + public Method getComponentDestroyerMethod() { + return(this.destroyer); + } + + /** + *

Return an array of {@link Class}es of all interfaces declared to be + * implemented by the component of this {@link Block} {@link Instance}.

+ */ + public Class[] getImplementedInterfaces() { + return(this.interfaces); + } + + /** + *

Add all libraries provided by a given block and its super-blocks.

+ */ + 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 . * + * * + * 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; + +/** + *

The {@link Runtime} class represents a collection of several {@link Block} + * {@link Instance}s.

+ * + * @author Pier Fumagalli + * @author Copyright © 2000-2004 The Apache + * Software Foundation. All rights reserved. + */ +public class Runtime extends URLClassLoader { + + private Library library = null; + private Map wrappers = new HashMap(); + + /** + *

Create a new {@link Runtime} instance.

+ */ + 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]); + } + } + + /** + *

Return the {@link Library} associated with this {@link Runtime}.

+ */ + public Library getLibrary() { + return(this.library); + } + + /** + *

Push a new {@link Block} {@link Instance} into this {@link Runtime}.

+ */ + 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)); + } + + /** + *

Return an {@link Iterator} over all {@link Instance} names configured.

+ */ + public Iterator iterator() { + return(this.wrappers.keySet().iterator()); + } + + /** + *

Return the {@link Block} associated with the given name.

+ */ + public Block getBlock(String name) { + return ((Wrapper)this.wrappers.get(name)).instance.getBlock(); + } + + /** + *

Return the {@link Instance} associated with the given name.

+ */ + public Instance getInstance(String name) { + return ((Wrapper)this.wrappers.get(name)).instance; + } + + /** + *

Return the {@link Configuration} associated with the given name.

+ */ + public Configuration getConfiguration(String name) { + return ((Wrapper)this.wrappers.get(name)).configuration; + } + + /** + *

A simple class wrapping aroung a {@link Block} {@link Instance} and its + * {@link Configuration}s.

+ */ + 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 . * + * * + * 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; + +/** + *

A simple {@link InvocationHandler} managing proxied object instances.

+ * + * @author Pier Fumagalli + * @author Copyright © 2000-2004 The Apache + * Software Foundation. All rights reserved. + */ +public class Wiring implements InvocationHandler { + + /**

The instance of the proxied object.

*/ + private Object instance = null; + + /** + *

Create a new {@link Wiring} instance.

+ */ + public Wiring(Object instance) { + if (instance == null) throw new NullPointerException("Null proxy instance"); + this.instance = instance; + } + + /** + *

Invoke the method over the remote proxied object instance.

+ */ + 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 . * + * * + * 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; + +/** + *

A simple class initializing a {@link Kernel} from a the command line.

+ * + * @author Pier Fumagalli + * @author Copyright © 2000-2004 The Apache + * Software Foundation. All rights reserved. + */ +public class Main implements Runnable { + + /**

The current {@link Deployer} instance.

*/ + private Deployer deployer = null; + + /** + *

Create a new {@link Main} instance.

+ */ + private Main(Deployer deployer) { + if (deployer == null) throw new NullPointerException("Null deployer"); + this.deployer = deployer; + } + + /** + *

Called upon shutdown by the {@link Runtime}, this method will destroy the + * configured {@link Deployer} instance before the JVM is terminated.

+ */ + public void run() { + this.deployer.destroy(); + } + + /** + *

Initialize from the command line.

+ */ + 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 + " "); + System.err.println(" or"); + System.err.println(" " + name + " "); + System.err.println(); + System.err.println(" Combined descriptor/instances XML"); + System.err.println(" Descriptors locator XML"); + System.err.println(" 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! + */ + } +}