You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by vg...@apache.org on 2004/11/18 01:15:59 UTC

svn commit: rev 76197 - in cocoon/trunk/src/java/org/apache/cocoon: . components/treeprocessor components/treeprocessor/sitemap

Author: vgritsenko
Date: Wed Nov 17 16:15:58 2004
New Revision: 76197

Modified:
   cocoon/trunk/src/java/org/apache/cocoon/Constants.java
   cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/DefaultTreeBuilder.java
   cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/SitemapLanguage.java
Log:
Refactor DefaultTreeBuilder. Make stuff private.
Implement separate context object for each pipeline
(required for VPCs)


Modified: cocoon/trunk/src/java/org/apache/cocoon/Constants.java
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/Constants.java	(original)
+++ cocoon/trunk/src/java/org/apache/cocoon/Constants.java	Wed Nov 17 16:15:58 2004
@@ -24,7 +24,7 @@
  *
  * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
  * @author <a href="mailto:proyal@managingpartners.com">Peter Royal</a>
- * @version CVS $Id: Constants.java,v 1.15 2004/06/11 21:37:04 vgritsenko Exp $
+ * @version CVS $Id$
  */
 public final class Constants {
 
@@ -255,6 +255,19 @@
 
     /** Application <code>Context</code> Key for the current classpath */
     public static final String CONTEXT_CLASSPATH = "classpath";
+
+
+    /** Application <code>Context</code> key for the current environment URI */
+    public static final String CONTEXT_ENV_URI = "env-uri";
+
+    /** Application <code>Context</code> key for the current environment prefix */
+    public static final String CONTEXT_ENV_PREFIX = "env-prefix";
+
+    /** Application <code>Context</code> key for the current environment helper */
+    public static final String CONTEXT_ENV_HELPER = "env-helper";
+
+    /** Application <code>Context</code> key prefix for the current sitemap virtual components */
+    public static final String CONTEXT_VPC_PREFIX = "vpc-";
 
     /**
      * Application <code>Context</code> Key for the URL to the configuration file

Modified: cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/DefaultTreeBuilder.java
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/DefaultTreeBuilder.java	(original)
+++ cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/DefaultTreeBuilder.java	Wed Nov 17 16:15:58 2004
@@ -39,6 +39,7 @@
 import org.apache.cocoon.components.LifecycleHelper;
 import org.apache.cocoon.components.source.SourceUtil;
 import org.apache.cocoon.components.treeprocessor.variables.VariableResolverFactory;
+import org.apache.cocoon.components.treeprocessor.variables.VariableResolver;
 import org.apache.cocoon.sitemap.PatternException;
 import org.apache.cocoon.sitemap.SitemapParameters;
 import org.apache.excalibur.source.Source;
@@ -56,38 +57,62 @@
 
     protected Map attributes = new HashMap();
 
+    //----- lifecycle-related objects ------
+
+    /**
+     * This component's avalon context
+     */
+    private Context context;
+
+    /**
+     * This component's service manager
+     */
+    private ServiceManager manager;
+
+    // -------------------------------------
+
     /**
-     * The tree processor that we're building.
+     * The tree processor that we are building.
      */
     protected ConcreteTreeProcessor processor;
 
-    //----- lifecycle-related objects ------
-    protected Context context;
+    /**
+     * The namespace of configuration for the processor that we are building.
+     */
+    protected String itsNamespace;
 
     /**
-     * The parent component manager. Either the one of the parent processor, or that provided
-     * by Cocoon in service()
+     * The context for the processor that we are building
+     * It is created by {@link #createContext(Configuration)}.
      */
-    protected ServiceManager ownManager;
+    private Context itsContext;
 
-    // -------------------------------------
+    /**
+     * The service manager for the processor that we are building.
+     * It is created by {@link #createServiceManager(Context, Configuration)}.
+     */
+    private ServiceManager itsManager;
 
     /**
-     * Component processor of the parent manager (can be null for the root sitemap)
+     * Helper object which sets up components in the context
+     * of the processor that we are building.
      */
-    protected ServiceManager parentProcessorManager;
+    private LifecycleHelper itsLifecycle;
 
     /**
-     * Component manager created by {@link #createServiceManager(Configuration)}.
+     * Selector for ProcessingNodeBuilders which is set up
+     * in the context of the processor that we are building.
      */
-    protected ServiceManager processorManager;
+    private ServiceSelector itsBuilders;
 
-    /** Selector for ProcessingNodeBuilders */
-    protected ServiceSelector builderSelector;
+    // -------------------------------------
 
-    protected LifecycleHelper lifecycle;
+    /**
+     * Component processor of the parent manager
+     * (can be null for the root sitemap)
+     */
+    protected ServiceManager parentProcessorManager;
 
-    protected String namespace;
 
     /** Nodes gone through setupNode() that implement Initializable */
     private List initializableNodes = new ArrayList();
@@ -116,9 +141,13 @@
      * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
      */
     public void service(ServiceManager manager) throws ServiceException {
-        this.ownManager = manager;
+        this.manager = manager;
     }
 
+    public void initialize() throws Exception {
+    }
+
+
     /**
      * Get the location of the treebuilder config file. Can be overridden for other versions.
      * @return
@@ -127,51 +156,6 @@
         return "resource://org/apache/cocoon/components/treeprocessor/sitemap-language.xml";
     }
 
-    public void initialize() throws Exception {
-        // Load the builder config file
-        SourceResolver resolver = (SourceResolver) this.ownManager.lookup(SourceResolver.ROLE);
-        String url = getBuilderConfigURL();
-        Configuration config;
-        try {
-            Source src = resolver.resolveURI(url);
-            try {
-                SAXConfigurationHandler handler = new SAXConfigurationHandler();
-                SourceUtil.toSAX(this.ownManager, src, null, handler);
-                config = handler.getConfiguration();
-            } finally {
-                resolver.release(src);
-            }
-        } catch (Exception e) {
-            throw new ConfigurationException("Could not load TreeBuilder configuration from " + url, e);
-        } finally {
-            this.ownManager.release(resolver);
-        }
-
-        // Create the NodeBuilder selector.
-        CocoonServiceSelector selector = new CocoonServiceSelector() {
-            protected String getComponentInstanceName() {
-                return "node";
-            }
-
-            protected String getClassAttributeName() {
-                return "builder";
-            }
-        };
-
-        // Automagically initialize the selector
-        LifecycleHelper.setupComponent(selector,
-            getLogger(),
-            this.context,
-            this.ownManager,
-            config.getChild("nodes", false),
-            true
-        );
-
-        this.builderSelector = selector;
-
-    }
-
-
     public void setParentProcessorManager(ServiceManager manager) {
         this.parentProcessorManager = manager;
     }
@@ -191,23 +175,44 @@
     }
 
     /**
+     * Create a context that will be used for all <code>Contextualizable</code>
+     * <code>ProcessingNodeBuilder</code>s and <code>ProcessingNode</code>s.
+     *
+     * <p>The default here is to simply return the context set in
+     * <code>contextualize()</code>, i.e. the context set by the calling
+     * <code>TreeProcessor</code>.
+     *
+     * <p>Subclasses can redefine this method to create a context local to
+     * a tree, such as for sitemap's &lt;map:components&gt;.
+     *
+     * @return a context
+     */
+    protected Context createContext(Configuration tree)
+    throws Exception {
+        return this.context;
+    }
+
+    /**
      * Create a service manager that will be used for all <code>Serviceable</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;.
+     *
+     * <p>The default here is to simply return the manager set in
+     * <code>compose()</code>, i.e. the component manager set by the calling
+     * <code>TreeProcessor</code>.
+     *
+     * <p>Subclasses can redefine this method to create a service manager local to
+     * a tree, such as for sitemap's &lt;map:components&gt;.
      *
      * @return a component manager
      */
-    protected ServiceManager createServiceManager(Configuration tree) throws Exception {
-        return this.ownManager;
+    protected ServiceManager createServiceManager(Context context, Configuration tree)
+    throws Exception {
+        return this.manager;
     }
 
+
     /* (non-Javadoc)
-     * @see org.apache.cocoon.components.treeprocessor.TreeBuilder#setProcessor(org.apache.cocoon.components.treeprocessor.ConcreteTreeProcessor)
+     * @see org.apache.cocoon.components.treeprocessor.TreeBuilder#setProcessor(ConcreteTreeProcessor)
      */
     public void setProcessor(ConcreteTreeProcessor processor) {
         this.processor = processor;
@@ -220,6 +225,7 @@
         return this.processor;
     }
 
+
     /**
      * Register a <code>ProcessingNode</code> under a given name.
      * For example, <code>ResourceNodeBuilder</code> stores here the <code>ProcessingNode</code>s
@@ -241,17 +247,16 @@
         // FIXME : check namespace
         String nodeName = config.getName();
 
-        if (this.getLogger().isDebugEnabled()) {
+        if (getLogger().isDebugEnabled()) {
             getLogger().debug("Creating node builder for " + nodeName);
         }
 
         ProcessingNodeBuilder builder;
         try {
-            builder = (ProcessingNodeBuilder)this.builderSelector.select(nodeName);
-
-        } catch(ServiceException ce) {
+            builder = (ProcessingNodeBuilder) this.itsBuilders.select(nodeName);
+        } catch (ServiceException ce) {
             // Is it because this element is unknown ?
-            if (this.builderSelector.isSelectable(nodeName)) {
+            if (this.itsBuilders.isSelectable(nodeName)) {
                 // No : rethrow
                 throw ce;
             } else {
@@ -299,25 +304,63 @@
      * Get the namespace URI that builders should use to find their nodes.
      */
     public String getNamespace() {
-        return this.namespace;
+        return this.itsNamespace;
     }
 
     /**
      * Build a processing tree from a <code>Configuration</code>.
      */
     public ProcessingNode build(Configuration tree) throws Exception {
+        // The namespace used in the whole sitemap is the one of the root element
+        this.itsNamespace = tree.getNamespace();
 
-        // The namespace use in the whole sitemap is the one of the root element
-        this.namespace = tree.getNamespace();
-
-        this.processorManager = createServiceManager(tree);
+        // Context and manager for the sitemap we build
+        this.itsContext = createContext(tree);
+        this.itsManager = createServiceManager(this.itsContext, tree);
 
         // Create a helper object to setup components
-        this.lifecycle = new LifecycleHelper(getLogger(),
-            this.context,
-            this.processorManager,
-            null // configuration
-        );
+        this.itsLifecycle = new LifecycleHelper(getLogger(),
+                                             this.itsContext,
+                                             this.itsManager,
+                                             null /* configuration */);
+
+        // Create & initialize the NodeBuilder selector.
+        {
+            CocoonServiceSelector selector = new CocoonServiceSelector() {
+                protected String getComponentInstanceName() {
+                    return "node";
+                }
+
+                protected String getClassAttributeName() {
+                    return "builder";
+                }
+            };
+            // Load the builder config file
+            SourceResolver resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
+            String url = getBuilderConfigURL();
+            Configuration config;
+            try {
+                Source src = resolver.resolveURI(url);
+                try {
+                    SAXConfigurationHandler handler = new SAXConfigurationHandler();
+                    SourceUtil.toSAX(this.manager, src, null, handler);
+                    config = handler.getConfiguration();
+                } finally {
+                    resolver.release(src);
+                }
+            } catch (Exception e) {
+                throw new ConfigurationException("Could not load TreeBuilder configuration from " + url, e);
+            } finally {
+                this.manager.release(resolver);
+            }
+            LifecycleHelper.setupComponent(selector,
+                                           getLogger(),
+                                           this.itsContext,
+                                           this.itsManager,
+                                           config.getChild("nodes", false),
+                                           true);
+            this.itsBuilders = selector;
+        }
 
         // Calls to getRegisteredNode() are forbidden
         this.canGetNode = false;
@@ -366,7 +409,7 @@
             ((AbstractProcessingNode)node).setSitemapExecutor(this.processor.getSitemapExecutor());
         }
 
-        this.lifecycle.setupComponent(node, false);
+        this.itsLifecycle.setupComponent(node, false);
 
         if (node instanceof ParameterizableProcessingNode) {
             Map params = getParameters(config);
@@ -407,9 +450,7 @@
                 String name = child.getAttribute("name");
                 String value = child.getAttribute("value");
                 try {
-                    params.put(
-                        VariableResolverFactory.getResolver(name, this.processorManager),
-                        VariableResolverFactory.getResolver(value, this.processorManager));
+                    params.put(resolve(name), resolve(value));
                 } catch(PatternException pe) {
                     String msg = "Invalid pattern '" + value + "' at " + child.getLocation();
                     throw new ConfigurationException(msg, pe);
@@ -442,42 +483,50 @@
 
         // Check that this type actually exists
         ServiceSelector selector = null;
-
         try {
-            selector = (ServiceSelector)this.processorManager.lookup(role + "Selector");
-        } catch(ServiceException ce) {
+            selector = (ServiceSelector) this.itsManager.lookup(role + "Selector");
+        } catch (ServiceException e) {
             throw new ConfigurationException("Cannot get service selector for 'map:" +
-                statement.getName() + "' at " + statement.getLocation(),
-                ce
-            );
+                                             statement.getName() + "' at " + statement.getLocation(),
+                                             e);
         }
 
-        this.processorManager.release(selector);
+        this.itsManager.release(selector);
 
         if (!selector.isSelectable(type)) {
             throw new ConfigurationException("Type '" + type + "' does not exist for 'map:" +
-                statement.getName() + "' at " + statement.getLocation()
-            );
+                                             statement.getName() + "' at " + statement.getLocation());
         }
 
         return type;
     }
 
+    /**
+     * Resolve expression using its manager
+     */
+    protected VariableResolver resolve (String expression)
+    throws PatternException {
+        return VariableResolverFactory.getResolver(expression, this.itsManager);
+    }
+
     public void recycle() {
         // Reset all data created during the build
         this.attributes.clear();
         this.canGetNode = false;
         this.disposableNodes = new ArrayList(); // Must not be cleared as it's used for processor disposal
         this.initializableNodes.clear();
-        this.lifecycle = null; // Created in build()
         this.linkedBuilders.clear();
-        this.namespace = null; // Set in build()
         this.parentProcessorManager = null; // Set in setParentProcessorManager()
-        this.processor = null; // Set in setProcessor()
-        this.processorManager = null; // Set in build()
-        this.registeredNodes.clear();
+        this.processor = null;          // Set in setProcessor()
+
+        this.itsNamespace = null;       // Set in build()
+        LifecycleHelper.dispose(this.itsBuilders);
+        this.itsBuilders = null;        // Set in build()
+        this.itsLifecycle = null;       // Set in build()
+        this.itsManager = null;         // Set in build()
+        this.itsContext = null;         // Set in build()
 
-        this.lifecycle = null; // Created in build()
+        this.registeredNodes.clear();
         this.initializableNodes.clear();
         this.linkedBuilders.clear();
         this.canGetNode = false;
@@ -487,8 +536,6 @@
     }
 
     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.
     }

Modified: cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/SitemapLanguage.java
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/SitemapLanguage.java	(original)
+++ cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/SitemapLanguage.java	Wed Nov 17 16:15:58 2004
@@ -15,20 +15,14 @@
  */
 package org.apache.cocoon.components.treeprocessor.sitemap;
 
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-import java.util.StringTokenizer;
-
 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.DefaultContext;
 import org.apache.avalon.framework.service.ServiceManager;
+
+import org.apache.cocoon.Constants;
 import org.apache.cocoon.acting.Action;
 import org.apache.cocoon.components.container.CocoonServiceManager;
 import org.apache.cocoon.components.pipeline.ProcessingPipeline;
@@ -36,7 +30,8 @@
 import org.apache.cocoon.components.treeprocessor.CategoryNodeBuilder;
 import org.apache.cocoon.components.treeprocessor.DefaultTreeBuilder;
 import org.apache.cocoon.components.treeprocessor.ProcessorComponentInfo;
-import org.apache.cocoon.components.treeprocessor.variables.VariableResolverFactory;
+import org.apache.cocoon.environment.Environment;
+import org.apache.cocoon.environment.internal.EnvironmentHelper;
 import org.apache.cocoon.generation.Generator;
 import org.apache.cocoon.matching.Matcher;
 import org.apache.cocoon.reading.Reader;
@@ -45,8 +40,19 @@
 import org.apache.cocoon.sitemap.PatternException;
 import org.apache.cocoon.transformation.Transformer;
 import org.apache.cocoon.util.StringUtils;
+
 import org.apache.regexp.RE;
 
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+
 /**
  * The tree builder for the sitemap language.
  *
@@ -63,7 +69,7 @@
      * Build a component manager with the contents of the &lt;map:components&gt; element of
      * the tree.
      */
-    protected ServiceManager createServiceManager(Configuration tree) throws Exception {
+    protected ServiceManager createServiceManager(Context context, Configuration tree) throws Exception {
 
         // Get the map:component node
         // Don't check namespace here : this will be done by node builders
@@ -80,7 +86,7 @@
 
         // Go through the component lifecycle
         newManager.enableLogging(getLogger());
-        newManager.contextualize(this.context);
+        newManager.contextualize(context);
         newManager.configure(config);
         newManager.initialize();
 
@@ -111,6 +117,17 @@
         return newManager;
     }
 
+    protected Context createContext(Configuration tree) throws Exception {
+        // Create sub-context for this sitemap
+        DefaultContext newContext = new DefaultContext(super.createContext(tree));
+        Environment env = EnvironmentHelper.getCurrentEnvironment();
+        newContext.put(Constants.CONTEXT_ENV_URI, env.getURI());
+        newContext.put(Constants.CONTEXT_ENV_PREFIX, env.getURIPrefix());
+        // FIXME How to get rif of EnvironmentHelper?
+        newContext.put(Constants.CONTEXT_ENV_HELPER, getProcessor().getWrappingProcessor().getEnvironmentHelper());
+        return newContext;
+    }
+
     /**
      * Setup the default compnent type for a given role.
      *
@@ -461,16 +478,14 @@
                                        + "\npipeline-hints: (value) [implicit] true");
                     }
 
-                    params.put( VariableResolverFactory.getResolver(nameValuePair[0], this.processorManager),
-                                VariableResolverFactory.getResolver("true", this.processorManager));
+                    params.put(resolve(nameValuePair[0]), resolve("true"));
                 } else {
                     if (getLogger().isDebugEnabled()) {
                         getLogger().debug("pipeline-hints: (name) " + nameValuePair[0]
                                           + "\npipeline-hints: (value) " + nameValuePair[1]);
                     }
 
-                    params.put( VariableResolverFactory.getResolver(nameValuePair[0], this.processorManager),
-                                VariableResolverFactory.getResolver(nameValuePair[1], this.processorManager));
+                    params.put(resolve(nameValuePair[0]), resolve(nameValuePair[1]));
                 }
             } catch(PatternException pe) {
                 String msg = "Invalid pattern '" + hintParams + "' at " + statement.getLocation();