sylvain 01/11/12 10:07:43 Modified: scratchpad/src/org/apache/cocoon/treeprocessor AbstractParentProcessingNode.java AbstractParentProcessingNodeBuilder.java AbstractProcessingNode.java AbstractProcessingNodeBuilder.java EnvironmentSourceResolver.java ListOfMapsResolver.java ProcessingNode.java ProcessingNodeBuilder.java TreeBuilder.java TreeBuilderComponentManager.java TreeProcessor.java treeprocessor.xconf scratchpad/src/org/apache/cocoon/treeprocessor/sitemap ActionNode.java ComponentsNodeBuilder.java GeneratorNode.java GeneratorNodeBuilder.java PipelineNode.java SitemapNode.java SitemapNodeBuilder.java Added: scratchpad/src/org/apache/cocoon/treeprocessor ProcessingLanguageException.java scratchpad/src/org/apache/cocoon/treeprocessor/sitemap PipelineNodeBuilder.java PipelinesNode.java PipelinesNodeBuilder.java Log: Update to scratchpad Revision Changes Path 1.2 +31 -26 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/AbstractParentProcessingNode.java Index: AbstractParentProcessingNode.java =================================================================== RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/AbstractParentProcessingNode.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- AbstractParentProcessingNode.java 2001/11/08 14:39:23 1.1 +++ AbstractParentProcessingNode.java 2001/11/12 18:07:43 1.2 @@ -19,58 +19,63 @@ /** * * @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a> - * @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:23 $ + * @version CVS $Revision: 1.2 $ $Date: 2001/11/12 18:07:43 $ */ public abstract class AbstractParentProcessingNode extends AbstractProcessingNode { - protected ProcessingNode[] childNodes; - /** - * Invoke in order all children, until one fails. + * Invoke all nodes of a node array in order, until one succeeds. * * @parameter currentMap the <code>Map<code> of parameters produced by this node, - * which is added to <code>listOfMap</code> if not null. + * which is added to <code>listOfMap</code>. */ - protected boolean invokeChildren ( + protected static final boolean invokeNodes ( + ProcessingNode[] nodes, Environment env, StreamPipeline pipeline, EventPipeline eventPipeline, List listOfMaps, Map currentMap) throws Exception { - if (currentMap != null) { - listOfMaps.add(currentMap); - } + listOfMaps.add(currentMap); - boolean success = true; - for (int i = 0; i < childNodes.length; i++) { - if (! childNodes[i].invoke(env, pipeline, eventPipeline, listOfMaps)) { - success = false; - break; - } - } + boolean success = invokeNodes(nodes, env, pipeline, eventPipeline, listOfMaps); - if (currentMap != null) { - listOfMaps.remove(listOfMaps.size() - 1); - } + listOfMaps.remove(listOfMaps.size() - 1); return success; } /** - * Disposes all children of this node. + * Invoke all nodes of a node array in order, until one succeeds. */ - protected void disposeChildren() { - for (int i = 0; i < childNodes.length; i++) { - childNodes[i].dispose(); + protected static final boolean invokeNodes ( + ProcessingNode[] nodes, + Environment env, + StreamPipeline pipeline, + EventPipeline eventPipeline, + List listOfMaps) + throws Exception { + + for (int i = 0; i < nodes.length; i++) { + if (nodes[i].invoke(env, pipeline, eventPipeline, listOfMaps)) { + return true; + } } + + return false; } - + /** - * Dispose this node. At this level, simply call <code>disposeChildren()</code>. + * Dispose all nodes in an array. */ - public void dispose() { - disposeChildren(); + protected static final void disposeNodes(ProcessingNode[] nodes) { + if (nodes == null) + return; + + for (int i = 0; i < nodes.length; i++) { + nodes[i].dispose(); + } } } 1.2 +103 -1 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/AbstractParentProcessingNodeBuilder.java Index: AbstractParentProcessingNodeBuilder.java =================================================================== RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/AbstractParentProcessingNodeBuilder.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- AbstractParentProcessingNodeBuilder.java 2001/11/08 14:39:23 1.1 +++ AbstractParentProcessingNodeBuilder.java 2001/11/12 18:07:43 1.2 @@ -10,12 +10,114 @@ import org.apache.avalon.framework.logger.AbstractLoggable; +import java.util.*; +import org.apache.avalon.framework.configuration.Configurable; +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.ConfigurationException; + +import org.apache.cocoon.util.StringUtils; + /** + * Base class for parent <code>ProcessingNodeBuilders</code>, providing services for parsing + * children nodes. * * @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a> - * @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:23 $ + * @version CVS $Revision: 1.2 $ $Date: 2001/11/12 18:07:43 $ */ + +public abstract class AbstractParentProcessingNodeBuilder extends AbstractProcessingNodeBuilder implements Configurable { + + protected Collection allowedChildren; + + protected Collection forbiddenChildren; + + protected Collection ignoredChildren; + + /** + * Configure the sets of allowed, forbidden and ignored children nodes. + */ + public void configure(Configuration config) throws ConfigurationException { + this.allowedChildren = getStringCollection(config.getChild("allowed-children")); + this.forbiddenChildren = getStringCollection(config.getChild("forbidden-children")); + this.ignoredChildren = getStringCollection(config.getChild("ignored-children")); + } + + /** + * Create the <code>ProcessingNodeBuilder</code>s for the children of a given node. + * Child nodes are controlled to be actually allowed in this node. + */ + protected List createChildBuilders(Configuration config, Map buildModel) throws Exception { + + Configuration[] children = config.getChildren(); + List result = new ArrayList(); + + for (int i = 0; i < children.length; i++) { + + Configuration child = children[i]; + checkNamespace(child); + String name = child.getName(); + + // Is this element to be ignored ? + if (ignoredChildren != null && ignoredChildren.contains(name)) { + getLogger().debug("Element '" + name + "' is ignored for building children of element '" + + config.getName() + "'"); + + continue; + } + + // Is it allowed ? + if ( (allowedChildren != null && !allowedChildren.contains(name)) || + (forbiddenChildren != null && forbiddenChildren.contains(name)) ) { + throw new ConfigurationException("Element '" + name + "' is not allowed at " + + child.getLocation()); + } + + // OK : get a builder. + ProcessingNodeBuilder childBuilder = this.treeBuilder.createNodeBuilder(child); + childBuilder.buildNode(child, buildModel); + result.add(childBuilder); + } + + return result; + } + + /** + * Collect nodes from a list of builders, taking care of builders that may + * return null nodes. + */ + protected ProcessingNode[] getNodes(List builderList) throws Exception { + + List result = new ArrayList(); + + Iterator iter = builderList.iterator(); + while(iter.hasNext()) { + ProcessingNode node = ((ProcessingNodeBuilder)iter.next()).getNode(); + if (node != null) { + result.add(node); + } + } + + return toNodeArray(result); + } + + /** + * Convenience function that converts a <code>List</code> of <code>ProcessingNode</code>s + * to an array. + */ + public static ProcessingNode[] toNodeArray(List list) { + return (ProcessingNode[])list.toArray(new ProcessingNode[list.size()]); + } + + /** + * Splits the value of a Configuration in a Collection of Strings. + * + * @return a collection of Strings, or null if <code>config</code> has no value. + */ + private Collection getStringCollection(Configuration config) { + String s = config.getValue(null); + + return (s == null) ? null : Arrays.asList(StringUtils.split(s, ", ")); + } -public abstract class AbstractParentProcessingNodeBuilder extends AbstractProcessingNodeBuilder { } 1.2 +26 -4 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/AbstractProcessingNode.java Index: AbstractProcessingNode.java =================================================================== RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/AbstractProcessingNode.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- AbstractProcessingNode.java 2001/11/08 14:39:23 1.1 +++ AbstractProcessingNode.java 2001/11/12 18:07:43 1.2 @@ -26,20 +26,42 @@ /** * * @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a> - * @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:23 $ + * @version CVS $Revision: 1.2 $ $Date: 2001/11/12 18:07:43 $ */ public abstract class AbstractProcessingNode extends AbstractLoggable implements ProcessingNode { - /** The node parameters, as a <code>Map</code> of <code>ListOfMapsResolver</code>. */ + /** The node parameters, as a <code>Map</code> of <code>ListOfMapsResolver</code>s. */ protected Map parameters; - protected SourceResolver getSourceResolver(Map objectModel) { + protected String location = "unknown location"; + + /** + * Get the <code>SourceResolver</code> in an object model. + */ + protected static final SourceResolver getSourceResolver(Map objectModel) { return (SourceResolver)objectModel.get(OBJECT_SOURCE_RESOLVER); } + + /** + * Set the parameters of this node as a <code>Map</code> of <code>ListOfMapsResolver</code>s + * that will be resolved at process-time. + */ + public void setParameters(Map parameters) { + } + + /** + * Get the location of this node. + */ + public String getLocation() { + return this.location; + } - protected Redirector getRedirector(Map objectModel) { - return (Redirector)objectModel.get(OBJECT_REDIRECTOR); + /** + * Set the location of this node. + */ + public void setLocation(String location) { + this.location = location; } /** 1.2 +5 -5 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/AbstractProcessingNodeBuilder.java Index: AbstractProcessingNodeBuilder.java =================================================================== RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/AbstractProcessingNodeBuilder.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- AbstractProcessingNodeBuilder.java 2001/11/08 14:39:23 1.1 +++ AbstractProcessingNodeBuilder.java 2001/11/12 18:07:43 1.2 @@ -24,21 +24,21 @@ /** * * @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a> - * @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:23 $ + * @version CVS $Revision: 1.2 $ $Date: 2001/11/12 18:07:43 $ */ public abstract class AbstractProcessingNodeBuilder extends AbstractLoggable implements ProcessingNodeBuilder { - protected TreeBuilder builder; + protected TreeBuilder treeBuilder; - public void setBuilder(TreeBuilder builder) { - this.builder = builder; + public void setBuilder(TreeBuilder treeBuilder) { + this.treeBuilder = treeBuilder; } /** - * Get <xxx:parameter> elements as a <ocd>Map</code> of </code>ListOfMapResolver</code>s, + * Get <xxx:parameter> elements as a <code>Map</code> of </code>ListOfMapResolver</code>s, * that can be turned into parameters using <code>ListOfMapResolver.buildParameters()</code>. * * @return the Map of ListOfMapResolver, or <code>null</code> if there are no parameters. @@ -59,7 +59,7 @@ params.put(child.getAttribute("name"), ListOfMapsResolver.getResolver(value)); } catch(PatternException pe) { throw new ConfigurationException("Invalid pattern '" + value + - ", at " + child.getLocation()); + " at " + child.getLocation()); } } } 1.2 +0 -0 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/EnvironmentSourceResolver.java Index: EnvironmentSourceResolver.java =================================================================== RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/EnvironmentSourceResolver.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- EnvironmentSourceResolver.java 2001/11/08 14:39:23 1.1 +++ EnvironmentSourceResolver.java 2001/11/12 18:07:43 1.2 @@ -26,7 +26,7 @@ * A <code>SourceResolver</code> that resolves URIs relative to an <code>Environment</code>. * * @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a> - * @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:23 $ + * @version CVS $Revision: 1.2 $ $Date: 2001/11/12 18:07:43 $ */ public class EnvironmentSourceResolver implements SourceResolver, Disposable { 1.2 +4 -2 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/ListOfMapsResolver.java Index: ListOfMapsResolver.java =================================================================== RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/ListOfMapsResolver.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- ListOfMapsResolver.java 2001/11/08 14:39:23 1.1 +++ ListOfMapsResolver.java 2001/11/12 18:07:43 1.2 @@ -21,7 +21,7 @@ * Utility class for handling {...} pattern substitutions from a List of Maps. * * @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a> - * @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:23 $ + * @version CVS $Revision: 1.2 $ $Date: 2001/11/12 18:07:43 $ */ public abstract class ListOfMapsResolver extends AbstractLoggable { @@ -137,10 +137,12 @@ * No-op resolver for expressions that don't need to be resolved. */ private static class NullResolver extends ListOfMapsResolver { - private String expression; + private String expression = null; public NullResolver(String expression) { - this.expression = this.unescape(expression); + if (expression != null) { + this.expression = this.unescape(expression); + } } public String resolve(List listOfMaps) { 1.2 +4 -0 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/ProcessingNode.java Index: ProcessingNode.java =================================================================== RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/ProcessingNode.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- ProcessingNode.java 2001/11/08 14:39:23 1.1 +++ ProcessingNode.java 2001/11/12 18:07:43 1.2 @@ -23,7 +23,7 @@ * on the root node. * * @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a> - * @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:23 $ + * @version CVS $Revision: 1.2 $ $Date: 2001/11/12 18:07:43 $ */ public interface ProcessingNode extends ThreadSafe, Disposable { @@ -48,4 +48,8 @@ */ void dispose(); + /** + * Get the location of this node. + */ + String getLocation(); } 1.2 +0 -0 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/ProcessingNodeBuilder.java Index: ProcessingNodeBuilder.java =================================================================== RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/ProcessingNodeBuilder.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- ProcessingNodeBuilder.java 2001/11/08 14:39:23 1.1 +++ ProcessingNodeBuilder.java 2001/11/12 18:07:43 1.2 @@ -34,7 +34,7 @@ * implementations. * * @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a> - * @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:23 $ + * @version CVS $Revision: 1.2 $ $Date: 2001/11/12 18:07:43 $ */ import java.util.Map; 1.2 +14 -11 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/TreeBuilder.java Index: TreeBuilder.java =================================================================== RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/TreeBuilder.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- TreeBuilder.java 2001/11/08 14:39:23 1.1 +++ TreeBuilder.java 2001/11/12 18:07:43 1.2 @@ -38,23 +38,19 @@ /** * * @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a> - * @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:23 $ + * @version CVS $Revision: 1.2 $ $Date: 2001/11/12 18:07:43 $ */ public class TreeBuilder extends AbstractLoggable implements Composable, Configurable, Contextualizable, LogKitManageable { /** - * The role name to be used by composable <code>ProcessingNodeBuilder</code>s to get - * the <code>Builder</code> for which they operate. - */ - public static final String ROLE = "org.apache.cocoon.components.treeprocessor.Builder"; - - /** * The categories of node Maps. */ private Map categories = new HashMap(); + private Map attributes = new HashMap(); + /** * The tree processor that we're building. */ @@ -114,7 +110,7 @@ this.languageName = config.getAttribute("name"); getLogger().debug("Configuring Builder for language : " + this.languageName); - this.namespace = config.getAttribute("namespace"); + this.namespace = config.getChild("namespace").getAttribute("uri", ""); try { // Create the NodeBuilder selector. @@ -184,7 +180,7 @@ * For example, <code>ResourceNodeBuilder</code> stores here the <code>ProcessingNode</code> * it produces for use by sitemap pipelines. This allows to turn the tree into a graph. */ - public void addNode(ProcessingNode node, String category, String name) { + public void addNode(String category, String name,ProcessingNode node) { Map nodes = (Map)categories.get(category); if (nodes == null) { nodes = new HashMap(); @@ -207,6 +203,14 @@ } } + public void setAttribute(String name, Object value) { + this.attributes.put(name, value); + } + + public Object getAttribute(String name) { + return this.attributes.get(name); + } + /** * Some NodeBuilders create components to be used by others */ @@ -222,9 +226,8 @@ public ProcessingNodeBuilder createNodeBuilder(Configuration config) throws Exception { //FIXME : check namespace String nodeName = config.getName(); - int pos; - if ((pos = nodeName.indexOf(':')) != -1) - nodeName = nodeName.substring(pos+1); + + getLogger().debug("Creating node builder for " + nodeName); ProcessingNodeBuilder builder = (ProcessingNodeBuilder)this.builderSelector.select(nodeName); builder.setBuilder(this); 1.2 +0 -0 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/TreeBuilderComponentManager.java Index: TreeBuilderComponentManager.java =================================================================== RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/TreeBuilderComponentManager.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- TreeBuilderComponentManager.java 2001/11/08 14:39:23 1.1 +++ TreeBuilderComponentManager.java 2001/11/12 18:07:43 1.2 @@ -23,7 +23,7 @@ * enriched through <code>Builder.addComponent()</code>. * * @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a> - * @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:23 $ + * @version CVS $Revision: 1.2 $ $Date: 2001/11/12 18:07:43 $ */ 1.2 +0 -0 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/TreeProcessor.java Index: TreeProcessor.java =================================================================== RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/TreeProcessor.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- TreeProcessor.java 2001/11/08 14:39:23 1.1 +++ TreeProcessor.java 2001/11/12 18:07:43 1.2 @@ -45,7 +45,7 @@ * Interpreted tree-traversal implementation of the a Processor language. * * @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a> - * @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:23 $ + * @version CVS $Revision: 1.2 $ $Date: 2001/11/12 18:07:43 $ */ public class TreeProcessor extends AbstractLoggable implements ThreadSafe, Processor, 1.2 +27 -16 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/treeprocessor.xconf Index: treeprocessor.xconf =================================================================== RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/treeprocessor.xconf,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- treeprocessor.xconf 2001/11/08 14:39:23 1.1 +++ treeprocessor.xconf 2001/11/12 18:07:43 1.2 @@ -9,48 +9,59 @@ ***************************************************************************** @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a> - @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:23 $ + @version CVS $Revision: 1.2 $ $Date: 2001/11/12 18:07:43 $ --> <tree-processor> <!-- The sitemap language --> - <language name="sitemap" namespace="http://apache.org/cocoon/sitemap/1.0"> + <language name="sitemap"> - <!-- Should we allow to specify the builder class ? --> - <!-- builder class="org.apache.cocoon.treeprocessor.Builder"/ --> - + <!-- The namespace for this language --> + <namespace uri="http://apache.org/cocoon/sitemap/1.0"/> + <!-- The file name for this language --> <file name="sitemap.xmap"/> <nodes> + <!-- Note : for now, names are prefixed, but they'll be removed with the namespace-aware Configuration--> <!-- Sitemap root node --> - <node name="sitemap" builder="org.apache.cocoon.treeprocessor.sitemap.SitemapNodeBuilder"> - <allowed-children>components, pipeline, views, resources, action-sets</allowed-children> + <node name="map:sitemap" builder="org.apache.cocoon.treeprocessor.sitemap.SitemapNodeBuilder"> + <allowed-children>map:pipelines, map:components</allowed-children> + <!-- the children below will be allowed when implemented :) --> + <ignored-children>map:views, map:resources, map:action-sets</ignored-children> </node> <!-- Components definition : fills selectors on the TreeProcessor --> - <node name="components" builder="org.apache.cocoon.treeprocessor.sitemap.ComponentsNodeBuilder"> - <selector section="matchers" elements="matcher" + <node name="map:components" builder="org.apache.cocoon.treeprocessor.sitemap.ComponentsNodeBuilder"> + <selector section="map:matchers" elements="map:matcher" role="org.apache.cocoon.matching.MatcherSelector"/> - <selector section="selectors" elements="selector" + <selector section="map:selectors" elements="map:selector" role="org.apache.cocoon.selection.SelectorSelector"/> - <selector section="actions" elements="action" + <selector section="map:actions" elements="map:action" role="org.apache.cocoon.acting.ActionSelector"/> - <selector section="generators" elements="generator" + <selector section="map:generators" elements="map:generator" role="org.apache.cocoon.generation.GeneratorSelector"/> - <selector section="transformers" elements="transformer" + <selector section="map:transformers" elements="map:transformer" role="org.apache.cocoon.transformation.TransformerSelector"/> - <selector section="serializers" elements="serializer" + <selector section="map:serializers" elements="map:serializer" role="org.apache.cocoon.serialization.SerializerSelector"/> - <selector section="readers" elements="reader" + <selector section="map:readers" elements="map:reader" role="org.apache.cocoon.reading.ReaderSelector"/> </node> + + <node name="map:pipelines" builder="org.apache.cocoon.treeprocessor.sitemap.PipelinesNodeBuilder"> + <allowed-children>map:pipeline</allowed-children> + </node> + + <node name="map:pipeline" builder="org.apache.cocoon.treeprocessor.sitemap.PipelineNodeBuilder"> + <forbidden-children>map:sitemap, map:components, map:pipelines</forbidden-children> + </node> - <!--node name="action" builder="org.apache.cocoon.treeprocessor.sitemap.ActionNodeBuilder"> + <!--node name="map:action" builder="org.apache.cocoon.treeprocessor.sitemap.ActionNodeBuilder"> <forbidden-children>sitemap, components, pipeline, error-handler</forbidden-children> </node--> - <node name="generator" builder="org.apache.cocoon.treeprocessor.sitemap.GeneratorNodeBuilder"/> + <node name="map:generate" builder="org.apache.cocoon.treeprocessor.sitemap.GeneratorNodeBuilder"/> </nodes> </language> 1.1 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/ProcessingLanguageException.java Index: ProcessingLanguageException.java =================================================================== /***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.cocoon.treeprocessor; import org.apache.avalon.framework.CascadingException; import java.io.PrintStream; import java.io.PrintWriter; /** * Exception thrown when there's something wrong in the syntax of a * processing language (i.e. sitemap). * * @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a> * @version CVS $Revision: 1.1 $ $Date: 2001/11/12 18:07:43 $ */ public class ProcessingLanguageException extends CascadingException { /** * Create a new <code>ProcessingLanguageException</code> instance. */ public ProcessingLanguageException(String message) { super(message, null); } /** * Create a new <code>ProcessingLanguageException</code> instance. * * @param ex the originating <code>Exception</code> */ public ProcessingLanguageException(Exception ex) { super(ex.getMessage(), ex); } /** * Construct a new <code>ProcessingLanguageException</code> that references * a parent Exception. */ public ProcessingLanguageException(String message, Throwable t) { super(message, t); } public String toString() { StringBuffer s = new StringBuffer(); s.append(super.toString()); if(getCause()!=null) { s.append(": "); s.append(getCause().toString()); } return s.toString(); } public void printStackTrace() { super.printStackTrace(); if(getCause()!=null) getCause().printStackTrace(); } public void printStackTrace( PrintStream s ) { super.printStackTrace(s); if(getCause()!=null) getCause().printStackTrace(s); } public void printStackTrace( PrintWriter s ) { super.printStackTrace(s); if(getCause()!=null) getCause().printStackTrace(s); } } 1.2 +40 -18 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/sitemap/ActionNode.java Index: ActionNode.java =================================================================== RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/sitemap/ActionNode.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- ActionNode.java 2001/11/08 14:39:24 1.1 +++ ActionNode.java 2001/11/12 18:07:43 1.2 @@ -21,7 +21,9 @@ import org.apache.cocoon.components.pipeline.StreamPipeline; import org.apache.cocoon.sitemap.PatternException; +import org.apache.cocoon.sitemap.SitemapRedirector; +import org.apache.cocoon.treeprocessor.ProcessingNode; import org.apache.cocoon.treeprocessor.AbstractParentProcessingNode; import org.apache.cocoon.treeprocessor.ListOfMapsResolver; @@ -30,13 +32,16 @@ /** * * @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a> - * @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:24 $ + * @version CVS $Revision: 1.2 $ $Date: 2001/11/12 18:07:43 $ */ public class ActionNode extends AbstractParentProcessingNode { + /** The childrens of this action */ + protected ProcessingNode[] children; + /** The action name */ - protected String name; + protected String actionName; /** The 'src' attribute */ protected ListOfMapsResolver source; @@ -48,16 +53,20 @@ protected Action threadSafeAction; public ActionNode(String name, String source) throws PatternException { - this.name = name; + this.actionName = name; this.source = ListOfMapsResolver.getResolver(source); } + public void setChildren(ProcessingNode[] children) { + this.children = children; + } + public void setSelector(ComponentSelector selector) throws ComponentException { this.selector = selector; // Is it a ThreadSafe action ? - Action action = (Action)selector.select(name); + Action action = (Action)selector.select(actionName); if (action instanceof ThreadSafe) { // Yes : keep it. this.threadSafeAction = action; @@ -72,39 +81,52 @@ // Extract required data from the object model Map objectModel = env.getObjectModel(); - - // Execute the action - Action action = this.threadSafeAction; - if (action == null) { - action = (Action)this.selector.select(this.name); - } - + SitemapRedirector redirector = SitemapNode.getRedirector(env); Map actionResult; - try { - actionResult = action.act( - getRedirector(objectModel), + + if (this.threadSafeAction != null) { + actionResult = this.threadSafeAction.act( + redirector, getSourceResolver(objectModel), objectModel, source.resolve(listOfMaps), ListOfMapsResolver.buildParameters(this.parameters, listOfMaps) ); - } finally { - if (this.threadSafeAction == null) { + + } else { + Action action = (Action)this.selector.select(this.actionName); + try { + actionResult = action.act( + redirector, + getSourceResolver(objectModel), + objectModel, + source.resolve(listOfMaps), + ListOfMapsResolver.buildParameters(this.parameters, listOfMaps) + ); + } finally { this.selector.release(action); } } + if (redirector.hasRedirected()) { + return true; + } + if (actionResult == null) { // Action failed return false; } else { - // Action succeeded : process children - return this.invokeChildren(env, pipeline, eventPipeline, listOfMaps, actionResult); + // Action succeeded : process children if there are some. + if (this.children != null) { + return this.invokeNodes(this.children, env, pipeline, eventPipeline, listOfMaps, actionResult); + } else { + return true; + } } } public void dispose() { - super.dispose(); + disposeNodes(children); if (this.threadSafeAction != null) { this.selector.release(this.threadSafeAction); } 1.2 +43 -17 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/sitemap/ComponentsNodeBuilder.java Index: ComponentsNodeBuilder.java =================================================================== RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/sitemap/ComponentsNodeBuilder.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- ComponentsNodeBuilder.java 2001/11/08 14:39:24 1.1 +++ ComponentsNodeBuilder.java 2001/11/12 18:07:43 1.2 @@ -27,6 +27,8 @@ import org.apache.avalon.framework.component.ComponentManager; import org.apache.avalon.framework.component.ComponentSelector; +import org.apache.cocoon.sitemap.SitemapComponentSelector; + import org.apache.cocoon.treeprocessor.AbstractProcessingNodeBuilder; import org.apache.cocoon.treeprocessor.ProcessingNode; @@ -40,14 +42,18 @@ * but creates <code>ComponentSelectors</code> that are made available to other nodes. * * @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a> - * @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:24 $ + * @version CVS $Revision: 1.2 $ $Date: 2001/11/12 18:07:43 $ */ public class ComponentsNodeBuilder extends AbstractProcessingNodeBuilder implements Composable, Configurable, Contextualizable, LogKitManageable { - /** The hint name to use to select the default component in a selector */ - public static final String DEFAULT_HINT = "!default!"; + /** + * The prefix used to store default components as <code>TreeBuilder</code> attributes. + * For example, the default generator (if any) can be obtained using + * <code>builder.getAttribute(ComponentsNodeBuilder.DEFAULT_PREFIX + "generator")</code>. + */ + public static final String DEFAULT_PREFIX = "components:default-"; private Context context; @@ -97,16 +103,21 @@ /** * Build a <code>ComponentSelector</code> for each component section and add it - * each component contained in the section. Selectors are also published on the - * <code>TreeBuilder</code> for use by other nodes. + * each component contained in the section. + * <p> + * Selectors are added to the component manager using <code>TreeBuilder.addComponent()</code> + * for use by other nodes. + * <p> + * For each section for which a default is provided (e.g. <code><generators default="file"></code>), + * this default is registred as an attribute on the builder */ public void buildNode(Configuration config, Map buildModel) throws Exception { // Iterate on all sections Configuration[] sections = config.getChildren(); - for (int i = 0; i < sections.length; i++) { + for (int sectIdx = 0; sectIdx < sections.length; sectIdx++) { - Configuration section = sections[i]; + Configuration section = sections[sectIdx]; checkNamespace(section); String sectionName = section.getName(); @@ -122,8 +133,10 @@ String defaultElement = section.getAttribute("default", null); if (defaultElement == null) { getLogger().debug("Component section '" + sectionName + "' has no default"); + } else { + this.treeBuilder.setAttribute(DEFAULT_PREFIX + elementName, defaultElement); } - + // Create the selector for this section getLogger().debug("Creating component selector for " + sectionName); @@ -136,20 +149,19 @@ throw new ComponentException("Cannot configure role manager", ce); } - ExcaliburComponentSelector selector = new ExcaliburComponentSelector(); + SitemapComponentSelector selector = new SitemapComponentSelector(); selector.setLogger(getLogger()); selector.contextualize(this.context); selector.setRoleManager(emptyRoleManager); selector.setLogKitManager(this.logKit); selector.compose(this.manager); // selector.configure( - no configuration - ); - - + // Iterate on all components Configuration[] elements = section.getChildren(); - for (int j = 0; i < elements.length; j++) { + for (int compIdx = 0; compIdx < elements.length; compIdx++) { - Configuration element = elements[i]; + Configuration element = elements[compIdx]; checkNamespace(element); // Is it the right name ? @@ -161,7 +173,7 @@ // Get the element name String name = element.getAttribute("name"); - // Register the class + // Get the class String className = element.getAttribute("src"); Class clazz; try { @@ -171,12 +183,13 @@ "' for " + elementName + " '" + name + "', at " + element.getLocation(), e); } + // Get the mime-type, if any + String mimeType = element.getAttribute("mime-type", null); + // Register the component selector.addComponent(name, clazz, element); + if (name.equals(defaultElement)) { - // Also register as default component - selector.addComponent(DEFAULT_HINT, clazz, element); - // Clear default to mark it as found defaultElement = null; } @@ -188,10 +201,23 @@ "' does not exist, at " + section.getLocation()); } + // Chain with parent processor selector, if any + String role = (String)this.sectionRoles.get(sectionName); + try { + SitemapComponentSelector parentSelector = + (SitemapComponentSelector)this.manager.lookup(role); + + // Found. + selector.setParentSelector(parentSelector); + + } catch (ComponentException ce) { + // Ignore : means no parent + } + selector.initialize(); // Publish the selector - this.builder.addComponentInstance((String)this.sectionRoles.get(sectionName), selector); + this.treeBuilder.addComponentInstance(role , selector); } // end for sections } 1.2 +11 -4 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/sitemap/GeneratorNode.java Index: GeneratorNode.java =================================================================== RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/sitemap/GeneratorNode.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- GeneratorNode.java 2001/11/08 14:39:24 1.1 +++ GeneratorNode.java 2001/11/12 18:07:43 1.2 @@ -11,6 +11,7 @@ import org.apache.cocoon.environment.Environment; import org.apache.cocoon.components.pipeline.EventPipeline; import org.apache.cocoon.components.pipeline.StreamPipeline; +import org.apache.cocoon.sitemap.PatternException; import org.apache.cocoon.treeprocessor.AbstractProcessingNode; import org.apache.cocoon.treeprocessor.ListOfMapsResolver; @@ -18,15 +19,20 @@ /** * * @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a> - * @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:24 $ + * @version CVS $Revision: 1.2 $ $Date: 2001/11/12 18:07:43 $ */ public class GeneratorNode extends AbstractProcessingNode { - protected String generatorName; + private String generatorName; - protected ListOfMapsResolver source; - + private ListOfMapsResolver source; + + public GeneratorNode(String name, String source) throws PatternException { + this.generatorName = name; + this.source = ListOfMapsResolver.getResolver(source); + } + public boolean invoke(Environment env, StreamPipeline pipeline, EventPipeline eventPipeline, List listOfMaps) throws Exception { @@ -36,7 +42,8 @@ ListOfMapsResolver.buildParameters(this.parameters, listOfMaps) ); - return true; + // Return false to contine sitemap invocation + return false; } } 1.2 +24 -2 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/sitemap/GeneratorNodeBuilder.java Index: GeneratorNodeBuilder.java =================================================================== RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/sitemap/GeneratorNodeBuilder.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- GeneratorNodeBuilder.java 2001/11/08 14:39:24 1.1 +++ GeneratorNodeBuilder.java 2001/11/12 18:07:43 1.2 @@ -9,6 +9,7 @@ package org.apache.cocoon.treeprocessor.sitemap; import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.cocoon.treeprocessor.AbstractProcessingNodeBuilder; import org.apache.cocoon.treeprocessor.ProcessingNode; @@ -17,14 +18,35 @@ /** * * @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a> - * @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:24 $ + * @version CVS $Revision: 1.2 $ $Date: 2001/11/12 18:07:43 $ */ public class GeneratorNodeBuilder extends AbstractProcessingNodeBuilder { - public void buildNode(Configuration config, Map buildModel) { + private GeneratorNode node; + + public void buildNode(Configuration config, Map buildModel) throws Exception { + + String type = config.getAttribute("type", null); + if (type == null) { + type = (String)this.treeBuilder.getAttribute(ComponentsNodeBuilder.DEFAULT_PREFIX + "generator"); + } + + if (type == null) { + throw new ConfigurationException( + "There is no default generator defined. Cannot create generator at " + + config.getLocation()); + } + + this.node = new GeneratorNode(type, config.getAttribute("src", null)); + this.node.setLogger(getLogger()); + this.node.setLocation(config.getLocation()); + + this.node.setParameters(getParameters(config)); + } + public ProcessingNode getNode() { - return null; + return this.node; } } 1.2 +145 -13 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/sitemap/PipelineNode.java Index: PipelineNode.java =================================================================== RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/sitemap/PipelineNode.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- PipelineNode.java 2001/11/08 14:39:24 1.1 +++ PipelineNode.java 2001/11/12 18:07:43 1.2 @@ -9,45 +9,177 @@ package org.apache.cocoon.treeprocessor.sitemap; import org.apache.avalon.framework.component.ComponentManager; +import org.apache.avalon.framework.component.Composable; import org.apache.avalon.framework.activity.Disposable; +import org.apache.cocoon.ResourceNotFoundException; + import org.apache.cocoon.environment.Environment; +import org.apache.cocoon.environment.ObjectModelHelper; +import org.apache.cocoon.environment.http.HttpResponse; import org.apache.cocoon.components.pipeline.EventPipeline; import org.apache.cocoon.components.pipeline.StreamPipeline; import org.apache.cocoon.treeprocessor.AbstractParentProcessingNode; +import org.apache.cocoon.treeprocessor.ListOfMapsResolver; +import org.apache.cocoon.treeprocessor.ProcessingNode; -import java.util.List; -import java.util.Map; +import java.util.*; /** * * * @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a> - * @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:24 $ + * @version CVS $Revision: 1.2 $ $Date: 2001/11/12 18:07:43 $ */ public class PipelineNode extends AbstractParentProcessingNode { + // TODO : handle a 'fail-hard' environment attribute + // can be useful to stop off-line generation when there's an error + + private ProcessingNode[] children; + + private ProcessingNode error404; + + private ProcessingNode error500; + + private ComponentManager manager; + + private boolean internalOnly = false; + + /** + * The component manager is used to create error pipelines + */ + public void compose(ComponentManager manager) { + this.manager = manager; + } + + public void setChildren(ProcessingNode[] node) + { + this.children = children; + } + + public void set404Handler(ProcessingNode node) + { + this.error404 = node; + } + + public void set500Handler(ProcessingNode node) + { + this.error500 = node; + } + + public void setInternalOnly(boolean internalOnly) { + this.internalOnly = internalOnly; + } + public boolean invoke(Environment env, StreamPipeline pipeline, EventPipeline eventPipeline, List listOfMaps) throws Exception { - boolean success = false; + // Always fail on external resquests if internal only. + if (this.internalOnly && !SitemapNode.isInternalRequest(env)) { + return false; + } - // Try each of the children until one is successfull. try { - for (int i = 0; i < childNodes.length; i++) { - if (childNodes[i].invoke(env, pipeline, eventPipeline, listOfMaps)) { - success = true; - break; - } - } + if (invokeNodes(children, env, pipeline, eventPipeline, listOfMaps)) { + return true; + } else { + throw new ResourceNotFoundException("No pipeline matched request: " + + env.getURIPrefix()+'/'+env.getURI()); + } + + } catch(ResourceNotFoundException rnfe) { + getLogger().debug("Not found while processing pipeline", rnfe); + + if (error404 != null) { + + invokeErrorHandler(error404, rnfe, env); + return false; + + } else { + throw rnfe; + } } catch(Exception e) { - // FIXME Error pipelines. getLogger().debug("Error while processing pipeline", e); - throw e; + + // Rethrow exception for internal requests + if (error500 != null || !SitemapNode.isInternalRequest(env)) { + + invokeErrorHandler(error500, e, env); + return false; + + } else { + throw e; + } } + } + + private boolean invokeErrorHandler(ProcessingNode node, Exception ex, Environment env) + throws Exception { + EventPipeline eventPipeline = null; + StreamPipeline pipeline = null; + try { + tryResetResponse(env); + eventPipeline = (EventPipeline) this.manager.lookup(EventPipeline.ROLE); + pipeline = (StreamPipeline) this.manager.lookup(StreamPipeline.ROLE); + pipeline.setEventPipeline(eventPipeline); + List listOfMaps = new ArrayList(); + + eventPipeline.setGenerator ("!error-notifier!", ex.getMessage(), + ListOfMapsResolver.EMPTY_PARAMETERS, ex); + + return node.invoke(env, pipeline, eventPipeline, listOfMaps); + + } catch (Exception subEx) { + getLogger().error("error notifier barfs", subEx); + throw ex; + + } finally { + this.manager.release(eventPipeline); + this.manager.release(pipeline); + } + } + + /** + * Reset the response if possible. This allows error handlers to have + * a higher chance to produce clean output if the pipeline that raised + * the error has already output some data. + * + * @param objectModel the object model + * @return true if the response was successfully reset + */ + private void tryResetResponse(Environment env) + { + try { + Object responseObj = ObjectModelHelper.getRequest(env.getObjectModel()); + if (responseObj instanceof HttpResponse) { + HttpResponse response = (HttpResponse)responseObj; + if (! response.isCommitted()) { + response.reset(); + getLogger().debug("Response successfully reset"); + } + } + } catch(Exception e) { + // Log the error, but don't transmit it + getLogger().warn("Problem resetting response", e); + } + + getLogger().debug("Response wasn't reset"); + } + + + public void dispose() { + + disposeNodes(children); - return success; + if (this.error404 != null) { + this.error404.dispose(); + } + + if (this.error500 != null) { + this.error500.dispose(); + } } } 1.2 +30 -16 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/sitemap/SitemapNode.java Index: SitemapNode.java =================================================================== RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/sitemap/SitemapNode.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- SitemapNode.java 2001/11/08 14:39:24 1.1 +++ SitemapNode.java 2001/11/12 18:07:43 1.2 @@ -22,15 +22,15 @@ import org.apache.cocoon.treeprocessor.AbstractParentProcessingNode; import org.apache.cocoon.treeprocessor.EnvironmentSourceResolver; +import org.apache.cocoon.treeprocessor.ProcessingNode; -import java.util.List; -import java.util.Map; +import java.util.*; /** * The root node of a sitemap. * * @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a> - * @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:24 $ + * @version CVS $Revision: 1.2 $ $Date: 2001/11/12 18:07:43 $ */ public class SitemapNode extends AbstractParentProcessingNode implements Composable { @@ -41,12 +41,16 @@ protected ComponentManager manager; + protected PipelinesNode pipelines; + + protected ProcessingNode[] otherNodes; + public static boolean isInternalRequest(Environment env) { return env.getAttribute(INTERNAL_ATTR) != null; } - public static Redirector getRedirector(Environment env) { - return (Redirector)env.getAttribute(REDIRECTOR_ATTR); + public static SitemapRedirector getRedirector(Environment env) { + return (SitemapRedirector)env.getAttribute(REDIRECTOR_ATTR); } /** @@ -58,6 +62,21 @@ } /** + * Set the pipeline nodes that will process the environment. + */ + public void setPipelines(PipelinesNode pipelines) { + this.pipelines = pipelines; + } + + /** + * Set the non-pipeline nodes (views & resources), which are held to properly + * <code>dispose()</code> them. + */ + public void setOtherNodes(ProcessingNode[] otherNodes) { + this.otherNodes = otherNodes; + } + + /** * Process the environment. Also adds an <code>EnvironmentSourceResolver</code> * and a <code>Redirector</code> in the object model. The previous resolver and * redirector, if any, are restored before return. @@ -106,6 +125,7 @@ // component manager used by all other nodes, which may redefine the // SourceHandler to use. EnvironmentSourceResolver resolver = new EnvironmentSourceResolver(this.manager, env); + SitemapRedirector redirector = new SitemapRedirector(env); Map objectModel = env.getObjectModel(); @@ -113,23 +133,14 @@ Object oldRedirector = env.getAttribute(REDIRECTOR_ATTR); objectModel.put(OBJECT_SOURCE_RESOLVER, resolver); - env.setAttribute(REDIRECTOR_ATTR, new SitemapRedirector(env)); + env.setAttribute(REDIRECTOR_ATTR, redirector); - boolean success = true; try { // FIXME : is there any useful information that can be passed as top-level parameters, // such as the URI of the mount point ? - for (int i = 0; i < childNodes.length; i++) { - if (! childNodes[i].invoke(env, pipeline, eventPipeline, listOfMaps)) { - success = false; - break; - } - } - //TODO : check redirector + return this.pipelines.invoke(env, pipeline, eventPipeline, listOfMaps); - return success; - } finally { // Restore old redirector and resolver @@ -145,7 +156,10 @@ * Dispose all children and the component manager. */ public void dispose() { - this.disposeChildren(); + + this.pipelines.dispose(); + disposeNodes(this.otherNodes); + if (this.manager instanceof Disposable) { ((Disposable)this.manager).dispose(); } 1.2 +42 -4 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/sitemap/SitemapNodeBuilder.java Index: SitemapNodeBuilder.java =================================================================== RCS file: /home/cvs/xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/sitemap/SitemapNodeBuilder.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- SitemapNodeBuilder.java 2001/11/08 14:39:24 1.1 +++ SitemapNodeBuilder.java 2001/11/12 18:07:43 1.2 @@ -12,35 +12,73 @@ import org.apache.avalon.framework.component.ComponentManager; import org.apache.avalon.framework.component.ComponentException; import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.cocoon.treeprocessor.ProcessingNode; import org.apache.cocoon.treeprocessor.AbstractParentProcessingNodeBuilder; -import java.util.Map; +import java.util.*; /** * * @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a> - * @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:24 $ + * @version CVS $Revision: 1.2 $ $Date: 2001/11/12 18:07:43 $ */ public class SitemapNodeBuilder extends AbstractParentProcessingNodeBuilder implements Composable { - protected ComponentManager manager; + private ComponentManager manager; - protected SitemapNode node; + private SitemapNode node; + private List childBuilders; + + private String location; + public void compose(ComponentManager manager) throws ComponentException { this.manager = manager; } public void buildNode(Configuration config, Map buildModel) throws Exception { + this.location = config.getLocation(); node = new SitemapNode(); + node.setLocation(this.location); + node.setLogger(getLogger()); node.compose(this.manager); + + this.childBuilders = createChildBuilders(config, buildModel); + } public ProcessingNode getNode() throws Exception { + + ProcessingNode[] childNodes = getNodes(childBuilders); + + // Children contain resources, view and pipelines : separate pipelines + PipelinesNode pipelines = null; + List otherNodes = new ArrayList(); + + for (int i = 0; i < childNodes.length; i++) { + + if (childNodes[i] instanceof PipelinesNode) { + if (pipelines != null) { + throw new ConfigurationException("There can only be one 'map:pipelines' at " + + this.location); + } else { + pipelines = (PipelinesNode) childNodes[i]; + } + } else { + otherNodes.add(childNodes[i]); + } + } + + if (pipelines == null) { + throw new ConfigurationException("There is no 'map:pipelines' in sitemap at " + this.location); + } + + node.setPipelines(pipelines); + node.setOtherNodes(toNodeArray(otherNodes)); + return this.node; } - } 1.1 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/sitemap/PipelineNodeBuilder.java Index: PipelineNodeBuilder.java =================================================================== /***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.cocoon.treeprocessor.sitemap; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.cocoon.treeprocessor.AbstractParentProcessingNodeBuilder; import org.apache.cocoon.treeprocessor.ProcessingNode; import org.apache.cocoon.treeprocessor.ProcessingNodeBuilder; import java.util.*; /** * Builds a <map:pipeline> * @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a> * @version CVS $Revision: 1.1 $ $Date: 2001/11/12 18:07:43 $ */ public class PipelineNodeBuilder extends AbstractParentProcessingNodeBuilder { private PipelineNode node; private List builders; private ProcessingNodeBuilder error404Builder; private ProcessingNodeBuilder error500Builder; public void buildNode(Configuration config, Map buildModel) throws Exception { this.node = new PipelineNode(); this.node.setLocation(config.getLocation()); this.node.setLogger(getLogger()); this.node.setInternalOnly(config.getAttributeAsBoolean("internal-only", false)); // Get all children but the error handlers if (this.ignoredChildren == null) this.ignoredChildren = new ArrayList(); this.ignoredChildren.add("handle-errors"); this.builders = createChildBuilders(config, buildModel); Configuration[] handlersConfig = config.getChildren("handle-errors"); for (int i = 0; i < handlersConfig.length; i++) { Configuration handlerConfig = handlersConfig[i]; int type = handlerConfig.getAttributeAsInteger("type", 500); ProcessingNodeBuilder handlerBuilder = this.treeBuilder.createNodeBuilder(handlerConfig); handlerBuilder.buildNode(handlerConfig, buildModel); if ( (type == 404 && this.error404Builder != null) || (type == 500 && this.error500Builder != null) ) { throw new ConfigurationException("Duplicate handle-errors at " + handlerConfig.getLocation()); } if (type == 404) { this.error404Builder = handlerBuilder; } else if (type == 500) { this.error500Builder = handlerBuilder; } else { throw new ConfigurationException("Unkown handle-errors type (" + type + ") at " + handlerConfig.getLocation()); } } } public ProcessingNode getNode() throws Exception { this.node.setChildren(this.getNodes(builders)); if (this.error404Builder != null) { this.node.set404Handler(this.error404Builder.getNode()); } if (this.error500Builder != null) { this.node.set500Handler(this.error500Builder.getNode()); } return this.node; } } 1.1 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/sitemap/PipelinesNode.java Index: PipelinesNode.java =================================================================== /***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.cocoon.treeprocessor.sitemap; import org.apache.avalon.framework.component.ComponentManager; import org.apache.avalon.framework.component.Composable; import org.apache.avalon.framework.activity.Disposable; import org.apache.cocoon.ResourceNotFoundException; import org.apache.cocoon.environment.Environment; import org.apache.cocoon.components.pipeline.EventPipeline; import org.apache.cocoon.components.pipeline.StreamPipeline; import org.apache.cocoon.treeprocessor.AbstractParentProcessingNode; import org.apache.cocoon.treeprocessor.ProcessingNode; import java.util.*; /** * Handles <map:pipelines> * * @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a> * @version CVS $Revision: 1.1 $ $Date: 2001/11/12 18:07:43 $ */ public final class PipelinesNode extends AbstractParentProcessingNode { private ProcessingNode[] children; public void setChildren(ProcessingNode[] node) { this.children = children; } public final boolean invoke(Environment env, StreamPipeline pipeline, EventPipeline eventPipeline, List listOfMaps) throws Exception { return invokeNodes(children, env, pipeline, eventPipeline, listOfMaps); } public final void dispose() { disposeNodes(children); } } 1.1 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/sitemap/PipelinesNodeBuilder.java Index: PipelinesNodeBuilder.java =================================================================== /***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.cocoon.treeprocessor.sitemap; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.cocoon.treeprocessor.AbstractParentProcessingNodeBuilder; import org.apache.cocoon.treeprocessor.ProcessingNode; import org.apache.cocoon.treeprocessor.ProcessingNodeBuilder; import java.util.*; /** * Buildes a <map:pipelines> * * @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a> * @version CVS $Revision: 1.1 $ $Date: 2001/11/12 18:07:43 $ */ public class PipelinesNodeBuilder extends AbstractParentProcessingNodeBuilder { private PipelinesNode node; private List builders; public void buildNode(Configuration config, Map buildModel) throws Exception { this.node = new PipelinesNode(); this.node.setLocation(config.getLocation()); this.node.setLogger(getLogger()); // Get all children but the error handlers this.builders = createChildBuilders(config, buildModel); if (this.builders.size() == 0) { throw new ConfigurationException("There must be at least one pipeline at " + config.getLocation()); } } public ProcessingNode getNode() throws Exception { this.node.setChildren(this.getNodes(builders)); return this.node; } }
---------------------------------------------------------------------- In case of troubles, e-mail: [EMAIL PROTECTED] To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]