You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by pi...@apache.org on 2004/11/02 17:45:58 UTC
svn commit: rev 56383 - in cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel: description runtime
Author: pier
Date: Tue Nov 2 08:45:57 2004
New Revision: 56383
Added:
cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Identifier.java
cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Module.java
cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/Dependencies.java
cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/DependencyException.java
Modified:
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/Factory.java
cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/Instance.java
Log:
Renaming "Abstract" into "Module".
Separating "Descriptor" and "Identifier".
Added code to track dependency failures.
Modified: cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Block.java
==============================================================================
--- cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Block.java (original)
+++ cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Block.java Tue Nov 2 08:45:57 2004
@@ -12,21 +12,18 @@
* =============================================================================== */
package org.apache.cocoon.kernel.description;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
import org.apache.cocoon.kernel.configuration.Configuration;
import org.apache.cocoon.kernel.runtime.DeployerException;
/**
- * <p>A {@link Block} represents a block descriptor.</p>
+ * <p>A {@link Module} is a specialized implementation of a {@link Descriptor}
+ * encloses an kernel interface descriptor in a bean-like object.</p>
*
* @author <a href="mailto:pier@apache.org">Pier Fumagalli</a>
* @author Copyright © 2000-2004 <a href="http://www.apache.org/">The Apache
* Software Foundation</a>. All rights reserved.
*/
-public class Block extends Abstract {
+public class Block extends Descriptor {
/** <p>The name of the exposed Java interface.</p> */
private String clazz = null;
@@ -37,7 +34,9 @@
/** <p>Whether the component is a singleton or not.</p> */
private boolean singleton = true;
/** <p>The array of identifiers of all implemented interfaces.</p> */
- private String[] implementations = null;
+ private Identifier[] implementations = null;
+ /** <p>The array of identifiers of all required modules.</p> */
+ private Identifier[] requirements = null;
/**
* <p>Create a new {@link Block} instance.</p>
@@ -51,26 +50,18 @@
super(configuration);
/* Specific block stuff */
- if (! "block".equals(configuration.name())) {
+ if (! NAMES[BLOCK].equals(configuration.name())) {
throw new DeployerException("Invalid root element name for block "
+ " descriptor at " + configuration.location());
}
-
- /* Implementations */
- Iterator iterator = configuration.children(NAMESPACE, "implements");
- Set list = new HashSet();
- while (iterator.hasNext()) {
- Configuration current = (Configuration) iterator.next();
- String id = current.getStringAttribute("block", null);
- if (id == null) {
- throw new DeployerException("Extended block identifier not speci"
- + "fied in descriptor at " + configuration.location());
- }
- list.add(id);
- }
- this.implementations = (String[]) list.toArray(new String[list.size()]);
- /* Provision */
+ /* Interface implementations and module requirements */
+ this.implementations = super.collectIdentifiers(configuration,
+ "implementations", "implements", NAMES[INTERFACE]);
+ this.requirements = super.collectIdentifiers(configuration,
+ "requirements", "requires", NAMES[MODULE]);
+
+ /* Component provision */
Configuration provides = configuration.child(NAMESPACE, "provides");
this.clazz = provides.getStringAttribute("component", null);
@@ -85,17 +76,9 @@
this.destroyer = provides.getStringAttribute("destroy", null);
this.singleton = provides.getBooleanAttribute("singleton", true);
if ((!singleton) && ((initializer != null) || (destroyer == null))) {
- throw new DeployerException("Non-singleton component declares initializer "
- + "or destroyer method at " + provides.location());
+ throw new DeployerException("Non-singleton component declares "
+ + "initializer or destroyer method at " + provides.location());
}
-
- }
-
- /**
- * <p>Check if this block is an <i>abstract</i> block.</p>
- */
- public boolean isAbstract() {
- return(this.clazz == null);
}
/**
@@ -129,8 +112,15 @@
/**
* <p>Return an array of all implemented interface identifers.</p>
*/
- public String[] getImplementedInterfaces() {
+ public Identifier[] getImplementedInterfaces() {
return(this.implementations);
+ }
+
+ /**
+ * <p>Return an array of all required module identifers.</p>
+ */
+ public Identifier[] getRequiredModules() {
+ return(this.requirements);
}
/**
Modified: cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Descriptor.java
==============================================================================
--- cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Descriptor.java (original)
+++ cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Descriptor.java Tue Nov 2 08:45:57 2004
@@ -14,44 +14,39 @@
import java.net.MalformedURLException;
import java.net.URL;
-import java.util.ArrayList;
+import java.util.HashSet;
import java.util.Iterator;
-import java.util.List;
-import java.util.StringTokenizer;
+import java.util.Set;
import org.apache.cocoon.kernel.configuration.Configuration;
+import org.apache.cocoon.kernel.configuration.ConfigurationException;
import org.apache.cocoon.kernel.runtime.DeployerException;
/**
- * <p>A {@link Descriptor} represents a block or interface descriptor.</p>
+ * <p>A {@link Descriptor} encloses an XML descriptor in a bean-like object.</p>
*
* @author <a href="mailto:pier@apache.org">Pier Fumagalli</a>
* @author Copyright © 2000-2004 <a href="http://www.apache.org/">The Apache
* Software Foundation</a>. All rights reserved.
*/
-public abstract class Descriptor {
+public abstract class Descriptor extends Identifier {
/** <p>The namespace declaration of the XML descriptor.</p> */
public static final String NAMESPACE = "http://apache.org/cocoon/blocks/descriptor/1.0";
/** <p>The type identifying an abstract descriptor.</p> */
- public static final int ABSTRACT = 0;
+ public static final int MODULE = 0;
/** <p>The type identifying a block descriptor.</p> */
public static final int BLOCK = 1;
/** <p>The type identifying an interface descriptor.</p> */
public static final int INTERFACE = 2;
- /** <p>The full URL of the identifier.</p> */
- private URL url = null;
- /** <p>The unversioned part of the identifier.</p> */
- private URL base = null;
- /** <p>The major version number.</p> */
- private int major = -1;
- /** <p>The minor version number.</p> */
- private int minor = -1;
- /** <p>The revision number.</p> */
- private int revision = -1;
+ /** <p>The names associated with each descriptor type.</p> */
+ public static final String NAMES[] = new String [] {"module", "block", "interface"};
+
/** <p>The array of libraries associated with this descriptor.</p> */
private URL[] libraries = null;
+ /** <p>The array of identifiers of all extended blocks.</p> */
+ private Identifier[] extensions = null;
/**
* <p>Create a new {@link Descriptor} instance.</p>
@@ -61,6 +56,7 @@
*/
protected Descriptor(Configuration configuration)
throws DeployerException {
+
/* Check the namespace */
if (! NAMESPACE.equals(configuration.namespace())) {
throw new DeployerException("Invalid namespace \""
@@ -68,121 +64,45 @@
+ configuration.location());
}
- /* Parse and setup the ID of this interface or block */
- String id = configuration.getStringAttribute("id", null);
- if (id == null) {
- throw new DeployerException("Identifier not specified at "
- + configuration.location());
- }
-
+ /* Parse and setup the ID of this descriptor */
try {
- this.setupIdentifier(new URL(id));
- } catch (Throwable t) {
- throw new DeployerException("Unable to parse identifier \"" + id + "\""
- + " specified at " + configuration.location(), t);
+ super.setup(new URL(configuration.getStringAttribute("id")));
+ } catch (ConfigurationException exception) {
+ throw new DeployerException("Descriptor identifier not specified at "
+ + configuration.location(), exception);
+ } catch (MalformedURLException exception) {
+ throw new DeployerException("Invalid descriptor identifier specified at "
+ + configuration.location(), exception);
}
/* 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 DeployerException("Library href attribute not specified "
- + "in descriptor at " + configuration.location());
- }
- try {
- urls.add(new URL(href, url));
- } catch (Throwable t) {
- throw new DeployerException("Unable to resolve library URL speci"
- + "fied in descriptor at " + configuration.location(), t);
- }
- }
- this.libraries = (URL[]) urls.toArray(new URL[urls.size()]);
- }
-
- /**
- * <p>Return the base identifier (URL without version) of this descriptor.</p>
- */
- public URL getBaseIdentifier() {
- return(this.base);
- }
-
- /**
- * <p>Return the major version number of this descriptor.</p>
- */
- public int getMajorVersionNumber() {
- return(this.major);
- }
-
- /**
- * <p>Return the minor version number of this descriptor.</p>
- */
- public int getMinorVersionNumber() {
- return(this.minor);
- }
-
- /**
- * <p>Return the revision number of this descriptor.</p>
- */
- public int getRevisionNumber() {
- return(this.revision);
- }
-
- /**
- * <p>Compare another {@link Descriptor} instance for equality.</p>
- */
- public boolean equals(Object object) {
- if (object == null) return(false);
- if (! (object instanceof Descriptor)) return(false);
- return(this.toURL().equals(((Descriptor)object).toURL()));
- }
+ Set collector = new HashSet();
+ Configuration current = null;
- /**
- * <p>Compare another {@link Descriptor} instance for compatibility.</p>
- */
- public boolean isCompatibleWith(Descriptor descriptor) {
- if (this.equals(descriptor)) return(true);
+ while (iterator.hasNext()) try {
+ current = (Configuration) iterator.next();
+ String url = current.getStringAttribute("href");
+ collector.add(new URL(configuration.locationURL(), url));
+
+ } catch (ConfigurationException exception) {
+ throw new DeployerException("Library location not specified in "
+ + "descriptor at " + current.location(), exception);
+
+ } catch (MalformedURLException exception) {
+ throw new DeployerException("Invalid library location specified in "
+ + " descriptor at " + current.location(), exception);
+ }
- 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);
+ this.libraries = (URL[]) collector.toArray(new URL[collector.size()]);
- return(true);
- }
-
- /**
- * <p>Return the {@link URL} representing the full descriptor identifier.</p>
- */
- public URL toURL() {
- return(this.url);
+ /* Extensions */
+ this.extensions = this.collectIdentifiers(configuration, "extensions",
+ "extends", configuration.name());
}
/**
- * <p>Return the {@link String} representing the full descriptor identifier.</p>
- */
- public String toString() {
- return(this.toURL().toString());
- }
-
- /**
- * <p>Return a hash code for this instance.</p>
- */
- public int hashCode() {
- return(this.toURL().hashCode());
- }
-
- /**
* <p>Return an array of {@link URL}s enclosing all libraries declared in this
* descriptor.</p>
*/
@@ -190,6 +110,13 @@
return(this.libraries);
}
+ /**
+ * <p>Return an array of all extended block identifers.</p>
+ */
+ public Identifier[] getExtendedBlocks() {
+ return(this.extensions);
+ }
+
/* =========================================================================== */
/* ABSTRACT METHODS */
/* =========================================================================== */
@@ -200,78 +127,42 @@
public abstract int getType();
/* =========================================================================== */
- /* PRIVATE METHODS */
+ /* PROTECTED METHODS */
/* =========================================================================== */
/**
- * <p>Set up this {@link Identifier} instance parsing a {@link URL}.</p>
- *
- * @param url The {@link URL} to parse.
- * @throws MalformedURLException if the URL could not be parsed.
+ * <p>Iterate through a given configuration trying to find the identifiers
+ * located in all element with a given name and in a specified attribute.</p>
+ *
+ * @throws ConfigurationException if an element did not contain the attribute.
*/
- 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);
+ protected Identifier[] collectIdentifiers(Configuration configuration,
+ String parent, String element, String attribute)
+ throws DeployerException {
+
+ /* Check if we were given a parent element name */
+ if (parent != null) configuration = configuration.child(NAMESPACE, parent);
+
+ /* Prepare the iterator of all named children of the configuration */
+ Iterator iterator = configuration.children(NAMESPACE, element);
+ Set collector = new HashSet();
+
+ while (iterator.hasNext()) try {
+ configuration = (Configuration) iterator.next();
+ String identifier = configuration.getStringAttribute(attribute);
+ collector.add(new Identifier(identifier));
+
+ } catch (MalformedURLException exception) {
+ throw new DeployerException("Invalid identifier specified in descriptor "
+ + configuration.location(), exception);
+
+ } catch (ConfigurationException exception) {
+ throw new DeployerException("Element <" + element + "/> does not "
+ + "contain the required " + attribute + " attribute at "
+ + configuration.location(), exception);
}
- /* 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);
+ /* Return whatever we have collected */
+ return (Identifier[]) collector.toArray(new Identifier[collector.size()]);
}
}
Added: cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Identifier.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Identifier.java Tue Nov 2 08:45:57 2004
@@ -0,0 +1,205 @@
+/* =============================================================================== *
+ * Copyright (C) 1999-2004, The Apache Software Foundation. All rights reserved. *
+ * *
+ * Licensed under the Apache License, Version 2.0 (the "License"). You may not use *
+ * this file except in compliance with the License. You may obtain a copy of the *
+ * License at <http://www.apache.org/licenses/LICENSE-2.0>. *
+ * *
+ * Unless required by applicable law or agreed to in writing, software distributed *
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR *
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations under the License. *
+ * =============================================================================== */
+package org.apache.cocoon.kernel.description;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.StringTokenizer;
+
+/**
+ * <p>The {@link Identifier} class encloses a kernel descriptor identifier.</p>
+ *
+ * @author <a href="mailto:pier@apache.org">Pier Fumagalli</a>
+ * @author Copyright © 2000-2004 <a href="http://www.apache.org/">The Apache
+ * Software Foundation</a>. All rights reserved.
+ */
+public class Identifier {
+
+ /** <p>The full URL of the identifier.</p> */
+ private URL url = null;
+ /** <p>The unversioned part of the identifier.</p> */
+ private URL base = null;
+ /** <p>The major version number.</p> */
+ private int major = -1;
+ /** <p>The minor version number.</p> */
+ private int minor = -1;
+ /** <p>The revision number.</p> */
+ private int revision = -1;
+
+ /**
+ * <p>Create a new {@link Identifier} instance.</p>
+ */
+ protected Identifier() {
+ super();
+ }
+
+ /**
+ * <p>Create a new {@link Identifier} instance.</p>
+ */
+ public Identifier(String identifier)
+ throws MalformedURLException {
+ if (identifier == null) throw new NullPointerException("Null identifier");
+ this.setup(new URL(identifier));
+ }
+
+ /**
+ * <p>Create a new {@link Identifier} instance.</p>
+ */
+ public Identifier(URL identifier)
+ throws MalformedURLException {
+ if (identifier == null) throw new NullPointerException("Null identifier");
+ this.setup(identifier);
+ }
+
+ /**
+ * <p>Return the base identifier (URL without version) of this descriptor.</p>
+ */
+ public URL getBaseIdentifier() {
+ if (this.url == null) throw new IllegalStateException();
+ return(this.base);
+ }
+
+ /**
+ * <p>Return the major version number of this descriptor.</p>
+ */
+ public int getMajorVersionNumber() {
+ if (this.url == null) throw new IllegalStateException();
+ return(this.major);
+ }
+
+ /**
+ * <p>Return the minor version number of this descriptor.</p>
+ */
+ public int getMinorVersionNumber() {
+ if (this.url == null) throw new IllegalStateException();
+ return(this.minor);
+ }
+
+ /**
+ * <p>Return the revision number of this descriptor.</p>
+ */
+ public int getRevisionNumber() {
+ if (this.url == null) throw new IllegalStateException();
+ return(this.revision);
+ }
+
+ /**
+ * <p>Check if the the specified {@link Object} equals this instance.</p>
+ */
+ public boolean equals(Object object) {
+ if (this.url == null) throw new IllegalStateException();
+ if (object == null) return(false);
+ if (! (object instanceof Identifier)) return(false);
+ return(this.toURL().equals(((Identifier)object).toURL()));
+ }
+
+ /**
+ * <p>Return the {@link URL} representing the full descriptor identifier.</p>
+ */
+ public URL toURL() {
+ if (this.url == null) throw new IllegalStateException();
+ return(this.url);
+ }
+
+ /**
+ * <p>Return the {@link String} representing the full descriptor identifier.</p>
+ */
+ public String toString() {
+ if (this.url == null) throw new IllegalStateException();
+ return(this.toURL().toString());
+ }
+
+ /**
+ * <p>Return a hash code for this instance.</p>
+ */
+ public int hashCode() {
+ if (this.url == null) throw new IllegalStateException();
+ return(this.toURL().hashCode());
+ }
+
+ /* =========================================================================== */
+ /* PRIVATE METHODS */
+ /* =========================================================================== */
+
+ /**
+ * <p>Set up this {@link Identifier} instance parsing a {@link URL}.</p>
+ *
+ * @param url The {@link URL} to parse.
+ * @throws MalformedURLException if the URL could not be parsed.
+ */
+ protected void setup(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);
+ }
+}
Modified: cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Interface.java
==============================================================================
--- cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Interface.java (original)
+++ cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Interface.java Tue Nov 2 08:45:57 2004
@@ -16,7 +16,8 @@
import org.apache.cocoon.kernel.runtime.DeployerException;
/**
- * <p>An {@link Interface} represents an interface descriptor.</p>
+ * <p>An {@link Interface} is a specialized implementation of a {@link Descriptor}
+ * encloses an kernel interface descriptor in a bean-like object.</p>
*
* @author <a href="mailto:pier@apache.org">Pier Fumagalli</a>
* @author Copyright © 2000-2004 <a href="http://www.apache.org/">The Apache
@@ -39,11 +40,12 @@
super(configuration);
/* Specific interface stuff */
- if (! "interface".equals(configuration.name())) {
+ if (! NAMES[INTERFACE].equals(configuration.name())) {
throw new DeployerException("Invalid root element name for interface "
+ " descriptor at " + configuration.location());
}
-
+
+ /* Interface exposition */
Configuration exposes = configuration.child(NAMESPACE, "exposes");
this.clazz = exposes.getStringAttribute("interface", null);
if (this.clazz == null) {
@@ -51,11 +53,11 @@
+ exposes.location());
}
}
-
+
/**
* <p>Return the class name of the exposed Java™ interface.</p>
*/
- public String getInterface() {
+ public String getInterfaceName() {
return(this.clazz);
}
Modified: cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Library.java
==============================================================================
--- cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Library.java (original)
+++ cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Library.java Tue Nov 2 08:45:57 2004
@@ -18,11 +18,9 @@
import java.util.HashSet;
import java.util.NoSuchElementException;
-import org.apache.cocoon.kernel.runtime.DeployerException;
-
/**
- * <p>The {@link Library} class defines a collection of {@link Descriptor} objects
- * enclosed in a simple {@link HashSet}.</p>
+ * <p>The {@link Library} class defines a collection of {@link Descriptor} instances
+ * backed by a simple {@link HashSet}.</p>
*
* @author <a href="mailto:pier@apache.org">Pier Fumagalli</a>
* @author Copyright © 2000-2004 <a href="http://www.apache.org/">The Apache
@@ -41,13 +39,22 @@
* <p>Add a new {@link Descriptor} to this {@link Library}.</p>
*
* @throws ClassCastException If the {@link Object} is not a {@link Descriptor}.
+ * @throws NullPointerException if the {@link Object} was <b>null</b>.
*/
public boolean add(Object object) {
- return(super.add((Descriptor) object));
+ if (object == null) throw new NullPointerException("Null descriptor");
+
+ if (super.contains(object)) {
+ throw new IllegalArgumentException("Descriptor " + object.toString()
+ + " already present in this Library instance");
+ }
+
+ return (super.add((Descriptor) object));
}
/**
- * <p>Returns an {@link Iterator} over all descriptors of a specified type.</p>
+ * <p>Returns an {@link Iterator} over all {@link Descriptor}s of the specified
+ * type stored in this {@link Library}.</p>
*
* @throws IllegalArgumentException If the type was not recognized.
*/
@@ -59,14 +66,17 @@
* <p>Returns the {@link Descriptor} associated with a specified identifier.</p>
*
* @return A {@link Descriptor} instance or <b>null</b> if not found.
+ * @throws IllegalArgumentException if the identifier was not valid.
+ * @throws NullPointerException if the identifier was <b>null</b>.
*/
- public Descriptor get(String identifier)
- throws DeployerException {
+ public Descriptor get(String identifier) {
if (identifier == null) throw new NullPointerException("Null identifier");
try {
- return this.get(new URL(identifier));
+ return this.get(new Identifier(identifier));
} catch (MalformedURLException e) {
- throw new DeployerException("Invalid descriptor " + identifier, e);
+ String message = "Invalid identifier " + identifier;
+ IllegalArgumentException x = new IllegalArgumentException(message);
+ throw (IllegalArgumentException) x.initCause(e);
}
}
@@ -74,13 +84,31 @@
* <p>Returns the {@link Descriptor} associated with a specified identifier.</p>
*
* @return A {@link Descriptor} instance or <b>null</b> if not found.
+ * @throws IllegalArgumentException if the identifier was not valid.
+ * @throws NullPointerException if the identifier was <b>null</b>.
*/
public Descriptor get(URL identifier) {
if (identifier == null) throw new NullPointerException("Null identifier");
+ try {
+ return this.get(new Identifier(identifier));
+ } catch (MalformedURLException e) {
+ String message = "Invalid identifier " + identifier.toString();
+ IllegalArgumentException x = new IllegalArgumentException(message);
+ throw (IllegalArgumentException) x.initCause(e);
+ }
+ }
+
+ /**
+ * <p>Returns the {@link Descriptor} associated with a specified identifier.</p>
+ *
+ * @return A {@link Descriptor} instance or <b>null</b> if not found.
+ * @throws NullPointerException if the identifier was <b>null</b>.
+ */
+ public Descriptor get(Identifier identifier) {
Iterator iterator = this.iterator();
while (iterator.hasNext()) {
- Descriptor current = (Descriptor) iterator.next();
- if (identifier.equals(current.toURL())) return(current);
+ Descriptor descriptor = (Descriptor) iterator.next();
+ if (descriptor.equals(identifier)) return(descriptor);
}
return(null);
}
Added: cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Module.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/description/Module.java Tue Nov 2 08:45:57 2004
@@ -0,0 +1,49 @@
+/* =============================================================================== *
+ * Copyright (C) 1999-2004, The Apache Software Foundation. All rights reserved. *
+ * *
+ * Licensed under the Apache License, Version 2.0 (the "License"). You may not use *
+ * this file except in compliance with the License. You may obtain a copy of the *
+ * License at <http://www.apache.org/licenses/LICENSE-2.0>. *
+ * *
+ * Unless required by applicable law or agreed to in writing, software distributed *
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR *
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations under the License. *
+ * =============================================================================== */
+package org.apache.cocoon.kernel.description;
+
+import org.apache.cocoon.kernel.configuration.Configuration;
+import org.apache.cocoon.kernel.runtime.DeployerException;
+
+/**
+ * <p>A {@link Module} is a specialized implementation of a {@link Descriptor}
+ * encloses an kernel interface descriptor in a bean-like object.</p>
+ *
+ * @author <a href="mailto:pier@apache.org">Pier Fumagalli</a>
+ * @author Copyright © 2000-2004 <a href="http://www.apache.org/">The Apache
+ * Software Foundation</a>. All rights reserved.
+ */
+public class Module extends Descriptor {
+
+ /**
+ * <p>Create a new {@link Module} instance.</p>
+ */
+ public Module(Configuration configuration)
+ throws DeployerException {
+ super(configuration);
+
+ /* Specific module stuff */
+ String name = configuration.name();
+ if (! NAMES[MODULE].equals(name)) {
+ throw new DeployerException("Invalid root element name for module "
+ + " descriptor at " + configuration.location());
+ }
+ }
+
+ /**
+ * <p>Return the type of this descriptor.</p>
+ */
+ public int getType() {
+ return Descriptor.MODULE;
+ }
+}
Added: cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/Dependencies.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/Dependencies.java Tue Nov 2 08:45:57 2004
@@ -0,0 +1,122 @@
+/* =============================================================================== *
+ * Copyright (C) 1999-2004, The Apache Software Foundation. All rights reserved. *
+ * *
+ * Licensed under the Apache License, Version 2.0 (the "License"). You may not use *
+ * this file except in compliance with the License. You may obtain a copy of the *
+ * License at <http://www.apache.org/licenses/LICENSE-2.0>. *
+ * *
+ * Unless required by applicable law or agreed to in writing, software distributed *
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR *
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations under the License. *
+ * =============================================================================== */
+package org.apache.cocoon.kernel.runtime;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.cocoon.kernel.description.Identifier;
+
+/**
+ * <p>The {@link Dependencies} class provides a simple utility to analyse dependancy
+ * trees in block, interfaces and modules.</p>
+ *
+ * @author <a href="mailto:pier@apache.org">Pier Fumagalli</a>
+ * @author Copyright © 2000-2004 <a href="http://www.apache.org/">The Apache
+ * Software Foundation</a>. All rights reserved.
+ */
+public class Dependencies {
+
+ /** <p>The {@link List} of the current dependancies.</p> */
+ private List dependancies = null;
+
+ /**
+ * <p>Create a new {@link Dependencies} instance.</p>
+ */
+ public Dependencies() {
+ this.dependancies = new ArrayList();
+ }
+
+ /**
+ * <p>Push an {@link Identifier} into this instance.</p>
+ */
+ public void push(Identifier identifier)
+ throws DependencyException {
+ if (identifier == null) throw new NullPointerException("Null identifier");
+
+ /* Loop detected? */
+ if (this.dependancies.contains(identifier)) {
+ List collector = new ArrayList();
+ StringBuffer message = new StringBuffer("Circular dependency detected:");
+ int start = -1;
+ for (int x = 0; x < this.dependancies.size(); x++) {
+ Identifier current = (Identifier) this.dependancies.get(x);
+ if (current.equals(identifier)) start = 1;
+ if (start > 0) {
+ message.append(System.getProperty("line.separator"));
+ message.append(Integer.toString(start ++));
+ message.append(": ");
+ message.append(current);
+ collector.add(current);
+ }
+ }
+ message.append(System.getProperty("line.separator"));
+ message.append(Integer.toString(start ++));
+ message.append(": * ");
+ message.append(identifier);
+ collector.add(identifier);
+
+ Identifier identifiers[] = new Identifier[collector.size()];
+ identifiers = (Identifier[]) collector.toArray(identifiers);
+ throw new DependencyException(message.toString(), identifiers);
+ }
+
+ /* No loop, add the sucker */
+ this.dependancies.add(identifier);
+ }
+
+ /**
+ * <p>Pop the last {@link Identifier} out of this instance.</p>
+ *
+ * @throws IllegalArgumentException if the {@link Identifier} is not the last.
+ */
+ public void pop(Identifier identifier) {
+ int pos = this.dependancies.size() - 1;
+ Identifier last = (Identifier) this.dependancies.get(pos);
+ if (last.equals(identifier)) {
+ this.dependancies.remove(pos);
+ } else {
+ throw new IllegalArgumentException("Invalid pop of \"" + identifier
+ + "\" when last element is \"" + last + "\"");
+ }
+ }
+
+ /**
+ * <p>Return a fully prepared {@link DependencyException}.</p>
+ */
+ public DependencyException fail(String message) {
+ return (this.fail(message, null));
+ }
+
+ /**
+ * <p>Return a fully prepared {@link DependencyException}.</p>
+ */
+ public DependencyException fail(String message, Throwable throwable) {
+ List collector = new ArrayList();
+ StringBuffer buffer = new StringBuffer(message);
+ buffer.append(":");
+
+ for (int x = 0; x < this.dependancies.size(); x++) {
+ Identifier current = (Identifier) this.dependancies.get(x);
+ buffer.append(System.getProperty("line.separator"));
+ buffer.append(Integer.toString(x + 1));
+ buffer.append(": ");
+ buffer.append(current);
+ collector.add(current);
+ }
+
+ Identifier identifiers[] = new Identifier[collector.size()];
+ identifiers = (Identifier[]) collector.toArray(identifiers);
+ return new DependencyException(buffer.toString(), identifiers);
+ }
+}
Added: cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/DependencyException.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/DependencyException.java Tue Nov 2 08:45:57 2004
@@ -0,0 +1,44 @@
+/* =============================================================================== *
+ * Copyright (C) 1999-2004, The Apache Software Foundation. All rights reserved. *
+ * *
+ * Licensed under the Apache License, Version 2.0 (the "License"). You may not use *
+ * this file except in compliance with the License. You may obtain a copy of the *
+ * License at <http://www.apache.org/licenses/LICENSE-2.0>. *
+ * *
+ * Unless required by applicable law or agreed to in writing, software distributed *
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR *
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations under the License. *
+ * =============================================================================== */
+package org.apache.cocoon.kernel.runtime;
+
+import org.apache.cocoon.kernel.description.Identifier;
+
+/**
+ * <p>A {@link DependencyException} is thrown whenever a circular dependancy around
+ * a descriptor is found.</p>
+ *
+ * @author <a href="mailto:pier@apache.org">Pier Fumagalli</a>
+ * @author Copyright © 2000-2004 <a href="http://www.apache.org/">The Apache
+ * Software Foundation</a>. All rights reserved.
+ */
+public class DependencyException extends DeployerException {
+
+ /** <p>The array of identifiers in circular dependancy.</p> */
+ private Identifier identifiers[] = null;
+
+ /**
+ * <p>Create a new {@link DependencyException} instance.</p>
+ */
+ protected DependencyException(String message, Identifier identifiers[]) {
+ super(message);
+ this.identifiers = identifiers;
+ }
+
+ /**
+ * <p>Return the ordered array causing circular dependancies.</p>
+ */
+ public Identifier[] getDependencies() {
+ return this.identifiers;
+ }
+}
Modified: cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/Factory.java
==============================================================================
--- cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/Factory.java (original)
+++ cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/Factory.java Tue Nov 2 08:45:57 2004
@@ -24,7 +24,7 @@
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.description.Abstract;
+import org.apache.cocoon.kernel.description.Module;
import org.apache.cocoon.kernel.description.Block;
import org.apache.cocoon.kernel.description.Descriptor;
import org.apache.cocoon.kernel.description.Interface;
@@ -60,15 +60,17 @@
String href = current.getStringAttribute("href");
URL url = new URL(config.locationURL(), href);
Configuration descriptor = ConfigurationBuilder.parse(url);
- if ("abstract".equals(descriptor.name())) {
- library.add(new Abstract(descriptor));
- } else if ("block".equals(descriptor.name())) {
+ String name = descriptor.name();
+
+ if (Descriptor.NAMES[Descriptor.MODULE].equals(name)) {
+ library.add(new Module(descriptor));
+ } else if (Descriptor.NAMES[Descriptor.BLOCK].equals(name)) {
library.add(new Block(descriptor));
- } else if ("interface".equals(descriptor.name())) {
+ } else if (Descriptor.NAMES[Descriptor.INTERFACE].equals(name)) {
library.add(new Interface(descriptor));
} else {
throw new DeployerException("Invalid descriptor root element \""
- + descriptor.name() + "\" found in descriptor at"
+ + descriptor.name() + "\" found in descriptor at "
+ descriptor.location());
}
} catch (DeployerException e) {
Modified: cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/Instance.java
==============================================================================
--- cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/Instance.java (original)
+++ cocoon/whiteboard/kernel/src/org/apache/cocoon/kernel/runtime/Instance.java Tue Nov 2 08:45:57 2004
@@ -18,9 +18,9 @@
import java.util.HashSet;
import java.util.Set;
-import org.apache.cocoon.kernel.description.Abstract;
import org.apache.cocoon.kernel.description.Block;
import org.apache.cocoon.kernel.description.Descriptor;
+import org.apache.cocoon.kernel.description.Identifier;
import org.apache.cocoon.kernel.description.Interface;
import org.apache.cocoon.kernel.description.Library;
@@ -50,49 +50,23 @@
public Instance(Runtime runtime, Block block)
throws DeployerException {
super(block.getLibraries(), runtime);
- Library library = runtime.getLibrary();
-
- /* Add all interfaces that must be implemented directly by this block */
+ this.block = block;
+
+ /* Process all interfaces, all extended blocks and all modules */
+ Dependencies dependencies = new Dependencies();
+ dependencies.push(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 DeployerException("Block " + block.toString()
- + " implements unknown block " + implementations[k]);
- }
- if (descriptor.getType() != Descriptor.INTERFACE) {
- throw new DeployerException("Block " + block.toString()
- + " implements non-interface " + descriptor.toString());
- }
- String clazz = ((Interface) descriptor).getInterface();
- try {
- interfaces.add(runtime.loadClass(clazz));
- } catch (ClassNotFoundException e) {
- throw new DeployerException("Cant find class " + clazz + " exposed by "
- + "interface " + descriptor.toString() + " implemented by "
- + block.toString());
- }
- }
+ this.process(runtime.getLibrary(), block.getImplementedInterfaces(),
+ dependencies, interfaces, Descriptor.INTERFACE);
+ this.process(runtime.getLibrary(), block.getExtendedBlocks(),
+ dependencies, interfaces, Descriptor.BLOCK);
+ this.process(runtime.getLibrary(), block.getRequiredModules(),
+ dependencies, interfaces, Descriptor.MODULE);
+
+ this.interfaces = new Class[interfaces.size()];
+ this.interfaces = (Class[]) interfaces.toArray(this.interfaces);
- /* 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 DeployerException("Block " + block.toString()
- + " extends unknown block " + extensions[k]);
- }
- if (descriptor.getType() == Descriptor.INTERFACE) {
- throw new DeployerException("Block " + block.toString()
- + " extends interface " + descriptor.toString());
- }
- collector.add(block);
- this.process(library, (Abstract) descriptor, collector, interfaces);
- }
-
/* Resolve the component class and verify that it implements what it must */
try {
this.component = this.loadClass(block.getComponent());
@@ -100,10 +74,11 @@
throw new DeployerException("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.interfaces[k].isAssignableFrom(this.component)) continue;
- throw new DeployerException("Component class \"" + this.component.getName()
+
+ throw new DeployerException("Component \"" + this.component.getName()
+ "\" is not assignable from \"" + this.interfaces[k] + "\"");
}
@@ -122,7 +97,7 @@
throw new DeployerException("Initializer method \"" + destroyer
+ "\" for component \"" + block.getComponent() + "\" not found");
}
-
+
/* Remember where we're coming from */
this.block = block;
}
@@ -165,55 +140,74 @@
}
/**
- * <p>Add all libraries provided by a given block and its super-blocks.</p>
+ * <p>Add all interfaces which must be implemented by this block.</p>
*/
- private void process(Library lib, Abstract abs, Set collector, Set interfaces)
- throws DeployerException {
- /* Check circularities */
- if (collector.contains(abs)) {
- throw new DeployerException("Circularity exception analysing "
- + "extensions for block " + abs.toString());
- }
- collector.add(abs);
-
- /* Process interfaces */
- if (abs.getType() == Descriptor.BLOCK) {
- String implementations[] = ((Block)abs).getImplementedInterfaces();
- for (int k = 0; k < implementations.length; k++) {
- Descriptor descriptor = lib.get(implementations[k]);
- if (descriptor == null) {
- throw new DeployerException("Block " + abs.toString() + " imple"
- + "ments unknown interface " + implementations[k]);
- }
- if (descriptor.getType() != Descriptor.INTERFACE) {
- throw new DeployerException("Block " + abs.toString()
- + " implements non-interface " + descriptor.toString());
- }
-
- String clazz = ((Interface) descriptor).getInterface();
- try {
- interfaces.add(this.getParent().loadClass(clazz));
- } catch (ClassNotFoundException e) {
- throw new DeployerException("Cant find class " + clazz
- + " exposed by interface " + descriptor.toString()
- + " implemented by " + abs.toString());
- }
- }
+ private void process(Library library, Identifier identifiers[],
+ Dependencies dependencies, Set interfaces, int type)
+ throws DependencyException {
+ for (int x = 0; x < identifiers.length; x ++) {
+ this.process(library, identifiers[x], dependencies, interfaces, type);
+ }
+ }
+
+ /**
+ * <p>Add all interfaces which must be implemented by this block.</p>
+ */
+ private void process(Library library, Identifier identifier,
+ Dependencies dependencies, Set interfaces, int type)
+ throws DependencyException {
+ /* Dependencies check */
+ dependencies.push(identifier);
+
+ /* Analyse current interface */
+ Descriptor desc = library.get(identifier);
+ if (desc == null) {
+ throw dependencies.fail("Descriptor " + identifier + " unknonwn");
+ }
+
+ /* Make sure that we are getting what we want */
+ if (type != desc.getType()) {
+ throw dependencies.fail("Invalid descriptor type for " + desc
+ + ": required \"" + Descriptor.NAMES[type] + "\" found \""
+ + Descriptor.NAMES[desc.getType()] + "\"");
}
- /* Process libraries */
- URL libraries[] = abs.getLibraries();
- for (int k = 0; k < libraries.length; k++) {
- super.addURL(libraries[k]);
- }
- String extensions[] = abs.getExtendedBlocks();
- for (int k = 0; k < extensions.length; k++) {
- Descriptor descriptor = lib.get(extensions[k]);
- if (descriptor.getType() == Descriptor.INTERFACE) {
- throw new DeployerException("Block " + abs.toString()
- + " extends interface " + descriptor.toString());
+ /* Add java interfaces exposed by interface blocks */
+ if (type == Descriptor.INTERFACE) {
+ String clazz = ((Interface) desc).getInterfaceName();
+ try {
+ /* Load in the parent classloader, the runtime */
+ interfaces.add(this.getParent().loadClass(clazz));
+ } catch (Throwable t) {
+ throw dependencies.fail("Unable to locate or access " + clazz
+ + " for interface " + identifier, t);
}
- this.process(lib, (Abstract) descriptor, collector, interfaces);
}
+
+ /* Add the libraries if this is a block or a module */
+ if ((type == Descriptor.BLOCK) || (type == Descriptor.MODULE)) {
+ URL libs[] = desc.getLibraries();
+ for (int x = 0; x < libs.length; x ++) super.addURL(libs[x]);
+ }
+
+ /* Process extensions declared by the descriptor */
+ Identifier identifiers[] = desc.getExtendedBlocks();
+ this.process(library, identifiers, dependencies, interfaces, type);
+
+ /* Process interfaces and modules of a block */
+ if (type == Descriptor.BLOCK) {
+ Block block = (Block) desc;
+
+ identifiers = block.getImplementedInterfaces();
+ type = Descriptor.INTERFACE;
+ this.process(library, identifiers, dependencies, interfaces, type);
+
+ identifiers = block.getRequiredModules();
+ type = Descriptor.MODULE;
+ this.process(library, identifiers, dependencies, interfaces, type);
+ }
+
+ /* Pop from the dependencies check */
+ dependencies.pop(identifier);
}
}