cocoon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cziege...@apache.org
Subject svn commit: rev 37174 - in cocoon/branches/BRANCH_2_1_X: . src/java/org/apache/cocoon/components/treeprocessor src/java/org/apache/cocoon/components/treeprocessor/sitemap
Date Sun, 29 Aug 2004 16:29:32 GMT
Author: cziegeler
Date: Sun Aug 29 09:29:31 2004
New Revision: 37174

Added:
   cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/ConcreteTreeProcessor.java
Modified:
   cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/AbstractProcessingNode.java
   cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/AbstractProcessingNodeBuilder.java
   cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/DefaultTreeBuilder.java
   cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/InvokeContext.java
   cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/ProcessingNode.java
   cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/TreeBuilder.java
   cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java
   cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ActSetNode.java
   cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ActTypeNode.java
   cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/CallFunctionNode.java
   cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ContinueNode.java
   cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ContinueNodeBuilder.java
   cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/FlowNode.java
   cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/MountNode.java
   cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/MountNodeBuilder.java
   cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/PipelinesNode.java
   cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/RedirectToURINode.java
   cocoon/branches/BRANCH_2_1_X/status.xml
Log:
Sync TreeProcessor and (re)apply patches

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/AbstractProcessingNode.java
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/AbstractProcessingNode.java	(original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/AbstractProcessingNode.java	Sun Aug 29 09:29:31 2004
@@ -15,15 +15,15 @@
  */
 package org.apache.cocoon.components.treeprocessor;
 
+import java.util.Map;
+
 import org.apache.avalon.framework.logger.AbstractLogEnabled;
 import org.apache.cocoon.environment.SourceResolver;
 
-import java.util.Map;
-
 /**
  *
  * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
- * @version CVS $Id: AbstractProcessingNode.java,v 1.2 2004/03/05 13:02:51 bdelacretaz Exp $
+ * @version CVS $Id$
  */
 
 public abstract class AbstractProcessingNode extends AbstractLogEnabled implements ProcessingNode {

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/AbstractProcessingNodeBuilder.java
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/AbstractProcessingNodeBuilder.java	(original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/AbstractProcessingNodeBuilder.java	Sun Aug 29 09:29:31 2004
@@ -30,7 +30,7 @@
 /**
  *
  * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
- * @version CVS $Id: AbstractProcessingNodeBuilder.java,v 1.4 2004/03/08 12:07:39 cziegeler Exp $
+ * @version CVS $Id$
  */
 
 

Added: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/ConcreteTreeProcessor.java
==============================================================================
--- (empty file)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/ConcreteTreeProcessor.java	Sun Aug 29 09:29:31 2004
@@ -0,0 +1,384 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.components.treeprocessor;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.avalon.framework.activity.Disposable;
+import org.apache.avalon.framework.component.ComponentManager;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.avalon.framework.logger.Logger;
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.Processor;
+import org.apache.cocoon.components.ChainedConfiguration;
+import org.apache.cocoon.components.CocoonComponentManager;
+import org.apache.cocoon.components.pipeline.ProcessingPipeline;
+import org.apache.cocoon.components.treeprocessor.sitemap.PipelinesNode;
+import org.apache.cocoon.environment.Environment;
+import org.apache.cocoon.environment.ForwardRedirector;
+import org.apache.cocoon.environment.Redirector;
+import org.apache.cocoon.environment.wrapper.EnvironmentWrapper;
+import org.apache.cocoon.environment.wrapper.MutableEnvironmentFacade;
+
+
+/**
+ * The concrete implementation of {@link Processor}, containing the evaluation tree and associated
+ * data such as component manager.
+ * 
+ * @version CVS $Id: ConcreteTreeProcessor.java,v 1.1 2004/06/05 08:18:50 sylvain Exp $
+ */
+public class ConcreteTreeProcessor extends AbstractLogEnabled implements Processor {
+
+	/** The processor that wraps us */
+	private TreeProcessor wrappingProcessor;
+	
+	/** Component manager defined by the &lt;map:components&gt; of this sitemap */
+    ComponentManager sitemapComponentManager;
+    
+  	/** Processing nodes that need to be disposed with this processor */
+    private List disposableNodes;
+   
+    /** Root node of the processing tree */
+    private ProcessingNode rootNode;
+    
+    private Map sitemapComponentConfigurations;
+    
+    private Configuration componentConfigurations;
+    
+    /** Number of simultaneous uses of this processor (either by concurrent request or by internal requests) */
+    private int requestCount;
+    
+	/** Builds a concrete processig, given the wrapping processor */
+	public ConcreteTreeProcessor(TreeProcessor wrappingProcessor) {
+		this.wrappingProcessor = wrappingProcessor;
+	}
+	
+	/** Set the processor data, result of the treebuilder job */
+	public void setProcessorData(ComponentManager manager, ProcessingNode rootNode, List disposableNodes) {
+		if (this.sitemapComponentManager != null) {
+			throw new IllegalStateException("setProcessorData() can only be called once");
+		}
+		
+		this.sitemapComponentManager = manager;
+		this.rootNode = rootNode;
+		this.disposableNodes = disposableNodes;
+	}
+	
+	/** Set the sitemap component configurations (called as part of the tree building process) */
+    public void setComponentConfigurations(Configuration componentConfigurations) {
+        this.componentConfigurations = componentConfigurations;
+        this.sitemapComponentConfigurations = null;
+    }
+
+    /**
+     * Get the sitemap component configurations
+     * @since 2.1
+     */
+    public Map getComponentConfigurations() {
+        // do we have the sitemap configurations prepared for this processor?
+        if ( null == this.sitemapComponentConfigurations ) {
+            
+            synchronized (this) {
+
+                if ( this.sitemapComponentConfigurations == null ) {
+                    // do we have configurations?
+                    final Configuration[] childs = (this.componentConfigurations == null 
+                                                     ? null 
+                                                     : this.componentConfigurations.getChildren());
+                    
+                    if ( null != childs ) {
+        
+                        if ( null == this.wrappingProcessor.parent ) {
+                            this.sitemapComponentConfigurations = new HashMap(12);
+                        } else {
+                            // copy all configurations from parent
+                            this.sitemapComponentConfigurations = new HashMap(
+                            			this.wrappingProcessor.parent.getComponentConfigurations()); 
+                        }
+                        
+                        // and now check for new configurations
+                        for(int m = 0; m < childs.length; m++) {
+                            
+                            final String r = this.wrappingProcessor.roleManager.getRoleForName(childs[m].getName());
+                            this.sitemapComponentConfigurations.put(r, new ChainedConfiguration(childs[m], 
+                                                                             (ChainedConfiguration)this.sitemapComponentConfigurations.get(r)));
+                        }
+                    } else {
+                        // we don't have configurations
+                        if ( null == this.wrappingProcessor.parent ) {
+                            this.sitemapComponentConfigurations = Collections.EMPTY_MAP;
+                        } else {
+                            // use configuration from parent
+                            this.sitemapComponentConfigurations = this.wrappingProcessor.parent.getComponentConfigurations(); 
+                        }
+                    }
+                }
+            }
+        }
+        return this.sitemapComponentConfigurations;    }
+	
+    /**
+     * Mark this processor as needing to be disposed. Actual call to {@link #dispose()} will occur when
+     * all request processings on this processor will be terminated.
+     */
+	public void markForDisposal() {
+		// Decrement the request count (negative number means dispose)
+		synchronized(this) {
+			this.requestCount--;
+		}
+		
+		if (this.requestCount < 0) {
+			// No more users : dispose right now
+			dispose();
+		}
+	}
+	
+	public TreeProcessor getWrappingProcessor() {
+		return this.wrappingProcessor;
+	}
+	
+	public Processor getRootProcessor() {
+		return this.wrappingProcessor.getRootProcessor();
+	}
+	
+    /**
+     * Process the given <code>Environment</code> producing the output.
+     * @return If the processing is successfull <code>true</code> is returned.
+     *         If not match is found in the sitemap <code>false</code>
+     *         is returned.
+     * @throws org.apache.cocoon.ResourceNotFoundException If a sitemap component tries
+     *                                   to access a resource which can not
+     *                                   be found, e.g. the generator
+     *         ConnectionResetException  If the connection was reset
+     */
+    public boolean process(Environment environment) throws Exception {
+        InvokeContext context = new InvokeContext();
+
+        context.enableLogging(getLogger());
+
+        try {
+            return process(environment, context);
+        } finally {
+            context.dispose();
+        }
+    }
+
+    /**
+     * Process the given <code>Environment</code> to assemble
+     * a <code>ProcessingPipeline</code>.
+     * @since 2.1
+     */
+    public ProcessingPipeline buildPipeline(Environment environment)
+    throws Exception {
+        InvokeContext context = new InvokeContext( true );
+
+        context.enableLogging(getLogger());
+
+        try {
+            if ( process(environment, context) ) {
+                return context.getProcessingPipeline();
+            } else {
+                return null;
+            }
+        } finally {
+            context.dispose();
+        }
+    }
+
+    /**
+     * Do the actual processing, be it producing the response or just building the pipeline
+     * @param environment
+     * @param context
+     * @return true if the pipeline was successfully built, false otherwise.
+     * @throws Exception
+     */
+    protected boolean process(Environment environment, InvokeContext context)
+    throws Exception {
+    	
+    		// Increment the concurrent requests count
+    		synchronized(this) {
+    			requestCount++;
+    		}
+
+    		try {
+    			
+    	        // and now process
+                CocoonComponentManager.enterEnvironment(environment, this.sitemapComponentManager, this);
+
+                Map objectModel = environment.getObjectModel();
+
+                Object oldResolver = objectModel.get(ProcessingNode.OBJECT_SOURCE_RESOLVER);
+    	        final Redirector oldRedirector = context.getRedirector();
+
+    	        // Build a redirector
+    	        TreeProcessorRedirector redirector = new TreeProcessorRedirector(environment, context);
+    	        setupLogger(redirector);
+    	        context.setRedirector(redirector);
+
+                objectModel.put(ProcessingNode.OBJECT_SOURCE_RESOLVER, environment);
+    	        try {
+    	            boolean success = this.rootNode.invoke(environment, context);
+    	            
+    	            return success;
+
+    	        } finally {
+                    CocoonComponentManager.leaveEnvironment();
+                    // Restore old redirector and resolver
+     	            context.setRedirector(oldRedirector);
+                    objectModel.put(PipelinesNode.OBJECT_SOURCE_RESOLVER, oldResolver);
+    	        }
+
+    		} finally {
+    			
+    			// Decrement the concurrent request count
+    			synchronized(this) {
+    				requestCount--;
+    			}
+    			
+    			if(requestCount < 0) {
+    				// Marked for disposal and no more concurrent requests.
+    				dispose();
+    			}
+    		}
+    }
+        
+    private boolean handleCocoonRedirect(String uri, Environment environment, InvokeContext context) throws Exception {
+        
+        // Build an environment wrapper
+        // If the current env is a facade, change the delegate and continue processing the facade, since
+        // we may have other redirects that will in turn also change the facade delegate
+        
+        MutableEnvironmentFacade facade = environment instanceof MutableEnvironmentFacade ?
+            ((MutableEnvironmentFacade)environment) : null;
+        
+        if (facade != null) {
+            // Consider the facade delegate (the real environment)
+            environment = facade.getDelegate();
+        }
+        
+        // test if this is a call from flow
+        boolean isRedirect = (environment.getObjectModel().remove("cocoon:forward") == null);
+        Environment newEnv = new ForwardEnvironmentWrapper(environment, this.sitemapComponentManager, uri, getLogger());
+        if ( isRedirect ) {
+            ((ForwardEnvironmentWrapper)newEnv).setInternalRedirect(true);
+        }
+        
+        if (facade != null) {
+            // Change the facade delegate
+            facade.setDelegate((EnvironmentWrapper)newEnv);
+            newEnv = facade;
+        }
+        
+        // Get the processor that should process this request
+        ConcreteTreeProcessor processor;
+        if (newEnv.getRootContext() == newEnv.getContext()) {
+            processor = (ConcreteTreeProcessor)getRootProcessor();
+        } else {
+            processor = this;
+        }
+        
+        // Process the redirect
+// No more reset since with TreeProcessorRedirector, we need to pop values from the redirect location
+//        context.reset();
+        // The following is a fix for bug #26854 and #26571
+        final boolean result = processor.process(newEnv, context);
+        if ( ((ForwardEnvironmentWrapper)newEnv).getRedirectURL() != null ) {
+            environment.redirect( false, ((ForwardEnvironmentWrapper)newEnv).getRedirectURL() );
+        }
+        return result;
+    }
+    
+	public void dispose() {
+        if (this.disposableNodes != null) {
+            // we must dispose the nodes in reverse order
+            // otherwise selector nodes are freed before the components node
+            for(int i=this.disposableNodes.size()-1; i>-1; i--) {
+                ((Disposable)disposableNodes.get(i)).dispose();
+            }
+            this.disposableNodes = null;
+        }
+        
+        // Ensure it won't be used anymore
+        this.rootNode = null;
+	}
+    
+    private class TreeProcessorRedirector extends ForwardRedirector {
+        
+        private InvokeContext context;
+        public TreeProcessorRedirector(Environment env, InvokeContext context) {
+            super(env);
+            this.context = context;
+        }
+        
+        protected void cocoonRedirect(String uri) throws IOException, ProcessingException {
+            try {
+                ConcreteTreeProcessor.this.handleCocoonRedirect(uri, this.env, this.context);
+            } catch(IOException ioe) {
+                throw ioe;
+            } catch(ProcessingException pe) {
+                throw pe;
+            } catch(RuntimeException re) {
+                throw re;
+            } catch(Exception ex) {
+                throw new ProcessingException(ex);
+            }
+        }
+    }
+    
+    /**
+     * Local extension of EnvironmentWrapper to propagate otherwise blocked
+     * methods to the actual environment.
+     */
+    private static final class ForwardEnvironmentWrapper extends EnvironmentWrapper {
+
+        public ForwardEnvironmentWrapper(Environment env,
+            ComponentManager manager, String uri, Logger logger) 
+        throws MalformedURLException {
+            super(env, manager, uri, logger);
+        }
+
+        public void setStatus(int statusCode) {
+            environment.setStatus(statusCode);
+        }
+
+        public void setContentLength(int length) {
+            environment.setContentLength(length);
+        }
+
+        public void setContentType(String contentType) {
+            environment.setContentType(contentType);
+        }
+
+        public String getContentType() {
+            return environment.getContentType();
+        }
+
+        public boolean isResponseModified(long lastModified) {
+            return environment.isResponseModified(lastModified);
+        }
+        
+        public void setResponseIsNotModified() {
+            environment.setResponseIsNotModified();
+        }
+    }
+
+}

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/DefaultTreeBuilder.java
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/DefaultTreeBuilder.java	(original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/DefaultTreeBuilder.java	Sun Aug 29 09:29:31 2004
@@ -52,7 +52,7 @@
 /**
  *
  * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
- * @version CVS $Id: DefaultTreeBuilder.java,v 1.8 2004/03/08 12:07:39 cziegeler Exp $
+ * @version CVS $Id$
  */
 
 public class DefaultTreeBuilder extends AbstractLogEnabled implements TreeBuilder,
@@ -63,7 +63,7 @@
     /**
      * The tree processor that we're building.
      */
-    protected TreeProcessor processor;
+    protected ConcreteTreeProcessor processor;
 
     //----- lifecycle-related objects ------
     protected Context context;
@@ -237,11 +237,11 @@
         return selector;
     }
 
-    public void setProcessor(TreeProcessor processor) {
+    public void setProcessor(ConcreteTreeProcessor processor) {
         this.processor = processor;
     }
 
-    public TreeProcessor getProcessor() {
+    public ConcreteTreeProcessor getProcessor() {
         return this.processor;
     }
 

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/InvokeContext.java
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/InvokeContext.java	(original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/InvokeContext.java	Sun Aug 29 09:29:31 2004
@@ -20,11 +20,11 @@
 import org.apache.avalon.framework.component.ComponentManager;
 import org.apache.avalon.framework.component.ComponentSelector;
 import org.apache.avalon.framework.component.Recomposable;
-import org.apache.avalon.framework.logger.LogEnabled;
-import org.apache.avalon.framework.logger.Logger;
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
 import org.apache.cocoon.components.CocoonComponentManager;
 import org.apache.cocoon.components.pipeline.ProcessingPipeline;
 import org.apache.cocoon.components.treeprocessor.variables.VariableResolver;
+import org.apache.cocoon.environment.Redirector;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -45,10 +45,12 @@
  * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
  * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
  * @author <a href="mailto:tcurdt@apache.org">Torsten Curdt</a>
- * @version CVS $Id: InvokeContext.java,v 1.5 2004/03/05 13:02:51 bdelacretaz Exp $
+ * @version CVS $Id$
  */
 
-public class InvokeContext implements Recomposable, Disposable, LogEnabled {
+public class InvokeContext 
+extends AbstractLogEnabled
+implements Recomposable, Disposable {
 
     private List mapStack = new ArrayList();
     private HashMap nameToMap = new HashMap();
@@ -62,9 +64,6 @@
     /** The component manager that was used to get the pipelines */
     private ComponentManager pipelinesManager;
 
-    /** Logger that we will log any messages to */
-    private Logger logger;
-
     /** The name of the processing pipeline component */
     protected String processingPipelineName;
 
@@ -77,6 +76,9 @@
     /** The ProcessingPipeline used */
     protected ProcessingPipeline processingPipeline;
 
+    /** The redirector */
+    protected Redirector redirector;
+    
     /** The Selector for the processing pipeline */
     protected ComponentSelector pipelineSelector;
 
@@ -92,9 +94,7 @@
      * Determines if the Pipeline been set for this context 
      */
     public boolean pipelineIsSet() {
-	if (this.processingPipeline != null)
-		return true;
-	return false;
+	    return (this.processingPipeline != null);
     }
 
     /**
@@ -105,15 +105,6 @@
     }
 
     /**
-     * Provide component with a logger.
-     *
-     * @param logger the logger
-     */
-    public void enableLogging(Logger logger) {
-        this.logger = logger;
-    }
-
-    /**
      * Composable Interface
      */
     public void compose(ComponentManager manager) throws ComponentException {
@@ -202,7 +193,7 @@
     public final void pushMap(String anchorName, Map map) {
         mapStack.add(map);
 
-        if (this.logger.isDebugEnabled()) {
+        if (this.getLogger().isDebugEnabled()) {
             dumpParameters();
         }
 
@@ -212,8 +203,8 @@
                 mapToName.put(map,anchorName);
             }
             else {
-                if (this.logger.isErrorEnabled()) {
-                    this.logger.error("name [" + anchorName + "] clashes");
+                if (this.getLogger().isErrorEnabled()) {
+                    this.getLogger().error("name [" + anchorName + "] clashes");
                 }
             }
         }
@@ -222,8 +213,7 @@
     /**
      * Dumps all sitemap parameters to log
      */
-    protected void dumpParameters()
-    {
+    protected void dumpParameters() {
         if (!mapStack.isEmpty()) {
             StringBuffer sb = new StringBuffer();
 
@@ -248,7 +238,7 @@
                 path = "../" + path;
             }
 
-            this.logger.debug(sb.toString());
+            this.getLogger().debug(sb.toString());
         }
 
     }
@@ -262,6 +252,24 @@
         Object name = mapToName.get(map);
         mapToName.remove(map);
         nameToMap.remove(name);
+    }
+    
+    /**
+     * Set the redirector to be used by nodes that need it.
+     * 
+     * @param redirector the redirector
+     */
+    public void setRedirector(Redirector redirector) {
+        this.redirector = redirector;
+    }
+    
+    /**
+     * Get the redirector to be used by nodes that need it.
+     * 
+     * @return the redirector
+     */
+    public Redirector getRedirector() {
+        return this.redirector;
     }
     
     /**

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/ProcessingNode.java
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/ProcessingNode.java	(original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/ProcessingNode.java	Sun Aug 29 09:29:31 2004
@@ -22,7 +22,7 @@
 /**
  *
  * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
- * @version CVS $Id: ProcessingNode.java,v 1.2 2004/03/05 13:02:51 bdelacretaz Exp $
+ * @version CVS $Id$
  */
 
 public interface ProcessingNode extends ThreadSafe {

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/TreeBuilder.java
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/TreeBuilder.java	(original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/TreeBuilder.java	Sun Aug 29 09:29:31 2004
@@ -26,14 +26,14 @@
 /**
  *
  * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
- * @version CVS $Id: TreeBuilder.java,v 1.4 2004/03/05 13:02:51 bdelacretaz Exp $
+ * @version CVS $Id$
  */
 
 public interface TreeBuilder extends Component {
 
-    void setProcessor(TreeProcessor processor);
+    void setProcessor(ConcreteTreeProcessor processor);
 
-    TreeProcessor getProcessor();
+    ConcreteTreeProcessor getProcessor();
 
     /**
      * Returns the language that is being built (e.g. "sitemap").

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java	(original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java	Sun Aug 29 09:29:31 2004
@@ -15,11 +15,6 @@
  */
 package org.apache.cocoon.components.treeprocessor;
 
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 
 import org.apache.avalon.excalibur.component.RoleManageable;
@@ -33,26 +28,20 @@
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.ConfigurationException;
 import org.apache.avalon.framework.configuration.SAXConfigurationHandler;
+import org.apache.avalon.framework.container.ContainerUtil;
 import org.apache.avalon.framework.context.Context;
 import org.apache.avalon.framework.context.ContextException;
 import org.apache.avalon.framework.context.Contextualizable;
 import org.apache.avalon.framework.logger.AbstractLogEnabled;
-import org.apache.avalon.framework.logger.Logger;
 import org.apache.avalon.framework.thread.ThreadSafe;
-import org.apache.cocoon.ProcessingException;
 import org.apache.cocoon.Processor;
-import org.apache.cocoon.components.ChainedConfiguration;
 import org.apache.cocoon.components.CocoonComponentManager;
 import org.apache.cocoon.components.ExtendedComponentSelector;
 import org.apache.cocoon.components.LifecycleHelper;
 import org.apache.cocoon.components.pipeline.ProcessingPipeline;
 import org.apache.cocoon.components.source.SourceUtil;
 import org.apache.cocoon.components.source.impl.DelayedRefreshSourceWrapper;
-import org.apache.cocoon.components.treeprocessor.sitemap.PipelinesNode;
 import org.apache.cocoon.environment.Environment;
-import org.apache.cocoon.environment.ForwardRedirector;
-import org.apache.cocoon.environment.wrapper.EnvironmentWrapper;
-import org.apache.cocoon.environment.wrapper.MutableEnvironmentFacade;
 import org.apache.excalibur.source.Source;
 import org.apache.excalibur.source.SourceResolver;
 
@@ -73,7 +62,6 @@
                Contextualizable,
                Disposable {
 
-    public static final String REDIRECTOR_ATTR = "sitemap:redirector";
     public static final String COCOON_REDIRECT_ATTR = "sitemap:cocoon-redirect";
 
     private static final String XCONF_URL =
@@ -91,18 +79,9 @@
     /** The role manager */
     protected RoleManager roleManager;
 
-    /** The language used by this processor */
-    protected String language;
-
     /** Selector of TreeBuilders, the hint is the language name */
     protected ExtendedComponentSelector builderSelector;
 
-    /** The root node of the processing tree */
-    protected ProcessingNode rootNode;
-
-    /** The list of processing nodes that should be disposed when disposing this processor */
-    protected List disposableNodes;
-
     /** Last modification time */
     protected long lastModified = 0;
 
@@ -121,25 +100,16 @@
     /** Check for reload? */
     protected boolean checkReload;
 
-    /** The component configurations from the sitemap (if any) */
-    protected Configuration componentConfigurations;
-    
-    /** The different sitemap component configurations */
-    protected Map sitemapComponentConfigurations;
-    
-    /** The component manager for the sitemap */
-    protected ComponentManager sitemapComponentManager;
-    
     /** The source resolver */
     protected SourceResolver resolver;
     
+    /** The actual processor (package-private as needs to be accessed by ConcreteTreeProcessor) */
+    ConcreteTreeProcessor concreteProcessor;
+
     /**
      * Create a TreeProcessor.
      */
     public TreeProcessor() {
-        // Language can be overriden in the configuration.
-        this.language = "sitemap";
-
         this.checkReload = true;
         this.lastModifiedDelay = 1000;
     }
@@ -147,9 +117,8 @@
     /**
      * Create a child processor for a given language
      */
-    protected TreeProcessor(TreeProcessor parent, ComponentManager manager, String language) {
+    protected TreeProcessor(TreeProcessor parent, ComponentManager manager) {
         this.parent = parent;
-        this.language = (language == null) ? parent.language : language;
 
         // Copy all that can be copied from the parent
         this.enableLogging(parent.getLogger());
@@ -161,26 +130,22 @@
 
         // We have our own CM
         this.manager = manager;
-        
-        // Other fields are setup in initialize()
     }
 
     /**
      * Create a new child of this processor (used for mounting submaps).
      *
      * @param manager the component manager to be used by the child processor.
-     * @param language the language to be used by the child processor.
      * @return a new child processor.
      */
     public TreeProcessor createChildProcessor(
         ComponentManager manager,
-        String language,
         Source source)
-      throws Exception {
+    throws Exception {
 
         // Note: lifecycle methods aren't called, since this constructors copies all
         // that can be copied from the parent (see above)
-        TreeProcessor child = new TreeProcessor(this, manager, language);
+        TreeProcessor child = new TreeProcessor(this, manager);
         child.source = new DelayedRefreshSourceWrapper(source, lastModifiedDelay);
         return child;
     }
@@ -202,7 +167,6 @@
 /*
   <processor>
     <reload delay="10"/>
-    <root-language name="sitemap"/>
     <language>...</language>
   </processor>
 */
@@ -211,11 +175,6 @@
         this.fileName = config.getAttribute("file", null);
         this.checkReload = config.getAttributeAsBoolean("check-reload", true);
 
-        Configuration rootLangConfig = config.getChild("root-language", false);
-        if (rootLangConfig != null) {
-            this.language = rootLangConfig.getAttribute("name");
-        }
-
         // Obtain the configuration file, or use the XCONF_URL if none
         // is defined
         String xconfURL = config.getAttribute("config", XCONF_URL);
@@ -237,8 +196,6 @@
         } catch(Exception e) {
             String msg = "Error while reading " + xconfURL + ": " + e.getMessage();
             throw new ConfigurationException(msg, e);
-        } finally {
-            this.manager.release( resolver );
         }
 
         // Create a selector for tree builders of all languages
@@ -269,15 +226,10 @@
      *         ConnectionResetException  If the connection was reset
      */
     public boolean process(Environment environment) throws Exception {
-        InvokeContext context = new InvokeContext();
-
-        context.enableLogging(getLogger());
-
-        try {
-            return process(environment, context);
-        } finally {
-            context.dispose();
-        }
+    	
+        this.setupConcreteProcessor(environment);
+    		
+        return this.concreteProcessor.process(environment);
     }
 
     /**
@@ -287,113 +239,14 @@
      */
     public ProcessingPipeline buildPipeline(Environment environment)
     throws Exception {
-        InvokeContext context = new InvokeContext( true );
-
-        context.enableLogging(getLogger());
-
-        try {
-            if ( process(environment, context) ) {
-                return context.getProcessingPipeline();
-            } else {
-                return null;
-            }
-        } finally {
-            context.dispose();
-        }
-    }
-
-    /**
-     * Do the actual processing, be it producing the response or just building the pipeline
-     * @param environment
-     * @param context
-     * @return true if the pipeline was successfully built, false otherwise.
-     * @throws Exception
-     */
-    protected boolean process(Environment environment, InvokeContext context)
-    throws Exception {
-
-        // first, check for sitemap changes
-        if (this.rootNode == null ||
-            (this.checkReload && this.source.getLastModified() > this.lastModified)) {
-            setupRootNode(environment);
-        }
-
-        // and now process
-        CocoonComponentManager.enterEnvironment(environment, this.sitemapComponentManager, this);
-
-        Map objectModel = environment.getObjectModel();
-
-        Object oldResolver = objectModel.get(ProcessingNode.OBJECT_SOURCE_RESOLVER);
-        Object oldRedirector = environment.getAttribute(REDIRECTOR_ATTR);
-
-        // Build a redirector
-        TreeProcessorRedirector redirector = new TreeProcessorRedirector(environment, context);
-        setupLogger(redirector);
-
-        objectModel.put(ProcessingNode.OBJECT_SOURCE_RESOLVER, environment);
-        environment.setAttribute(REDIRECTOR_ATTR, redirector);
-        try {
-            boolean success = this.rootNode.invoke(environment, context);
-            
-            return success;
-
-        } finally {
-            CocoonComponentManager.leaveEnvironment();
-            // Restore old redirector and resolver
-            environment.setAttribute(REDIRECTOR_ATTR, oldRedirector);
-            objectModel.put(PipelinesNode.OBJECT_SOURCE_RESOLVER, oldResolver);
-        }
-    }
-        
-    private boolean handleCocoonRedirect(String uri, Environment environment, InvokeContext context) throws Exception {
-        
-        // Build an environment wrapper
-        // If the current env is a facade, change the delegate and continue processing the facade, since
-        // we may have other redirects that will in turn also change the facade delegate
-        
-        MutableEnvironmentFacade facade = environment instanceof MutableEnvironmentFacade ?
-            ((MutableEnvironmentFacade)environment) : null;
-        
-        if (facade != null) {
-            // Consider the facade delegate (the real environment)
-            environment = facade.getDelegate();
-        }
-        
-        // test if this is a call from flow
-        boolean isRedirect = (environment.getObjectModel().remove("cocoon:forward") == null);
-        Environment newEnv = new ForwardEnvironmentWrapper(environment, this.manager, uri, getLogger());
-        if ( isRedirect ) {
-            ((ForwardEnvironmentWrapper)newEnv).setInternalRedirect(true);
-        }
-        
-        if (facade != null) {
-            // Change the facade delegate
-            facade.setDelegate((EnvironmentWrapper)newEnv);
-            newEnv = facade;
-        }
-        
-        // Get the processor that should process this request
-        TreeProcessor processor;
-        if (newEnv.getRootContext() == newEnv.getContext()) {
-            processor = (TreeProcessor)getRootProcessor();
-        } else {
-            processor = this;
-        }
-        
-        // Process the redirect
-// No more reset since with TreeProcessorRedirector, we need to pop values from the redirect location
-//        context.reset();
-        // The following is a fix for bug #26854 and #26571
-        final boolean result = processor.process(newEnv, context);
-        if ( ((ForwardEnvironmentWrapper)newEnv).getRedirectURL() != null ) {
-            environment.redirect( false, ((ForwardEnvironmentWrapper)newEnv).getRedirectURL() );
-        }
-        return result;
-    }
-    
-    /**
-     * Get the root parent of this processor
-     * @since 2.1.1
+    	
+    		setupConcreteProcessor(environment);
+    		
+    		return this.concreteProcessor.buildPipeline(environment);
+    }
+      
+    /* (non-Javadoc)
+     * @see org.apache.cocoon.Processor#getRootProcessor()
      */
     public Processor getRootProcessor() {
         TreeProcessor result = this;
@@ -408,79 +261,47 @@
      * Set the sitemap component configurations
      */
     public void setComponentConfigurations(Configuration componentConfigurations) {
-        this.componentConfigurations = componentConfigurations;
-        this.sitemapComponentConfigurations = null;
+        this.concreteProcessor.setComponentConfigurations(componentConfigurations);
     }
 
-    /**
-     * Get the sitemap component configurations
-     * @since 2.1
+    /* (non-Javadoc)
+     * @see org.apache.cocoon.Processor#getComponentConfigurations()
      */
     public Map getComponentConfigurations() {
-        // do we have the sitemap configurations prepared for this processor?
-        if ( null == this.sitemapComponentConfigurations ) {
-            
-            synchronized (this) {
+        return this.concreteProcessor.getComponentConfigurations();
+    }
 
-                if ( this.sitemapComponentConfigurations == null ) {
-                    // do we have configurations?
-                    final Configuration[] childs = (this.componentConfigurations == null 
-                                                     ? null 
-                                                     : this.componentConfigurations.getChildren());
-                    
-                    if ( null != childs ) {
-        
-                        if ( null == this.parent ) {
-                            this.sitemapComponentConfigurations = new HashMap(12);
-                        } else {
-                            // copy all configurations from parent
-                            this.sitemapComponentConfigurations = new HashMap(this.parent.getComponentConfigurations()); 
-                        }
-                        
-                        // and now check for new configurations
-                        for(int m = 0; m < childs.length; m++) {
-                            
-                            final String r = this.roleManager.getRoleForName(childs[m].getName());
-                            this.sitemapComponentConfigurations.put(r, new ChainedConfiguration(childs[m], 
-                                                                             (ChainedConfiguration)this.sitemapComponentConfigurations.get(r)));
-                        }
-                    } else {
-                        // we don't have configurations
-                        if ( null == this.parent ) {
-                            this.sitemapComponentConfigurations = Collections.EMPTY_MAP;
-                        } else {
-                            // use configuration from parent
-                            this.sitemapComponentConfigurations = this.parent.getComponentConfigurations(); 
-                        }
-                    }
-                }
-            }
+    private void setupConcreteProcessor(Environment env) throws Exception {
+        // first, check for sitemap changes
+        if (this.concreteProcessor == null ||
+            (this.checkReload && this.source.getLastModified() != this.lastModified)) {
+            buildConcreteProcessor(env);
         }
-        return this.sitemapComponentConfigurations;
     }
-
-    protected synchronized void setupRootNode(Environment env) throws Exception {
+    
+    private synchronized void buildConcreteProcessor(Environment env) throws Exception {
 
         // Now that we entered the synchronized area, recheck what's already
         // been checked in process().
-        if (this.rootNode != null && source.getLastModified() <= this.lastModified) {
+        if (this.concreteProcessor != null && source.getLastModified() == this.lastModified) {
             // Nothing changed
             return;
         }
 
         long startTime = System.currentTimeMillis();
 
-        // Dispose the previous tree, if any
-        disposeTree();
-
         // Get a builder
-        TreeBuilder builder = (TreeBuilder)this.builderSelector.select(this.language);
-        ProcessingNode root;
+        TreeBuilder builder = (TreeBuilder)this.builderSelector.select("sitemap");
+        ConcreteTreeProcessor newProcessor = new ConcreteTreeProcessor(this);
+        long newLastModified;
+        this.setupLogger(newProcessor);
+        //FIXME (SW): why do we need to enterProcessor here?
+        CocoonComponentManager.enterEnvironment(env, this.manager, this);
         try {
             if (builder instanceof Recomposable) {
                 ((Recomposable)builder).recompose(this.manager);
             }
-            builder.setProcessor(this);
+            builder.setProcessor(newProcessor);
             if (this.fileName == null) {
                 this.fileName = builder.getFileName();
             }
@@ -488,114 +309,57 @@
             if (this.source == null) {
                 this.source = new DelayedRefreshSourceWrapper(this.resolver.resolveURI(this.fileName), lastModifiedDelay);
             }
-            root = builder.build(this.source);
-
-            this.sitemapComponentManager = builder.getSitemapComponentManager();
             
-            this.disposableNodes = builder.getDisposableNodes();
+            newLastModified = this.source.getLastModified();
+
+            ProcessingNode root = builder.build(this.source);
+
+            newProcessor.setProcessorData(builder.getSitemapComponentManager(), root, builder.getDisposableNodes());
         } finally {
+            CocoonComponentManager.leaveEnvironment();
             this.builderSelector.release(builder);
         }
 
-        this.lastModified = System.currentTimeMillis();
-
         if (getLogger().isDebugEnabled()) {
             double time = (this.lastModified - startTime) / 1000.0;
             getLogger().debug("TreeProcessor built in " + time + " secs from " + source.getURI());
         }
 
-        // Finished
-        this.rootNode = root;
-    }
+        // Switch to the new processor (ensure it's never temporarily null)
+        ConcreteTreeProcessor oldProcessor = this.concreteProcessor;
 
-    public void dispose() {
-        disposeTree();
-        if (this.parent == null) {
-            // root processor : dispose the builder selector
-            this.builderSelector.dispose();
-        }
-        if ( this.manager != null ) {
-            if ( this.source != null ) {
-                this.resolver.release(this.source.getSource());
-                this.source = null;
-            }
-            this.manager.release(this.resolver);
-            this.resolver = null;
-            this.manager = null;
-        }
-    }
+        this.concreteProcessor = newProcessor;
+        this.lastModified = newLastModified;
 
-    /**
-     * Dispose all nodes in the tree that are disposable
-     */
-    protected void disposeTree() {
-        if (this.disposableNodes != null) {
-            // we must dispose the nodes in reverse order
-            // otherwise selector nodes are freed before the components node
-            for(int i=this.disposableNodes.size()-1; i>-1; i--) {
-                ((Disposable)disposableNodes.get(i)).dispose();
-            }
-            this.disposableNodes = null;
+        // Dispose the old processor, if any
+        if (oldProcessor != null) {
+            oldProcessor.markForDisposal();
         }
     }
-    
-    private class TreeProcessorRedirector extends ForwardRedirector {
-        
-        private InvokeContext context;
-        public TreeProcessorRedirector(Environment env, InvokeContext context) {
-            super(env);
-            this.context = context;
-        }
-        
-        protected void cocoonRedirect(String uri) throws IOException, ProcessingException {
-            try {
-                TreeProcessor.this.handleCocoonRedirect(uri, this.env, this.context);
-            } catch(IOException ioe) {
-                throw ioe;
-            } catch(ProcessingException pe) {
-                throw pe;
-            } catch(RuntimeException re) {
-                throw re;
-            } catch(Exception ex) {
-                throw new ProcessingException(ex);
-            }
-        }
-    }
-    
-    /**
-     * Local extension of EnvironmentWrapper to propagate otherwise blocked
-     * methods to the actual environment.
-     */
-    private static final class ForwardEnvironmentWrapper extends EnvironmentWrapper {
-
-        public ForwardEnvironmentWrapper(Environment env,
-            ComponentManager manager, String uri, Logger logger) throws MalformedURLException {
-            super(env, manager, uri, logger);
-        }
-
-        public void setStatus(int statusCode) {
-            environment.setStatus(statusCode);
-        }
 
-        public void setContentLength(int length) {
-            environment.setContentLength(length);
-        }
-
-        public void setContentType(String contentType) {
-            environment.setContentType(contentType);
-        }
-
-        public String getContentType() {
-            return environment.getContentType();
-        }
+    /* (non-Javadoc)
+     * @see org.apache.avalon.framework.activity.Disposable#dispose()
+     */
+    public void dispose() {
+        // Dispose the concrete processor. No need to check for existing requests, as there
+        // are none when a TreeProcessor is disposed.
+        ContainerUtil.dispose(this.concreteProcessor);
+        this.concreteProcessor = null;
 
-        public boolean isResponseModified(long lastModified) {
-            return environment.isResponseModified(lastModified);
-        }
-        
-        public void setResponseIsNotModified() {
-            environment.setResponseIsNotModified();
-        }
-    }
+        if ( this.manager != null ) {
+	        if ( this.source != null ) {
+	            this.resolver.release(this.source.getSource());
+	            this.source = null;
+	        }
+            if (this.parent == null) {
+                // root processor : dispose the builder selector
+                this.builderSelector.dispose();
+                this.builderSelector = null;
 
+                this.manager.release(this.resolver);
+                this.resolver = null;
+            }
+            this.manager = null;
+	    }
+	}
 }

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ActSetNode.java
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ActSetNode.java	(original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ActSetNode.java	Sun Aug 29 09:29:31 2004
@@ -28,7 +28,7 @@
  * Handles &lt;map:act type="..."&gt; (action-sets calls are handled by {@link ActSetNode}).
  *
  * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
- * @version CVS $Id: ActSetNode.java,v 1.2 2004/03/05 13:02:51 bdelacretaz Exp $
+ * @version CVS $Id$
  */
 
 public class ActSetNode extends SimpleParentProcessingNode
@@ -62,7 +62,7 @@
 
         Map result = this.actionSet.call(env, context, resolvedParams);
 
-        if (PipelinesNode.getRedirector(env).hasRedirected()) {
+        if (context.getRedirector().hasRedirected()) {
             return true;
 
         } else if (result == null) {

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ActTypeNode.java
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ActTypeNode.java	(original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ActTypeNode.java	Sun Aug 29 09:29:31 2004
@@ -25,6 +25,7 @@
 import org.apache.avalon.framework.component.Composable;
 import org.apache.avalon.framework.parameters.Parameters;
 import org.apache.cocoon.acting.Action;
+import org.apache.cocoon.components.CocoonComponentManager;
 import org.apache.cocoon.components.treeprocessor.InvokeContext;
 import org.apache.cocoon.components.treeprocessor.ParameterizableProcessingNode;
 import org.apache.cocoon.components.treeprocessor.SimpleSelectorProcessingNode;
@@ -38,7 +39,7 @@
  * Handles &lt;map:act type="..."&gt; (action-sets calls are handled by {@link ActSetNode}).
  *
  * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
- * @version CVS $Id: ActTypeNode.java,v 1.5 2004/03/05 13:02:51 bdelacretaz Exp $
+ * @version CVS $Id$
  */
 
 public class ActTypeNode extends SimpleSelectorProcessingNode
@@ -88,7 +89,7 @@
 
         // Prepare data needed by the action
         Map objectModel = env.getObjectModel();
-        Redirector redirector = PipelinesNode.getRedirector(env);
+        Redirector redirector = context.getRedirector();
         SourceResolver resolver = getSourceResolver(objectModel);
         String resolvedSource = source.resolve(context, objectModel);
         Parameters resolvedParams =

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/CallFunctionNode.java
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/CallFunctionNode.java	(original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/CallFunctionNode.java	Sun Aug 29 09:29:31 2004
@@ -41,7 +41,7 @@
  *
  * @author <a href="mailto:ovidiu@apache.org">Ovidiu Predescu</a>
  * @since March 13, 2002
- * @version CVS $Id: CallFunctionNode.java,v 1.9 2004/03/05 13:02:51 bdelacretaz Exp $
+ * @version CVS $Id$
  */
 public class CallFunctionNode extends AbstractProcessingNode implements Configurable, Composable {
     protected List parameters;
@@ -117,7 +117,7 @@
         // If the continuation id is not null, it takes precedence over
         // the function call, so we invoke it here.
         if (continuation != null && continuation.length() > 0) {
-            interpreter.handleContinuation(continuation, params, PipelinesNode.getRedirector(env));
+            interpreter.handleContinuation(continuation, params, context.getRedirector());
             return true;
         }
 
@@ -127,7 +127,7 @@
         String name = functionName.resolve(context, env.getObjectModel());
 
         if (name != null && name.length() > 0) {
-            interpreter.callFunction(name, params, PipelinesNode.getRedirector(env));
+            interpreter.callFunction(name, params, context.getRedirector());
             return true;
         }
         

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ContinueNode.java
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ContinueNode.java	(original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ContinueNode.java	Sun Aug 29 09:29:31 2004
@@ -38,7 +38,7 @@
  *
  * @author <a href="mailto:ovidiu@apache.org">Ovidiu Predescu</a>
  * @since March 25, 2002
- * @version CVS $Id: ContinueNode.java,v 1.5 2004/03/05 13:02:51 bdelacretaz Exp $
+ * @version CVS $Id$
  */
 public class ContinueNode
         extends AbstractProcessingNode
@@ -111,7 +111,7 @@
         Interpreter interpreter = (Interpreter)selector.select(language);
 
         try {
-            interpreter.handleContinuation(contId, params, PipelinesNode.getRedirector(env));
+            interpreter.handleContinuation(contId, params, context.getRedirector());
         } finally {
             selector.release((Component)interpreter);
         }

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ContinueNodeBuilder.java
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ContinueNodeBuilder.java	(original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ContinueNodeBuilder.java	Sun Aug 29 09:29:31 2004
@@ -26,7 +26,7 @@
  *
  * @author <a href="mailto:ovidiu@apache.org">Ovidiu Predescu</a>
  * @since March 25, 2002
- * @version CVS $Id: ContinueNodeBuilder.java,v 1.3 2004/03/05 13:02:52 bdelacretaz Exp $
+ * @version CVS $Id$
  */
 public class ContinueNodeBuilder extends AbstractProcessingNodeBuilder
 {
@@ -39,8 +39,8 @@
 
     this.node = new ContinueNode(contId);
     this.treeBuilder.setupNode(this.node, config);
-    if (node instanceof Configurable)
-      ((Configurable)this.node).configure(config);
+
+    this.node.configure(config);
 
     return this.node;
   }

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/FlowNode.java
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/FlowNode.java	(original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/FlowNode.java	Sun Aug 29 09:29:31 2004
@@ -15,6 +15,8 @@
  */
 package org.apache.cocoon.components.treeprocessor.sitemap;
 
+import org.apache.avalon.framework.activity.Disposable;
+import org.apache.avalon.framework.component.Component;
 import org.apache.avalon.framework.component.ComponentException;
 import org.apache.avalon.framework.component.ComponentManager;
 import org.apache.avalon.framework.component.ComponentSelector;
@@ -33,16 +35,17 @@
  *
  * @author <a href="mailto:ovidiu@apache.org">Ovidiu Predescu</a>
  * @since September 13, 2002
- * @version CVS $Id: FlowNode.java,v 1.4 2004/03/05 13:02:52 bdelacretaz Exp $
+ * @version CVS $Id$
  */
 public class FlowNode extends AbstractProcessingNode
-        implements Composable, Contextualizable {
+        implements Composable, Contextualizable, Disposable {
 
     ComponentManager manager;
     String language;
     Context context;
     Interpreter interpreter;
-
+    ComponentSelector selector;
+    
     public FlowNode(String language) {
         this.language = language;
     }
@@ -79,9 +82,9 @@
         this.manager = manager;
 
         try {
-            ComponentSelector selector = (ComponentSelector)manager.lookup(Interpreter.ROLE);
+            this.selector = (ComponentSelector)manager.lookup(Interpreter.ROLE);
             // Obtain the Interpreter instance for this language
-            interpreter = (Interpreter)selector.select(language);
+            this.interpreter = (Interpreter)selector.select(language);
         } catch (Exception ex) {
             throw new ComponentException(language,
                 "ScriptNode: Couldn't obtain a flow interpreter for " + language + ": " + ex);
@@ -90,5 +93,21 @@
 
     public Interpreter getInterpreter() {
         return interpreter;
+    }
+    
+    
+    /* (non-Javadoc)
+     * @see org.apache.avalon.framework.activity.Disposable#dispose()
+     */
+    public void dispose() {
+        if ( this.manager != null ) {
+            if ( this.selector != null ) {
+                this.selector.release( (Component)this.interpreter );
+                this.interpreter = null;
+            }
+            this.manager.release( this.selector );
+            this.selector = null;
+            this.manager = null;
+        }
     }
 }

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/MountNode.java
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/MountNode.java	(original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/MountNode.java	Sun Aug 29 09:29:31 2004
@@ -19,6 +19,7 @@
 import java.util.Iterator;
 import java.util.Map;
 
+import org.apache.avalon.framework.activity.Disposable;
 import org.apache.avalon.framework.component.ComponentException;
 import org.apache.avalon.framework.component.ComponentManager;
 import org.apache.avalon.framework.component.Composable;
@@ -36,33 +37,36 @@
  *
  * @author <a href="mailto:bluetkemeier@s-und-n.de">Bj&ouml;rn L&uuml;tkemeier</a>
  * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
- * @version CVS $Id: MountNode.java,v 1.12 2004/03/10 14:18:01 stephan Exp $
+ * @version CVS $Id$
  */
-public class MountNode extends AbstractProcessingNode implements Composable {
+public class MountNode extends AbstractProcessingNode implements Composable, Disposable {
 
     /** The 'uri-prefix' attribute */
-    private VariableResolver prefix;
+    private final VariableResolver prefix;
 
     /** The 'src' attribute */
-    private VariableResolver source;
+    private final VariableResolver source;
 
     /** Processors for sources */
     private Map processors = new HashMap();
 
     /** The processor for this node */
-    private TreeProcessor parentProcessor;
-
-    /** The language for the mounted processor */
-    private String language;
+    private final TreeProcessor parentProcessor;
 
+    /** The value of the 'check-reload' attribute */
+    private final boolean checkReload;
+   
     /** The component manager to be used by the mounted processor */
     private ComponentManager manager;
 
-    public MountNode(VariableResolver prefix, VariableResolver source, String language, TreeProcessor parentProcessor) {
+    public MountNode(VariableResolver prefix, 
+                     VariableResolver source, 
+                     TreeProcessor parentProcessor,
+                     boolean checkReload) {
         this.prefix = prefix;
         this.source = source;
-        this.language = language;
         this.parentProcessor = parentProcessor;
+        this.checkReload = checkReload;
     }
 
     public void compose(ComponentManager manager) throws ComponentException {
@@ -77,10 +81,10 @@
         String resolvedSource = this.source.resolve(context, objectModel);
         String resolvedPrefix = this.prefix.resolve(context, objectModel);
 
-        if (resolvedSource.length()==0)
+        if (resolvedSource.length()==0) {
             throw new ProcessingException("Source of mount statement is empty"); 
-
-        TreeProcessor processor = getProcessor(resolvedSource);
+        }
+        TreeProcessor processor = getProcessor(resolvedSource, resolvedPrefix);
 
         String oldPrefix = env.getURIPrefix();
         String oldURI    = env.getURI();
@@ -113,7 +117,7 @@
         }
     }
 
-    private synchronized TreeProcessor getProcessor(String source) throws Exception {
+    private synchronized TreeProcessor getProcessor(String source, String prefix) throws Exception {
 
         TreeProcessor processor = (TreeProcessor)processors.get(source);
 
@@ -130,7 +134,7 @@
             try {
                 Source src = resolver.resolveURI(actualSource);
                 try {
-                    processor = this.parentProcessor.createChildProcessor(this.manager, this.language, src);
+                    processor = this.parentProcessor.createChildProcessor(this.manager, src);
                 } finally {
                     resolver.release(src);
                 }
@@ -145,6 +149,9 @@
         return processor;
     }
 
+    /**
+     * 
+     */
     public void dispose() {
         Iterator iter = this.processors.values().iterator();
         while(iter.hasNext()) {

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/MountNodeBuilder.java
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/MountNodeBuilder.java	(original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/MountNodeBuilder.java	Sun Aug 29 09:29:31 2004
@@ -24,7 +24,7 @@
 /**
  *
  * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
- * @version CVS $Id: MountNodeBuilder.java,v 1.2 2004/03/05 13:02:52 bdelacretaz Exp $
+ * @version CVS $Id$
  */
 
 public class MountNodeBuilder extends AbstractProcessingNodeBuilder implements ThreadSafe {
@@ -39,8 +39,8 @@
         MountNode node = new MountNode(
             VariableResolverFactory.getResolver(config.getAttribute("uri-prefix"), manager),
             VariableResolverFactory.getResolver(config.getAttribute("src"), manager),
-            config.getAttribute("language", null),
-            this.treeBuilder.getProcessor()
+            this.treeBuilder.getProcessor().getWrappingProcessor(),
+            config.getAttributeAsBoolean("check-reload", true)
         );
         return (this.treeBuilder.setupNode(node, config));
     }

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/PipelinesNode.java
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/PipelinesNode.java	(original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/PipelinesNode.java	Sun Aug 29 09:29:31 2004
@@ -33,7 +33,7 @@
  * @author <a href="mailto:bluetkemeier@s-und-n.de">Bj&ouml;rn L&uuml;tkemeier</a>
  * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
  * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
- * @version CVS $Id: PipelinesNode.java,v 1.9 2004/03/05 13:02:52 bdelacretaz Exp $
+ * @version CVS $Id$
  */
 
 public final class PipelinesNode extends SimpleParentProcessingNode
@@ -74,10 +74,6 @@
         ((PipelineNode)nodes[nodes.length - 1]).setLast(true);
 
         super.setChildren(nodes);
-    }
-
-    public static Redirector getRedirector(Environment env) {
-        return (Redirector)env.getAttribute(TreeProcessor.REDIRECTOR_ATTR);
     }
 
     /**

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/RedirectToURINode.java
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/RedirectToURINode.java	(original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/RedirectToURINode.java	Sun Aug 29 09:29:31 2004
@@ -26,7 +26,7 @@
 /**
  *
  * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
- * @version CVS $Id: RedirectToURINode.java,v 1.5 2004/03/05 13:02:52 bdelacretaz Exp $
+ * @version CVS $Id$
  */
 
 public class RedirectToURINode extends AbstractProcessingNode {
@@ -59,7 +59,7 @@
             getLogger().info("Redirecting to '" + resolvedURI + "' at " + this.getLocation());
         }
 
-        final Redirector redirector = PipelinesNode.getRedirector(env);
+        final Redirector redirector = context.getRedirector();
 
         if( this.global ) {
             redirector.globalRedirect(this.createSession, resolvedURI);

Modified: cocoon/branches/BRANCH_2_1_X/status.xml
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/status.xml	(original)
+++ cocoon/branches/BRANCH_2_1_X/status.xml	Sun Aug 29 09:29:31 2004
@@ -252,7 +252,8 @@
      Updated Apache Ant to 1.6.2.
    </action>
    <action dev="CZ" type="fix">
-     Mail block: The mail transformer ignored configured toAddresses from a pipeline parameter. This is fixed now.
+     Mail block: The mail transformer ignored configured toAddresses from a
+     pipeline parameter. This is fixed now.
    </action>
    <action dev="TC" type="add" fixes-bug="29935" due-to="Leszek Gawron" due-to-email="ouzo@wlkp.org">
      Added support for stripping root elements in the CIncludeTransformer.
@@ -275,6 +276,9 @@
    <action dev="CZ" type="add">
      Add configuration support for log4j.
    </action>
+   <action dev="CZ" type="fix" fixes-bug="27066">
+     Apply patch to fix some memory leaks in the tree processor.
+   </action>
    <action dev="CZ" type="fix" fixes-bug="29373">
      Portal: Fix NPE when non-caching pipelines are used for the portal profile.
    </action>
@@ -283,6 +287,11 @@
    </action>
    <action dev="CZ" type="fix" fixes-bug="28687">
      Portal: Fix problem with bookmarks and CachingURICoplet
+   </action>
+   <action dev="SW" type="fix" fixes-bug="27249">
+     Refactor TreeProcessor to avoid constant reloading of sitemap if its
+     modification date is in the future and occasional ECM-related exceptions
+     when a sitemap is reloaded.
    </action>
    <action dev="VG" type="add">
      Added instrumentation support to ContinuationsManager.

Mime
View raw message