You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by sy...@apache.org on 2002/03/17 22:55:22 UTC

cvs commit: xml-cocoon2/src/java/org/apache/cocoon/components/treeprocessor/sitemap CallNode.java MatchNodeBuilder.java SitemapLanguage.java

sylvain     02/03/17 13:55:22

  Modified:    src/java/org/apache/cocoon/components/treeprocessor
                        AbstractProcessingNodeBuilder.java
                        ProcessingNodeBuilder.java TreeBuilder.java
                        TreeProcessor.java treeprocessor-builtins.xml
               src/java/org/apache/cocoon/components/treeprocessor/sitemap
                        CallNode.java MatchNodeBuilder.java
                        SitemapLanguage.java
  Added:       src/java/org/apache/cocoon/components/treeprocessor
                        DefaultTreeBuilder.java
  Log:
  - TreeBuilder is now recyclable so that loading is faster (yes it can ;)
  - docs and cleanup
  
  Revision  Changes    Path
  1.2       +1 -5      xml-cocoon2/src/java/org/apache/cocoon/components/treeprocessor/AbstractProcessingNodeBuilder.java
  
  Index: AbstractProcessingNodeBuilder.java
  ===================================================================
  RCS file: /home/cvs/xml-cocoon2/src/java/org/apache/cocoon/components/treeprocessor/AbstractProcessingNodeBuilder.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- AbstractProcessingNodeBuilder.java	5 Mar 2002 08:26:22 -0000	1.1
  +++ AbstractProcessingNodeBuilder.java	17 Mar 2002 21:55:22 -0000	1.2
  @@ -56,10 +56,6 @@
   import org.apache.avalon.framework.configuration.Configuration;
   import org.apache.avalon.framework.configuration.ConfigurationException;
   
  -import org.apache.avalon.framework.component.Composable;
  -import org.apache.avalon.framework.component.ComponentManager;
  -import org.apache.avalon.framework.component.ComponentException;
  -
   import org.apache.cocoon.sitemap.PatternException;
   
   import java.util.Map;
  @@ -68,7 +64,7 @@
   /**
    *
    * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
  - * @version CVS $Id: AbstractProcessingNodeBuilder.java,v 1.1 2002/03/05 08:26:22 sylvain Exp $
  + * @version CVS $Id: AbstractProcessingNodeBuilder.java,v 1.2 2002/03/17 21:55:22 sylvain Exp $
    */
   
   
  
  
  
  1.2       +13 -1     xml-cocoon2/src/java/org/apache/cocoon/components/treeprocessor/ProcessingNodeBuilder.java
  
  Index: ProcessingNodeBuilder.java
  ===================================================================
  RCS file: /home/cvs/xml-cocoon2/src/java/org/apache/cocoon/components/treeprocessor/ProcessingNodeBuilder.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ProcessingNodeBuilder.java	5 Mar 2002 08:26:22 -0000	1.1
  +++ ProcessingNodeBuilder.java	17 Mar 2002 21:55:22 -0000	1.2
  @@ -58,9 +58,21 @@
   
   /**
    * A <code>ProcessingNode</code> builder.
  + * <p>
  + * Lifecycle information : a <code>TreeBuilder</code> can be recycled
  + * and used to build several <code>Processor</code>s, each one defining
  + * a different <code>ComponentManager</code>. As a consequence, a
  + * <code>ProcessingNodeBuilder</code> that needs access to the
  + * <code>ComponentManager</code> of the <code>Processor</code> being
  + * built must be not only <code>Composable</code> but also
  + * <strong><code>Recomposable</code></strong>.
  + * <p>
  + * Note however that being <code>Recomposable</code> doesn't forbid to be
  + * <code>ThreadSafe</code> since a <code>ProcessingNodeBuilder</code> is
  + * used by only one <code>TreeBuilder</code> at a time.
    *
    * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
  - * @version CVS $Id: ProcessingNodeBuilder.java,v 1.1 2002/03/05 08:26:22 sylvain Exp $
  + * @version CVS $Id: ProcessingNodeBuilder.java,v 1.2 2002/03/17 21:55:22 sylvain Exp $
    */
   
   public interface ProcessingNodeBuilder extends Component {
  
  
  
  1.2       +23 -423   xml-cocoon2/src/java/org/apache/cocoon/components/treeprocessor/TreeBuilder.java
  
  Index: TreeBuilder.java
  ===================================================================
  RCS file: /home/cvs/xml-cocoon2/src/java/org/apache/cocoon/components/treeprocessor/TreeBuilder.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- TreeBuilder.java	5 Mar 2002 08:26:22 -0000	1.1
  +++ TreeBuilder.java	17 Mar 2002 21:55:22 -0000	1.2
  @@ -50,376 +50,72 @@
   */
   package org.apache.cocoon.components.treeprocessor;
   
  -import org.apache.avalon.excalibur.component.DefaultRoleManager;
  -import org.apache.avalon.excalibur.component.ExcaliburComponentSelector;
  -import org.apache.avalon.excalibur.component.RoleManageable;
  -import org.apache.avalon.excalibur.component.RoleManager;
  -import org.apache.avalon.excalibur.logger.LogKitManageable;
  -import org.apache.avalon.excalibur.logger.LogKitManager;
  -
  -import org.apache.avalon.framework.activity.Disposable;
  -import org.apache.avalon.framework.activity.Initializable;
  -
  -import org.apache.avalon.framework.component.Composable;
   import org.apache.avalon.framework.component.Component;
  -import org.apache.avalon.framework.component.ComponentManager;
  -import org.apache.avalon.framework.component.ComponentException;
  -import org.apache.avalon.framework.component.ComponentSelector;
   
  -import org.apache.avalon.framework.configuration.Configurable;
   import org.apache.avalon.framework.configuration.Configuration;
   import org.apache.avalon.framework.configuration.ConfigurationException;
  -import org.apache.avalon.framework.configuration.DefaultConfiguration;
  -
  -import org.apache.avalon.framework.context.Context;
  -import org.apache.avalon.framework.context.Contextualizable;
  -import org.apache.avalon.framework.context.ContextException;
   
  -import org.apache.avalon.framework.logger.AbstractLoggable;
  -
  -import org.apache.cocoon.components.ExtendedComponentSelector;
  -import org.apache.cocoon.components.LifecycleHelper;
  -
  -import org.apache.cocoon.sitemap.PatternException;
  -import org.apache.cocoon.util.ClassUtils;
  +import org.apache.cocoon.environment.Source;
  +import org.apache.cocoon.environment.SourceResolver;
   
   import java.util.*;
   
   /**
    *
    * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
  - * @version CVS $Id: TreeBuilder.java,v 1.1 2002/03/05 08:26:22 sylvain Exp $
  + * @version CVS $Id: TreeBuilder.java,v 1.2 2002/03/17 21:55:22 sylvain Exp $
    */
   
  -public class TreeBuilder extends AbstractLoggable implements
  -  Composable, Configurable, Contextualizable, LogKitManageable, RoleManageable, Disposable {
  -
  -    /**
  -     * The tree processor that we're building.
  -     */
  -    protected TreeProcessor processor;
  -
  -    //----- lifecycle-related objects ------
  -    protected Context context;
  -
  -    protected LogKitManager logKit;
  -
  -    /**
  -     * The parent component manager, set using <code>compose()</code> (implementation of
  -     * <code>Composable</code>).
  -     */
  -    protected ComponentManager parentManager;
  -
  -    /**
  -     * The parent role manager, set using <code>setRoleManager</code> (implementation of
  -     * <code>createRoleManager</code>).
  -     */
  -    protected RoleManager parentRoleManager;
  -
  -    protected Configuration configuration;
  -    // -------------------------------------
  -
  -    /**
  -     * Component manager created by {@link #createComponentManager()}.
  -     */
  -    protected ComponentManager manager;
  -
  -    /**
  -     * Role manager result created by {@link #createRoleManager()}.
  -     */
  -    protected RoleManager roleManager;
  -
  -    /** Selector for ProcessingNodeBuilders */
  -    protected ComponentSelector builderSelector;
  -
  -    protected LifecycleHelper lifecycle;
  -
  -    protected String namespace;
  -
  -    protected String parameterElement;
  -
  -    protected String languageName;
  -
  -    /** Nodes gone through setupNode() that implement Initializable */
  -    private List initializableNodes = new ArrayList();
  -
  -    /** Nodes gone through setupNode() that implement Disposable */
  -    private List disposableNodes = new ArrayList();
  -
  -    /** NodeBuilders created by createNodeBuilder() that implement LinkedProcessingNodeBuilder */
  -    private List linkedBuilders = new ArrayList();
  -
  -    /** Are we in a state that allows to get registered nodes ? */
  -    private boolean canGetNode = false;
  -
  -    /** Nodes registered using registerNode() */
  -    private Map registeredNodes = new HashMap();
  -
  -    /** Attributes set using setAttribute() */
  -    private Map attributes = new HashMap();
  -
  -
  -    public void contextualize(Context context) throws ContextException {
  -        this.context = context;
  -    }
  -
  -    public void setLogKitManager(LogKitManager logKit) {
  -        this.logKit = logKit;
  -    }
  -
  -    public void compose(ComponentManager manager) throws ComponentException {
  -        this.parentManager = manager;
  -    }
  -
  -    public void setRoleManager(RoleManager rm) {
  -        this.parentRoleManager = rm;
  -    }
  -
  -    public void configure(Configuration config) throws ConfigurationException {
  -        this.configuration = config;
  -
  -        this.languageName = config.getAttribute("name");
  -        getLogger().debug("Configuring Builder for language : " + this.languageName);
  +public interface TreeBuilder extends Component {
   
  -        this.namespace = config.getChild("namespace").getAttribute("uri", "");
  +    void setProcessor(TreeProcessor processor);
   
  -        this.parameterElement = config.getChild("parameter").getAttribute("element", "parameter");
  -    }
  -
  -    /**
  -     * Create a role manager that will be used by all <code>RoleManageable</code>
  -     * components. The default here is to create a role manager with the contents of
  -     * the &lt;roles&gt; element of the configuration.
  -     * <p>
  -     * Subclasses can redefine this method to create roles from other sources than
  -     * the one used here.
  -     *
  -     * @return the role manager
  -     */
  -    protected RoleManager createRoleManager() throws Exception
  -    {
  -        RoleManager roles = new DefaultRoleManager();
  -
  -        LifecycleHelper.setupComponent(roles,
  -            getLogger(),
  -            this.context,
  -            this.manager,
  -            this.parentRoleManager,
  -            this.logKit,
  -            this.configuration.getChild("roles")
  -        );
  -
  -        return roles;
  -    }
  -
  -    /**
  -     * Create a component manager that will be used for all <code>Composable</code>
  -     * <code>ProcessingNodeBuilder</code>s and <code>ProcessingNode</code>s.
  -     * <p>
  -     * The default here is to simply return the manager set by <code>compose()</code>,
  -     * i.e. the component manager set by the calling <code>TreeProcessor</code>.
  -     * <p>
  -     * Subclasses can redefine this method to create a component manager local to a tree,
  -     * such as for sitemap's &lt;map:components&gt;.
  -     *
  -     * @return a component manager
  -     */
  -    protected ComponentManager createComponentManager(Configuration tree) throws Exception
  -    {
  -        return this.parentManager;
  -    }
  -
  -    /**
  -     * Create a <code>ComponentSelector</code> for <code>ProcessingNodeBuilder</code>s.
  -     * It creates a selector with the contents of the "node" element of the configuration.
  -     *
  -     * @return a selector for node builders
  -     */
  -    protected ComponentSelector createBuilderSelector() throws Exception {
  -
  -        // Create the NodeBuilder selector.
  -        ExcaliburComponentSelector selector = new ExtendedComponentSelector() {
  -            protected String getComponentInstanceName() {
  -                return "node";
  -            }
  -
  -            protected String getClassAttributeName() {
  -                return "builder";
  -            }
  -        };
  -
  -        // Automagically initialize the selector
  -        LifecycleHelper.setupComponent(selector,
  -            getLogger(),
  -            this.context,
  -            this.manager,
  -            this.roleManager,
  -            this.logKit,
  -            this.configuration.getChild("nodes")
  -        );
  -
  -        return selector;
  -    }
  -
  -    public void setProcessor(TreeProcessor processor) {
  -        this.processor = processor;
  -    }
  -
  -    public TreeProcessor getProcessor() {
  -        return this.processor;
  -    }
  +    TreeProcessor getProcessor();
   
       /**
        * Returns the language that is being built (e.g. "sitemap").
        */
  -    public String getLanguage() {
  -        return this.languageName;
  -    }
  +    String getLanguage();
   
       /**
        * Returns the name of the parameter element.
        */
  -    public String getParameterName() {
  -        return this.parameterElement;
  -    }
  +    String getParameterName();
   
       /**
        * Register a <code>ProcessingNode</code> under a given name.
        * For example, <code>ResourceNodeBuilder</code> stores here the <code>ProcessingNode</code>s
        * it produces for use by sitemap pipelines. This allows to turn the tree into a graph.
        */
  -    public void registerNode(String name, ProcessingNode node) {
  -        this.registeredNodes.put(name, node);
  -    }
  -
  -    public ProcessingNode getRegisteredNode(String name) {
  -        if (this.canGetNode) {
  -            return (ProcessingNode)this.registeredNodes.get(name);
  -        } else {
  -            throw new IllegalArgumentException("Categories are only available during buildNode()");
  -        }
  -    }
  -
  -    public void setAttribute(String name, Object value) {
  -        this.attributes.put(name, value);
  -    }
  -
  -    public Object getAttribute(String name) {
  -        return this.attributes.get(name);
  -    }
  -
  -    public ProcessingNodeBuilder createNodeBuilder(Configuration config) throws Exception {
  -        //FIXME : check namespace
  -        String nodeName = config.getName();
  -
  -        getLogger().debug("Creating node builder for " + nodeName);
  -
  -        ProcessingNodeBuilder builder;
  -        try {
  -            builder = (ProcessingNodeBuilder)this.builderSelector.select(nodeName);
  -
  -        } catch(ComponentException ce) {
  -            // Is it because this element is unknown ?
  -            if (this.builderSelector.hasComponent(nodeName)) {
  -                // No : rethrow
  -                throw ce;
  -            } else {
  -                // Throw a more meaningfull exception
  -                String msg = "Unkown element '" + nodeName + "' at " + config.getLocation();
  -                getLogger().error(msg);
  -                throw new ConfigurationException(msg);
  -            }
  -        }
  -
  -        builder.setBuilder(this);
  -
  -        if (builder instanceof LinkedProcessingNodeBuilder) {
  -            this.linkedBuilders.add(builder);
  -        }
  -
  -        return builder;
  -    }
  +    void registerNode(String name, ProcessingNode node);
   
       /**
  -     * Create the tree once component manager and node builders have been set up.
  -     * Can be overriden by subclasses to perform pre/post tree creation operations.
  +     * @throws IllegalStateException
        */
  -    protected ProcessingNode createTree(Configuration tree) throws Exception {
  -        // Create a node builder from the top-level element
  -        ProcessingNodeBuilder rootBuilder = createNodeBuilder(tree);
  -
  -        // Build the whole tree (with an empty buildModel)
  -        return rootBuilder.buildNode(tree);
  -    }
  +    ProcessingNode getRegisteredNode(String name);
   
  -    /**
  -     * Resolve links : call <code>linkNode()</code> on all
  -     * <code>LinkedProcessingNodeBuilder</code>s.
  -     * Can be overriden by subclasses to perform pre/post resolution operations.
  -     */
  -    protected void linkNodes() throws Exception {
  -        // Resolve links
  -        Iterator iter = this.linkedBuilders.iterator();
  -        while(iter.hasNext()) {
  -            ((LinkedProcessingNodeBuilder)iter.next()).linkNode();
  -        }
  -    }
  +    ProcessingNodeBuilder createNodeBuilder(Configuration config) throws Exception;
   
       /**
        * Get the namespace URI that builders should use to find their nodes.
        */
  -    public String getNamespace() {
  -        return this.namespace;
  -    }
  +    String getNamespace();
   
       /**
        * Build a processing tree from a <code>Configuration</code>.
        */
  -    public ProcessingNode build(Configuration tree) throws Exception {
  -
  -        this.roleManager = createRoleManager();
  -
  -        this.manager = createComponentManager(tree);
  -
  -        // Create a helper object to setup components
  -        this.lifecycle = new LifecycleHelper(getLogger(),
  -            this.context,
  -            this.manager,
  -            this.roleManager,
  -            this.logKit,
  -            null // configuration
  -        );
  -
  -        this.builderSelector = createBuilderSelector();
  -
  -        // Calls to getRegisteredNode() are forbidden
  -        this.canGetNode = false;
  -
  -        ProcessingNode result = createTree(tree);
  -
  -        // Calls to getRegisteredNode() are now allowed
  -        this.canGetNode = true;
  -
  -        linkNodes();
  -
  -        // Initialize all Initializable nodes
  -        Iterator iter = this.initializableNodes.iterator();
  -        while(iter.hasNext()) {
  -            ((Initializable)iter.next()).initialize();
  -        }
  -
  -        // And that's all !
  -        return result;
  -    }
  +    ProcessingNode build(Configuration tree) throws Exception;
  +    
  +    ProcessingNode build(Source source) throws Exception;
  +    
  +    String getFileName();
   
       /**
        * Return the list of <code>ProcessingNodes</code> part of this tree that are
        * <code>Disposable</code>. Care should be taken to properly dispose them before
        * trashing the processing tree.
        */
  -    public List getDisposableNodes() {
  -        return this.disposableNodes;
  -    }
  +    List getDisposableNodes();
   
       /**
        * Setup a <code>ProcessingNode</code> by setting its location, calling all
  @@ -429,111 +125,15 @@
        * As a convenience, the node is returned by this method to allow constructs
        * like <code>return treeBuilder.setupNode(new MyNode(), config)</code>.
        */
  -    public ProcessingNode setupNode(ProcessingNode node, Configuration config)
  -      throws Exception {
  -        if (node instanceof AbstractProcessingNode) {
  -            ((AbstractProcessingNode)node).setLocation(config.getLocation());
  -        }
  -
  -        this.lifecycle.setupComponent(node, false);
  -
  -        if (node instanceof ParameterizableProcessingNode) {
  -            Map params = getParameters(config);
  -            ((ParameterizableProcessingNode)node).setParameters(params);
  -        }
  -
  -        if (node instanceof Initializable) {
  -            this.initializableNodes.add(node);
  -        }
  -
  -        if (node instanceof Disposable) {
  -            this.disposableNodes.add(node);
  -        }
  +    ProcessingNode setupNode(ProcessingNode node, Configuration config) throws Exception;
   
  -        return node;
  -    }
  -
  -    /**
  -     * Get &lt;xxx:parameter&gt; 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.
  -     */
  -    protected Map getParameters(Configuration config) throws ConfigurationException {
  -
  -        Configuration[] children = config.getChildren(this.parameterElement);
  -
  -        if (children.length == 0) {
  -            return null;
  -        }
  -
  -        Map params = new HashMap();
  -        for (int i = 0; i < children.length; i++) {
  -            Configuration child = children[i];
  -            if (true) { // FIXME : check namespace
  -                String value = child.getAttribute("value");
  -                try {
  -                    params.put(child.getAttribute("name"), MapStackResolver.getResolver(value));
  -                } catch(PatternException pe) {
  -                    String msg = "Invalid pattern '" + value + "' at " + child.getLocation();
  -                    getLogger().error(msg, pe);
  -                    throw new ConfigurationException(msg, pe);
  -                }
  -            }
  -        }
  -
  -        return params;
  -    }
   
       /**
        * Get the type for a statement : it returns the 'type' attribute if present,
  -     * and otherwhise the default hint of the <code>ExtendedSelector</code> designated by
  -     * role <code>role</code>.
  +     * and otherwhise the default hint for the <code>ComponentSelector</code> identified by
  +     * the role <code>role</code>.
        *
        * @throws ConfigurationException if the default type could not be found.
        */
  -    public String getTypeForStatement(Configuration statement, String role) throws ConfigurationException {
  -
  -        String type = statement.getAttribute("type", null);
  -
  -        ComponentSelector selector;
  -
  -        try {
  -            selector = (ComponentSelector)this.manager.lookup(role);
  -        } catch(ComponentException ce) {
  -            String msg = "Cannot get component selector for '" + statement.getName() + "' at " +
  -                statement.getLocation();
  -            getLogger().error(msg);
  -            throw new ConfigurationException(msg);
  -        }
  -
  -        if (type == null && selector instanceof ExtendedComponentSelector) {
  -            type = ((ExtendedComponentSelector)selector).getDefaultHint();
  -        }
  -
  -        if (type == null) {
  -            String msg = "No default type exists for '" + statement.getName() + "' at " +
  -                statement.getLocation();
  -            getLogger().error(msg);
  -            throw new ConfigurationException(msg);
  -        }
  -
  -        if (!selector.hasComponent(type)) {
  -            String msg = "Type '" + type + "' is not defined for '" + statement.getName() + "' at " +
  -                statement.getLocation();
  -            getLogger().error(msg);
  -            throw new ConfigurationException(msg);
  -        }
  -
  -        this.manager.release(selector);
  -
  -        return type;
  -    }
  -
  -    public void dispose() {
  -        LifecycleHelper.dispose(this.builderSelector);
  -
  -        // Don't dispose manager or roles : they are used by the built tree
  -        // and thus must live longer than the builder.
  -    }
  +    String getTypeForStatement(Configuration statement, String role) throws ConfigurationException;
   }
  
  
  
  1.3       +46 -95    xml-cocoon2/src/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java
  
  Index: TreeProcessor.java
  ===================================================================
  RCS file: /home/cvs/xml-cocoon2/src/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- TreeProcessor.java	13 Mar 2002 17:41:06 -0000	1.2
  +++ TreeProcessor.java	17 Mar 2002 21:55:22 -0000	1.3
  @@ -63,6 +63,7 @@
   import org.apache.avalon.framework.component.ComponentManager;
   import org.apache.avalon.framework.component.ComponentSelector;
   import org.apache.avalon.framework.component.Composable;
  +import org.apache.avalon.framework.component.Recomposable;
   
   import org.apache.avalon.framework.configuration.Configurable;
   import org.apache.avalon.framework.configuration.Configuration;
  @@ -79,6 +80,7 @@
   
   import org.apache.cocoon.Processor;
   import org.apache.cocoon.components.CocoonComponentManager;
  +import org.apache.cocoon.components.ExtendedComponentSelector;
   import org.apache.cocoon.components.LifecycleHelper;
   import org.apache.cocoon.components.pipeline.EventPipeline;
   import org.apache.cocoon.components.pipeline.StreamPipeline;
  @@ -97,7 +99,7 @@
    * Interpreted tree-traversal implementation of a pipeline assembly language.
    *
    * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
  - * @version CVS $Id: TreeProcessor.java,v 1.2 2002/03/13 17:41:06 ovidiu Exp $
  + * @version CVS $Id: TreeProcessor.java,v 1.3 2002/03/17 21:55:22 sylvain Exp $
    */
   
   public class TreeProcessor extends AbstractLoggable implements ThreadSafe, Processor,
  @@ -124,8 +126,8 @@
       /** The language used by this processor */
       protected String language;
   
  -    /** The configuration for each language */
  -    protected Map languageConfigs;
  +    /** Selector of TreeBuilders, the hint is the language name */
  +    protected ExtendedComponentSelector builderSelector;
   
       /** The root node of the processing tree */
       protected ProcessingNode rootNode;
  @@ -136,9 +138,6 @@
       /** Last modification time */
       protected long lastModified = 0;
   
  -    /** The relative file name of the tree definition */
  -    protected String sourceName;
  -
       /** The source of the tree definition */
       protected Source source;
   
  @@ -150,8 +149,6 @@
   
       protected SourceHandler sourceHandler;
   
  -    protected Class treeBuilderClass;
  -
       /**
        * Create a TreeProcessor.
        */
  @@ -170,7 +167,7 @@
           // Copy all that can be copied from the parent
           this.context = parent.context;
           this.logKit = parent.logKit;
  -        this.languageConfigs = parent.languageConfigs;
  +        this.builderSelector = parent.builderSelector;
   
           // We have our own CM
           this.manager = manager;
  @@ -194,7 +191,7 @@
           TreeProcessor child = new TreeProcessor(this, manager, language);
           child.setLogger(getLogger());
           child.initialize();
  -        // FIXME : make the delay configurable
  +        // FIXME : make delay configurable
           child.source = new DelayedRefreshSourceWrapper(source, 1000L);
           return child;
       }
  @@ -258,66 +255,33 @@
               getLogger().error(msg, e);
               throw new ConfigurationException(msg, e);
           }
  -
  -        this.languageConfigs = new HashMap();
  -
  -        // Add builtin languages
  -        addLanguages("builtin", builtin.getChildren("language"));
  -
  -        // Add additional languages from the configuration
  -        addLanguages("additional", config.getChildren("language"));
  -    }
  -
  -    private void addLanguages(String type, Configuration[] languages)
  -      throws ConfigurationException {
  -
  -        for (int i = 0; i < languages.length; i++) {
  -
  -            String name = languages[i].getAttribute("name");
  -
  -            if (this.languageConfigs.containsKey(name)) {
  -                getLogger().info("Redefining language '" + name + "' in " + type + " configuration.");
  -            } else {
  -                getLogger().debug("Adding " + type + " language '" + name + "'");
  -            }
  -
  -            this.languageConfigs.put(name, languages[i]);
  +        
  +        // Create a selector for tree builders of all languages
  +        this.builderSelector = new ExtendedComponentSelector(Thread.currentThread().getContextClassLoader());
  +        try {
  +            LifecycleHelper.setupComponent(this.builderSelector,
  +                getLogger(),
  +                this.context,
  +                this.manager,
  +                this.roleManager,
  +                this.logKit,
  +                builtin
  +            );
  +        } catch(ConfigurationException ce) {
  +            throw ce;
  +        } catch(Exception e) {
  +            throw new ConfigurationException("Could not setup builder selector", e);
           }
       }
   
       public void initialize() throws Exception {
   
  -        this.currentLanguage = (Configuration)this.languageConfigs.get(this.language);
  -        if (this.currentLanguage == null) {
  -            throw new ConfigurationException("No configuration defined for language '" + this.language + "'");
  -        }
  -
  -        Configuration fileConfig = this.currentLanguage.getChild("file", false);
  -        if (fileConfig == null) {
  -            throw new ConfigurationException("Missing 'file' configuration for language '" + this.language + "', at " +
  -                this.currentLanguage.getLocation());
  -        }
  -
  -        this.sourceName = fileConfig.getAttribute("name");
  -
           // Get a new Source handler
           this.sourceHandler = (SourceHandler)this.manager.lookup(SourceHandler.ROLE);
   
           // and add the special "cocoon:" source factory
           this.sourceHandler.addFactory("cocoon", new CocoonSourceFactory(this, this.manager));
   
  -        // Get the TreeBuider class
  -        String builderClassName =
  -            this.currentLanguage.getAttribute("class", TreeBuilder.class.getName());
  -
  -        try {
  -            this.treeBuilderClass = Thread.currentThread().getContextClassLoader().loadClass(builderClassName);
  -        } catch(Exception e) {
  -            String msg = "Cannot create class '" + builderClassName + "' at " +
  -                this.currentLanguage.getLocation();
  -            getLogger().error(msg, e);
  -            throw new ConfigurationException(msg, e);
  -        }
       }
   
       public boolean process(Environment environment) throws Exception {
  @@ -374,46 +338,28 @@
   
           long startTime = System.currentTimeMillis();
   
  -        if (this.source == null) {
  -            // Root Processor : create source
  -            // FIXME : make the delay configurable
  -            this.source = new DelayedRefreshSourceWrapper(env.resolve(this.sourceName), 1000L);
  -
  -        } else {
  -            // Dispose existing tree, we will build a new one.
  -            disposeTree();
  -        }
  -
  -        // Read the tree definition file as a Configuration
  -        getLogger().debug("Building " + this.language + " from " + source.getSystemId());
  -
  -        // Build a namespace-aware configuration object
  -        SAXConfigurationHandler handler = new NamespacedSAXConfigurationHandler();
  -        source.toSAX(handler);
  -        Configuration treeConfig = handler.getConfiguration();
  -
  -        TreeBuilder treeBuilder = (TreeBuilder)this.treeBuilderClass.newInstance();
  -        LifecycleHelper.setupComponent(treeBuilder,
  -            getLogger(),
  -            this.context,
  -            this.manager,
  -            this.roleManager,
  -            this.logKit,
  -            this.currentLanguage);
  -
  -        treeBuilder.setProcessor(this);
  -
  -        // Build the tree
  +        // Dispose the previous tree, if any
  +        disposeTree();
  +        
  +        // Get a builder
  +        TreeBuilder builder = (TreeBuilder)this.builderSelector.select(this.language);
           ProcessingNode root;
           try {
  -            root = treeBuilder.build(treeConfig);
  -        } catch(Exception e) {
  -            getLogger().debug("Failed to build processing tree from " + source.getSystemId(), e);
  -            throw e;
  +            if (builder instanceof Recomposable) {
  +                ((Recomposable)builder).recompose(this.manager);
  +            }
  +            builder.setProcessor(this);
  +            
  +            if (this.source == null) {
  +                // FIXME : make the delay configurable
  +                this.source = new DelayedRefreshSourceWrapper(env.resolve(builder.getFileName()), 1000L);
  +            }
  +            root = builder.build(this.source);
  +            
  +        } finally {        
  +            this.builderSelector.release(builder);
           }
   
  -        LifecycleHelper.decommission(treeBuilder);
  -
           this.lastModified = System.currentTimeMillis();
   
           if (getLogger().isDebugEnabled()) {
  @@ -429,6 +375,10 @@
       public void dispose() {
           disposeTree();
           this.manager.release(this.sourceHandler);
  +        if (this.parent == null) {
  +            // root processor : dispose the builder selector
  +            this.builderSelector.dispose();
  +        }
       }
   
       /**
  @@ -440,6 +390,7 @@
               while (iter.hasNext()) {
                   ((Disposable)iter.next()).dispose();
               }
  +            this.disposableNodes = null;
           }
       }
   }
  
  
  
  1.2       +26 -6     xml-cocoon2/src/java/org/apache/cocoon/components/treeprocessor/treeprocessor-builtins.xml
  
  Index: treeprocessor-builtins.xml
  ===================================================================
  RCS file: /home/cvs/xml-cocoon2/src/java/org/apache/cocoon/components/treeprocessor/treeprocessor-builtins.xml,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- treeprocessor-builtins.xml	5 Mar 2002 08:26:22 -0000	1.1
  +++ treeprocessor-builtins.xml	17 Mar 2002 21:55:22 -0000	1.2
  @@ -1,6 +1,14 @@
   <tree-processor>
  -  <!-- The sitemap language -->
  -  <language name="sitemap" class="org.apache.cocoon.components.treeprocessor.sitemap.SitemapLanguage">
  +  <!-- The sitemap language.
  +       The "class" attribute names the implementation of TreeBuilder to be used for this language
  +       
  +       A language definition is a component of a ComponentSelector. Consequently, it can
  +       have all attributes supported by components, including pool-settings.
  +       Since it is unlikely that several sitemaps will be built simultaneously, the
  +       pool-max is set to 1, meaning that only one builder is recycled.
  +    -->
  +  <language name="sitemap" class="org.apache.cocoon.components.treeprocessor.sitemap.SitemapLanguage"
  +		pool-min="1" pool-max="1">
     
       <!-- Namespace for this language -->
       <namespace uri="http://apache.org/cocoon/sitemap/1.0"/>
  @@ -11,7 +19,7 @@
       <!-- Description of the element for nodes parameters -->
       <parameter element="parameter"/>
       
  -    <!-- roles for the sitemap language -->
  +    <!-- New roles available to components created within a sitemap (i.e. in <map:components>) -->
       <roles>
         <role name="org.apache.cocoon.acting.ActionSelector"
               shorthand="actions"
  @@ -25,6 +33,14 @@
               shorthand="matchers"
               default-class="org.apache.cocoon.components.treeprocessor.sitemap.ComponentsSelector">
   
  +        <!-- since <map:components> is a regular xconf, we can define shorthand for
  +             well-known implementations.
  +             
  +             The hint below allows the following to be written in <map:matchers> :
  +               <regexp-uri-matcher name="regexp"/>
  +             in place of :
  +               <map:matcher name="regexp" src="org.apache.cocoon.matching.RegexpURIMatcher"/>
  +          -->
           <hint shorthand="regexp-uri-matcher"
                 class="org.apache.cocoon.matching.RegexpURIMatcher"/>
   
  @@ -72,15 +88,19 @@
       
       <!-- node definitions for the sitemap language -->
       <nodes>
  -      <!-- All node names are given as local names in the above namespace (no prefix) -->
  +      <!-- A node has the following attributes :
  +           - name : the node name, given as a local name in the language namespace (no prefix)
  +           - builder : the class name of the ProcessingNodeBuilder for this node
  +           
  +           The contents of a node definition is the configuration of Configurable
  +           ProcessingNodeBuilders.
  +        -->
         
         <!-- Sitemap root node -->
         <node name="sitemap" builder="org.apache.cocoon.components.treeprocessor.sitemap.SitemapNodeBuilder">
           <allowed-children>components, views, action-sets, resources, pipelines</allowed-children>
         </node>
       
  -      <!-- Components definition : parse view info associated to components
  -           (actual components creation is done by SitemapLanguage) -->
         <node name="components" builder="org.apache.cocoon.components.treeprocessor.sitemap.ComponentsNodeBuilder"/>
         
         <node name="pipelines" builder="org.apache.cocoon.components.treeprocessor.sitemap.PipelinesNodeBuilder">
  
  
  
  1.1                  xml-cocoon2/src/java/org/apache/cocoon/components/treeprocessor/DefaultTreeBuilder.java
  
  Index: DefaultTreeBuilder.java
  ===================================================================
  /*
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
  
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
  
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
  
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
  
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
  
   4. The names "Apache Cocoon" and  "Apache Software Foundation" must  not  be
      used to  endorse or promote  products derived from  this software without
      prior written permission. For written permission, please contact
      apache@apache.org.
  
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
  
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation and was  originally created by
   Stefano Mazzocchi  <st...@apache.org>. For more  information on the Apache
   Software Foundation, please see <http://www.apache.org/>.
  
  */
  package org.apache.cocoon.components.treeprocessor;
  
  import org.apache.avalon.excalibur.component.DefaultRoleManager;
  import org.apache.avalon.excalibur.component.ExcaliburComponentSelector;
  import org.apache.avalon.excalibur.component.RoleManageable;
  import org.apache.avalon.excalibur.component.RoleManager;
  import org.apache.avalon.excalibur.logger.LogKitManageable;
  import org.apache.avalon.excalibur.logger.LogKitManager;
  import org.apache.avalon.excalibur.pool.Recyclable;
  
  import org.apache.avalon.framework.activity.Disposable;
  import org.apache.avalon.framework.activity.Initializable;
  
  import org.apache.avalon.framework.component.Component;
  import org.apache.avalon.framework.component.ComponentManager;
  import org.apache.avalon.framework.component.ComponentException;
  import org.apache.avalon.framework.component.ComponentSelector;
  import org.apache.avalon.framework.component.Recomposable;
  
  import org.apache.avalon.framework.configuration.Configurable;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.configuration.ConfigurationException;
  import org.apache.avalon.framework.configuration.DefaultConfiguration;
  import org.apache.avalon.framework.configuration.NamespacedSAXConfigurationHandler;
  
  import org.apache.avalon.framework.context.Context;
  import org.apache.avalon.framework.context.Contextualizable;
  import org.apache.avalon.framework.context.ContextException;
  
  import org.apache.avalon.framework.logger.AbstractLoggable;
  
  import org.apache.cocoon.components.ExtendedComponentSelector;
  import org.apache.cocoon.components.LifecycleHelper;
  
  import org.apache.cocoon.environment.Source;
  import org.apache.cocoon.environment.SourceResolver;
  
  import org.apache.cocoon.sitemap.PatternException;
  import org.apache.cocoon.util.ClassUtils;
  
  import java.util.*;
  
  /**
   *
   * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
   * @version CVS $Id: DefaultTreeBuilder.java,v 1.1 2002/03/17 21:55:22 sylvain Exp $
   */
  
  public class DefaultTreeBuilder extends AbstractLoggable implements TreeBuilder,
    Recomposable, Configurable, Contextualizable, LogKitManageable, RoleManageable, Recyclable, Disposable {
  
      /**
       * The tree processor that we're building.
       */
      protected TreeProcessor processor;
  
      //----- lifecycle-related objects ------
      protected Context context;
  
      protected LogKitManager logKit;
  
      /**
       * The parent component manager, set using <code>compose()</code> (implementation of
       * <code>Composable</code>).
       */
      protected ComponentManager parentManager;
  
      /**
       * The parent role manager, set using <code>setRoleManager</code> (implementation of
       * <code>createRoleManager</code>).
       */
      protected RoleManager parentRoleManager;
  
      protected Configuration configuration;
      // -------------------------------------
  
      /**
       * Component manager created by {@link #createComponentManager()}.
       */
      protected ComponentManager manager;
  
      /**
       * Role manager result created by {@link #createRoleManager()}.
       */
      protected RoleManager roleManager;
  
      /** Selector for ProcessingNodeBuilders */
      protected ComponentSelector builderSelector;
  
      protected LifecycleHelper lifecycle;
  
      protected String namespace;
  
      protected String parameterElement;
  
      protected String languageName;
      
      protected String fileName;
      
      /** Nodes gone through setupNode() that implement Initializable */
      private List initializableNodes = new ArrayList();
  
      /** Nodes gone through setupNode() that implement Disposable */
      private List disposableNodes = new ArrayList();
  
      /** NodeBuilders created by createNodeBuilder() that implement LinkedProcessingNodeBuilder */
      private List linkedBuilders = new ArrayList();
  
      /** Are we in a state that allows to get registered nodes ? */
      private boolean canGetNode = false;
  
      /** Nodes registered using registerNode() */
      private Map registeredNodes = new HashMap();
  
  
      public void contextualize(Context context) throws ContextException {
          this.context = context;
      }
  
      public void setLogKitManager(LogKitManager logKit) {
          this.logKit = logKit;
      }
  
      public void compose(ComponentManager manager) throws ComponentException {
          this.parentManager = manager;
      }
  
      public void recompose(ComponentManager manager) throws ComponentException {
          this.parentManager = manager;
      }
  
      public void setRoleManager(RoleManager rm) {
          this.parentRoleManager = rm;
      }
  
      public void configure(Configuration config) throws ConfigurationException {
          this.configuration = config;
  
          this.languageName = config.getAttribute("name");
          getLogger().debug("Configuring Builder for language : " + this.languageName);
  
          this.fileName = config.getChild("file").getAttribute("name");
  
          this.namespace = config.getChild("namespace").getAttribute("uri", "");
  
          this.parameterElement = config.getChild("parameter").getAttribute("element", "parameter");
      }
  
      /**
       * Create a role manager that will be used by all <code>RoleManageable</code>
       * components. The default here is to create a role manager with the contents of
       * the &lt;roles&gt; element of the configuration.
       * <p>
       * Subclasses can redefine this method to create roles from other sources than
       * the one used here.
       *
       * @return the role manager
       */
      protected RoleManager createRoleManager() throws Exception
      {
          RoleManager roles = new DefaultRoleManager();
  
          LifecycleHelper.setupComponent(roles,
              getLogger(),
              this.context,
              this.manager,
              this.parentRoleManager,
              this.logKit,
              this.configuration.getChild("roles")
          );
  
          return roles;
      }
  
      /**
       * Create a component manager that will be used for all <code>Composable</code>
       * <code>ProcessingNodeBuilder</code>s and <code>ProcessingNode</code>s.
       * <p>
       * The default here is to simply return the manager set by <code>compose()</code>,
       * i.e. the component manager set by the calling <code>TreeProcessor</code>.
       * <p>
       * Subclasses can redefine this method to create a component manager local to a tree,
       * such as for sitemap's &lt;map:components&gt;.
       *
       * @return a component manager
       */
      protected ComponentManager createComponentManager(Configuration tree) throws Exception
      {
          return this.parentManager;
      }
  
      /**
       * Create a <code>ComponentSelector</code> for <code>ProcessingNodeBuilder</code>s.
       * It creates a selector with the contents of the "node" element of the configuration.
       *
       * @return a selector for node builders
       */
      protected ComponentSelector createBuilderSelector() throws Exception {
  
          // Create the NodeBuilder selector.
          ExcaliburComponentSelector selector = new ExtendedComponentSelector() {
              protected String getComponentInstanceName() {
                  return "node";
              }
  
              protected String getClassAttributeName() {
                  return "builder";
              }
          };
  
          // Automagically initialize the selector
          LifecycleHelper.setupComponent(selector,
              getLogger(),
              this.context,
              this.manager,
              this.roleManager,
              this.logKit,
              this.configuration.getChild("nodes")
          );
  
          return selector;
      }
  
      public void setProcessor(TreeProcessor processor) {
          this.processor = processor;
      }
  
      public TreeProcessor getProcessor() {
          return this.processor;
      }
  
      /**
       * Returns the language that is being built (e.g. "sitemap").
       */
      public String getLanguage() {
          return this.languageName;
      }
  
      /**
       * Returns the name of the parameter element.
       */
      public String getParameterName() {
          return this.parameterElement;
      }
  
      /**
       * Register a <code>ProcessingNode</code> under a given name.
       * For example, <code>ResourceNodeBuilder</code> stores here the <code>ProcessingNode</code>s
       * it produces for use by sitemap pipelines. This allows to turn the tree into a graph.
       */
      public void registerNode(String name, ProcessingNode node) {
          this.registeredNodes.put(name, node);
      }
  
      public ProcessingNode getRegisteredNode(String name) {
          if (this.canGetNode) {
              return (ProcessingNode)this.registeredNodes.get(name);
          } else {
              throw new IllegalArgumentException("Categories are only available during buildNode()");
          }
      }
  
      public ProcessingNodeBuilder createNodeBuilder(Configuration config) throws Exception {
          //FIXME : check namespace
          String nodeName = config.getName();
  
          getLogger().debug("Creating node builder for " + nodeName);
  
          ProcessingNodeBuilder builder;
          try {
              builder = (ProcessingNodeBuilder)this.builderSelector.select(nodeName);
  
          } catch(ComponentException ce) {
              // Is it because this element is unknown ?
              if (this.builderSelector.hasComponent(nodeName)) {
                  // No : rethrow
                  throw ce;
              } else {
                  // Throw a more meaningfull exception
                  String msg = "Unkown element '" + nodeName + "' at " + config.getLocation();
                  getLogger().error(msg);
                  throw new ConfigurationException(msg);
              }
          }
  
          if (builder instanceof Recomposable) {
              ((Recomposable)builder).recompose(this.manager);
          }
          
          builder.setBuilder(this);
  
          if (builder instanceof LinkedProcessingNodeBuilder) {
              this.linkedBuilders.add(builder);
          }
  
          return builder;
      }
  
      /**
       * Create the tree once component manager and node builders have been set up.
       * Can be overriden by subclasses to perform pre/post tree creation operations.
       */
      protected ProcessingNode createTree(Configuration tree) throws Exception {
          // Create a node builder from the top-level element
          ProcessingNodeBuilder rootBuilder = createNodeBuilder(tree);
  
          // Build the whole tree (with an empty buildModel)
          return rootBuilder.buildNode(tree);
      }
  
      /**
       * Resolve links : call <code>linkNode()</code> on all
       * <code>LinkedProcessingNodeBuilder</code>s.
       * Can be overriden by subclasses to perform pre/post resolution operations.
       */
      protected void linkNodes() throws Exception {
          // Resolve links
          Iterator iter = this.linkedBuilders.iterator();
          while(iter.hasNext()) {
              ((LinkedProcessingNodeBuilder)iter.next()).linkNode();
          }
      }
  
      /**
       * Get the namespace URI that builders should use to find their nodes.
       */
      public String getNamespace() {
          return this.namespace;
      }
  
      public ProcessingNode build(Source source) throws Exception {
          
          try {
              // Build a namespace-aware configuration object
              NamespacedSAXConfigurationHandler handler = new NamespacedSAXConfigurationHandler();
              source.toSAX(handler);
              Configuration treeConfig = handler.getConfiguration();
          
              return build(treeConfig);
              
          } catch(Exception e) {
              getLogger().error("Failed to load " + this.languageName + " from " +
                  source.getSystemId(), e);
                  
              throw e;
          }
      }
  
      public String getFileName() {
          return this.fileName;
      }
      
      /**
       * Build a processing tree from a <code>Configuration</code>.
       */
      protected ProcessingNode build(Configuration tree) throws Exception {
  
          this.roleManager = createRoleManager();
  
          this.manager = createComponentManager(tree);
  
          // Create a helper object to setup components
          this.lifecycle = new LifecycleHelper(getLogger(),
              this.context,
              this.manager,
              this.roleManager,
              this.logKit,
              null // configuration
          );
  
          this.builderSelector = createBuilderSelector();
  
          // Calls to getRegisteredNode() are forbidden
          this.canGetNode = false;
  
          ProcessingNode result = createTree(tree);
  
          // Calls to getRegisteredNode() are now allowed
          this.canGetNode = true;
  
          linkNodes();
  
          // Initialize all Initializable nodes
          Iterator iter = this.initializableNodes.iterator();
          while(iter.hasNext()) {
              ((Initializable)iter.next()).initialize();
          }
  
          // And that's all !
          return result;
      }
  
      /**
       * Return the list of <code>ProcessingNodes</code> part of this tree that are
       * <code>Disposable</code>. Care should be taken to properly dispose them before
       * trashing the processing tree.
       */
      public List getDisposableNodes() {
          return this.disposableNodes;
      }
  
      /**
       * Setup a <code>ProcessingNode</code> by setting its location, calling all
       * the lifecycle interfaces it implements and giving it the parameter map if
       * it's a <code>ParameterizableNode</code>.
       * <p>
       * As a convenience, the node is returned by this method to allow constructs
       * like <code>return treeBuilder.setupNode(new MyNode(), config)</code>.
       */
      public ProcessingNode setupNode(ProcessingNode node, Configuration config)
        throws Exception {
          if (node instanceof AbstractProcessingNode) {
              ((AbstractProcessingNode)node).setLocation(config.getLocation());
          }
  
          this.lifecycle.setupComponent(node, false);
  
          if (node instanceof ParameterizableProcessingNode) {
              Map params = getParameters(config);
              ((ParameterizableProcessingNode)node).setParameters(params);
          }
  
          if (node instanceof Initializable) {
              this.initializableNodes.add(node);
          }
  
          if (node instanceof Disposable) {
              this.disposableNodes.add(node);
          }
  
          return node;
      }
  
      /**
       * Get &lt;xxx:parameter&gt; 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.
       */
      protected Map getParameters(Configuration config) throws ConfigurationException {
  
          Configuration[] children = config.getChildren(this.parameterElement);
  
          if (children.length == 0) {
              return null;
          }
  
          Map params = new HashMap();
          for (int i = 0; i < children.length; i++) {
              Configuration child = children[i];
              if (true) { // FIXME : check namespace
                  String value = child.getAttribute("value");
                  try {
                      params.put(child.getAttribute("name"), MapStackResolver.getResolver(value));
                  } catch(PatternException pe) {
                      String msg = "Invalid pattern '" + value + "' at " + child.getLocation();
                      getLogger().error(msg, pe);
                      throw new ConfigurationException(msg, pe);
                  }
              }
          }
  
          return params;
      }
  
      /**
       * Get the type for a statement : it returns the 'type' attribute if present,
       * and otherwhise the default hint of the <code>ExtendedSelector</code> designated by
       * role <code>role</code>.
       *
       * @throws ConfigurationException if the default type could not be found.
       */
      public String getTypeForStatement(Configuration statement, String role) throws ConfigurationException {
  
          String type = statement.getAttribute("type", null);
  
          ComponentSelector selector;
  
          try {
              selector = (ComponentSelector)this.manager.lookup(role);
          } catch(ComponentException ce) {
              String msg = "Cannot get component selector for '" + statement.getName() + "' at " +
                  statement.getLocation();
              getLogger().error(msg);
              throw new ConfigurationException(msg);
          }
  
          if (type == null && selector instanceof ExtendedComponentSelector) {
              type = ((ExtendedComponentSelector)selector).getDefaultHint();
          }
  
          if (type == null) {
              String msg = "No default type exists for '" + statement.getName() + "' at " +
                  statement.getLocation();
              getLogger().error(msg);
              throw new ConfigurationException(msg);
          }
  
          if (!selector.hasComponent(type)) {
              String msg = "Type '" + type + "' is not defined for '" + statement.getName() + "' at " +
                  statement.getLocation();
              getLogger().error(msg);
              throw new ConfigurationException(msg);
          }
  
          this.manager.release(selector);
  
          return type;
      }
  
      public void recycle() {
          this.lifecycle = null; // Created in build()
          this.initializableNodes.clear();
          this.disposableNodes.clear();
          this.linkedBuilders.clear();
          this.canGetNode = false;
          this.registeredNodes.clear();
      }
  
      public void dispose() {
          LifecycleHelper.dispose(this.builderSelector);
  
          // Don't dispose manager or roles : they are used by the built tree
          // and thus must live longer than the builder.
      }
  }
  
  
  
  1.2       +18 -16    xml-cocoon2/src/java/org/apache/cocoon/components/treeprocessor/sitemap/CallNode.java
  
  Index: CallNode.java
  ===================================================================
  RCS file: /home/cvs/xml-cocoon2/src/java/org/apache/cocoon/components/treeprocessor/sitemap/CallNode.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- CallNode.java	5 Mar 2002 08:26:23 -0000	1.1
  +++ CallNode.java	17 Mar 2002 21:55:22 -0000	1.2
  @@ -69,7 +69,7 @@
   /**
    *
    * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
  - * @version CVS $Id: CallNode.java,v 1.1 2002/03/05 08:26:23 sylvain Exp $
  + * @version CVS $Id: CallNode.java,v 1.2 2002/03/17 21:55:22 sylvain Exp $
    */
   
   public class CallNode extends AbstractProcessingNode
  @@ -120,23 +120,25 @@
   
           boolean result;
   
  -        if (this.resourceNode != null) {
  -            // Static resource name
  +        try {
  +            if (this.resourceNode != null) {
  +                // Static resource name
                   result = this.resourceNode.invoke(env, context);
  -
  -        } else {
  -            // Resolved resource name
  -            String name = this.resourceResolver.resolve(context.getMapStack());
  -
  -            if (getLogger().isInfoEnabled()) {
  -                getLogger().info("Calling resource " + name);
  +    
  +            } else {
  +                // Resolved resource name
  +                String name = this.resourceResolver.resolve(context.getMapStack());
  +    
  +                if (getLogger().isInfoEnabled()) {
  +                    getLogger().info("Calling resource " + name);
  +                }
  +    
  +                result = this.resources.invokeByName(name, env, context);
  +            }
  +        } finally {
  +            if (this.parameters != null) {
  +                context.popMap();
               }
  -
  -            result = this.resources.invokeByName(name, env, context);
  -        }
  -
  -        if (this.parameters != null) {
  -            context.popMap();
           }
           return result;
       }
  
  
  
  1.2       +7 -3      xml-cocoon2/src/java/org/apache/cocoon/components/treeprocessor/sitemap/MatchNodeBuilder.java
  
  Index: MatchNodeBuilder.java
  ===================================================================
  RCS file: /home/cvs/xml-cocoon2/src/java/org/apache/cocoon/components/treeprocessor/sitemap/MatchNodeBuilder.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- MatchNodeBuilder.java	5 Mar 2002 08:26:23 -0000	1.1
  +++ MatchNodeBuilder.java	17 Mar 2002 21:55:22 -0000	1.2
  @@ -52,7 +52,7 @@
   
   import org.apache.avalon.framework.component.ComponentManager;
   import org.apache.avalon.framework.component.ComponentSelector;
  -import org.apache.avalon.framework.component.Composable;
  +import org.apache.avalon.framework.component.Recomposable;
   import org.apache.avalon.framework.configuration.Configuration;
   import org.apache.avalon.framework.configuration.ConfigurationException;
   
  @@ -69,17 +69,21 @@
   /**
    *
    * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
  - * @version CVS $Id: MatchNodeBuilder.java,v 1.1 2002/03/05 08:26:23 sylvain Exp $
  + * @version CVS $Id: MatchNodeBuilder.java,v 1.2 2002/03/17 21:55:22 sylvain Exp $
    */
   
   public class MatchNodeBuilder extends AbstractParentProcessingNodeBuilder
  -  implements Composable {
  +  implements Recomposable {
   
       private static final String SELECTOR_ROLE = Matcher.ROLE + "Selector";
   
       private ComponentManager manager;
   
       public void compose(ComponentManager manager) {
  +        this.manager = manager;
  +    }
  +
  +    public void recompose(ComponentManager manager) {
           this.manager = manager;
       }
   
  
  
  
  1.2       +3 -3      xml-cocoon2/src/java/org/apache/cocoon/components/treeprocessor/sitemap/SitemapLanguage.java
  
  Index: SitemapLanguage.java
  ===================================================================
  RCS file: /home/cvs/xml-cocoon2/src/java/org/apache/cocoon/components/treeprocessor/sitemap/SitemapLanguage.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- SitemapLanguage.java	5 Mar 2002 08:26:23 -0000	1.1
  +++ SitemapLanguage.java	17 Mar 2002 21:55:22 -0000	1.2
  @@ -72,7 +72,7 @@
   
   import org.apache.cocoon.components.treeprocessor.CategoryNode;
   import org.apache.cocoon.components.treeprocessor.CategoryNodeBuilder;
  -import org.apache.cocoon.components.treeprocessor.TreeBuilder;
  +import org.apache.cocoon.components.treeprocessor.DefaultTreeBuilder;
   
   import org.apache.cocoon.util.StringUtils;
   
  @@ -82,10 +82,10 @@
    * The tree builder for the sitemap language.
    *
    * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
  - * @version CVS $Id: SitemapLanguage.java,v 1.1 2002/03/05 08:26:23 sylvain Exp $
  + * @version CVS $Id: SitemapLanguage.java,v 1.2 2002/03/17 21:55:22 sylvain Exp $
    */
   
  -public class SitemapLanguage extends TreeBuilder {
  +public class SitemapLanguage extends DefaultTreeBuilder {
   
       private static final String ATTR_PREFIX = "org.apache.cocoon.components.treeprocessor.ViewNodeBuilder";
   
  
  
  

----------------------------------------------------------------------
In case of troubles, e-mail:     webmaster@xml.apache.org
To unsubscribe, e-mail:          cocoon-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: cocoon-cvs-help@xml.apache.org