cocoon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sylv...@apache.org
Subject cvs commit: cocoon-2.1/src/java/org/apache/cocoon/components/treeprocessor/sitemap MountNodeBuilder.java
Date Sat, 05 Jun 2004 08:18:50 GMT
sylvain     2004/06/05 01:18:50

  Modified:    .        status.xml
               src/java/org/apache/cocoon/components/treeprocessor
                        DefaultTreeBuilder.java TreeBuilder.java
                        TreeProcessor.java
               src/java/org/apache/cocoon/components/treeprocessor/sitemap
                        MountNodeBuilder.java
  Added:       src/java/org/apache/cocoon/components/treeprocessor
                        ConcreteTreeProcessor.java
  Log:
  Fix bug# 27249 : refactor TreeProcessor to avoid constant sitemap reloading if its modification
date is in the future and occasional ECM-related exceptions when a sitemap is reloaded
  
  Revision  Changes    Path
  1.352     +6 -1      cocoon-2.1/status.xml
  
  Index: status.xml
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/status.xml,v
  retrieving revision 1.351
  retrieving revision 1.352
  diff -u -r1.351 -r1.352
  --- status.xml	4 Jun 2004 09:55:16 -0000	1.351
  +++ status.xml	5 Jun 2004 08:18:50 -0000	1.352
  @@ -205,6 +205,11 @@
     <changes>
   
    <release version="@version@" date="@date@">
  +   <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="BD" type="add" due-to="Stavros Kounis" fixes-bug="28834">
        Tour block: added Java shapes sample.
      </action>
  
  
  
  1.9       +4 -4      cocoon-2.1/src/java/org/apache/cocoon/components/treeprocessor/DefaultTreeBuilder.java
  
  Index: DefaultTreeBuilder.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/java/org/apache/cocoon/components/treeprocessor/DefaultTreeBuilder.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- DefaultTreeBuilder.java	8 Mar 2004 12:07:39 -0000	1.8
  +++ DefaultTreeBuilder.java	5 Jun 2004 08:18:50 -0000	1.9
  @@ -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;
       }
   
  
  
  
  1.5       +3 -3      cocoon-2.1/src/java/org/apache/cocoon/components/treeprocessor/TreeBuilder.java
  
  Index: TreeBuilder.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/java/org/apache/cocoon/components/treeprocessor/TreeBuilder.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- TreeBuilder.java	5 Mar 2004 13:02:51 -0000	1.4
  +++ TreeBuilder.java	5 Jun 2004 08:18:50 -0000	1.5
  @@ -31,9 +31,9 @@
   
   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").
  
  
  
  1.34      +61 -287   cocoon-2.1/src/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java
  
  Index: TreeProcessor.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java,v
  retrieving revision 1.33
  retrieving revision 1.34
  diff -u -r1.33 -r1.34
  --- TreeProcessor.java	4 Jun 2004 13:35:05 -0000	1.33
  +++ TreeProcessor.java	5 Jun 2004 08:18:50 -0000	1.34
  @@ -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;
  @@ -39,12 +34,8 @@
   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.service.ServiceManager;
   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.ContextHelper;
   import org.apache.cocoon.components.ExtendedComponentSelector;
   import org.apache.cocoon.components.LifecycleHelper;
  @@ -52,11 +43,7 @@
   import org.apache.cocoon.components.source.SourceUtil;
   import org.apache.cocoon.components.source.impl.DelayedRefreshSourceWrapper;
   import org.apache.cocoon.environment.Environment;
  -import org.apache.cocoon.environment.ForwardRedirector;
  -import org.apache.cocoon.environment.Redirector;
   import org.apache.cocoon.environment.internal.EnvironmentHelper;
  -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;
   
  @@ -101,12 +88,6 @@
       /** 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;
   
  @@ -125,23 +106,14 @@
       /** 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;
  -    
  -    /** A service manager wrapper */
  -    protected ServiceManager serviceManager;
  -    
       /** The source resolver */
       protected SourceResolver resolver;
       
       /** The environment helper */
       private EnvironmentHelper environmentHelper;
  +    
  +    /** The actual processor (package-private as needs to be accessed by ConcreteTreeProcessor)
*/
  +    ConcreteTreeProcessor concreteProcessor;
   
       /**
        * Create a TreeProcessor.
  @@ -175,7 +147,7 @@
           this.lastModifiedDelay = parent.lastModifiedDelay;
           
           // We have our own CM
  -        this.manager = parent.sitemapComponentManager;
  +        this.manager = parent.concreteProcessor.sitemapComponentManager;
           this.resolver = (SourceResolver)this.manager.lookup(SourceResolver.ROLE);
           this.environmentHelper = new EnvironmentHelper(parent.environmentHelper);
           // Setup environment helper
  @@ -198,31 +170,19 @@
           return new TreeProcessor(this, delayedSource, checkReload, prefix);
       }
   
  -    /* (non-Javadoc)
  -     * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
  -     */
       public void contextualize(Context context) throws ContextException {
           this.context = context;
       }
   
  -    /* (non-Javadoc)
  -     * @see org.apache.avalon.framework.component.Composable#compose(org.apache.avalon.framework.component.ComponentManager)
  -     */
       public void compose(ComponentManager manager) throws ComponentException {
           this.manager = manager;
           this.resolver = (SourceResolver)this.manager.lookup(SourceResolver.ROLE);
       }
   
  -    /* (non-Javadoc)
  -     * @see org.apache.avalon.excalibur.component.RoleManageable#setRoleManager(org.apache.avalon.excalibur.component.RoleManager)
  -     */
       public void setRoleManager(RoleManager rm) {
           this.roleManager = rm;
       }
   
  -    /* (non-Javadoc)
  -     * @see org.apache.avalon.framework.activity.Initializable#initialize()
  -     */
       public void initialize() throws Exception {
           // setup the environment helper
           if (this.environmentHelper == null ) {
  @@ -301,95 +261,12 @@
        *         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();
  -        }
  +    	
  +    		setupConcreteProcessor(environment);
  +    		
  +    		return this.concreteProcessor.process(environment);
       }
   
  -    /**
  -     * 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
  -        EnvironmentHelper.enterProcessor(this, this.serviceManager, environment);
  -
  -        final Redirector oldRedirector = context.getRedirector();
  -
  -        // Build a redirector
  -        TreeProcessorRedirector redirector = new TreeProcessorRedirector(environment, context);
  -        setupLogger(redirector);
  -        context.setRedirector(redirector);
  -
  -        try {
  -            boolean success = this.rootNode.invoke(environment, context);
  -            
  -            return success;
  -
  -        } finally {
  -            EnvironmentHelper.leaveProcessor();
  -            // Restore old redirector 
  -            context.setRedirector(oldRedirector);
  -        }
  -    }
  -        
  -    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, 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.getURIPrefix().equals("") ) {
  -            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();
  -        return processor.process(newEnv, context);
  -    }
       
       /**
        * Process the given <code>Environment</code> to assemble
  @@ -398,19 +275,10 @@
        */
       public InternalPipelineDescription buildPipeline(Environment environment)
       throws Exception {
  -        InvokeContext context = new InvokeContext( true );
  -
  -        context.enableLogging(getLogger());
  -        context.setLastProcessor(this);
  -        try {
  -            if ( process(environment, context) ) {
  -                return context.getInternalPipelineDescription(environment);
  -            } else {
  -                return null;
  -            }
  -        } finally {
  -            context.dispose();
  -        }
  +    	
  +    		setupConcreteProcessor(environment);
  +    		
  +    		return this.concreteProcessor.buildPipeline(environment);
       }
         
       /* (non-Javadoc)
  @@ -429,54 +297,14 @@
        * Set the sitemap component configurations
        */
       public void setComponentConfigurations(Configuration componentConfigurations) {
  -        this.componentConfigurations = componentConfigurations;
  -        this.sitemapComponentConfigurations = null;
  +    		this.concreteProcessor.setComponentConfigurations(componentConfigurations);
       }
   
       /* (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) {
  -
  -                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();

  -                        }
  -                    }
  -                }
  -            }
  -        }
  -        return this.sitemapComponentConfigurations;
  +    		return this.concreteProcessor.getComponentConfigurations();
       }
   
       /* (non-Javadoc)
  @@ -497,29 +325,37 @@
           return this.environmentHelper;   
       }
   
  -    protected synchronized void setupRootNode(Environment env) throws Exception {
  +    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);
  +        }
  +    }
  +    
  +    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;
  +        ConcreteTreeProcessor newProcessor = new ConcreteTreeProcessor(this);
  +        long newLastModified;
  +        this.setupLogger(newProcessor);
  +        //FIXME (SW): why do we need to enterProcessor here?
           EnvironmentHelper.enterProcessor(this, new ComponentManagerWrapper(this.manager),
env);
           try {
               if (builder instanceof Recomposable) {
                   ((Recomposable)builder).recompose(this.manager);
               }
  -            builder.setProcessor(this);
  +            builder.setProcessor(newProcessor);
               if (this.fileName == null) {
                   this.fileName = builder.getFileName();
               }
  @@ -527,116 +363,54 @@
               if (this.source == null) {
                   this.source = new DelayedRefreshSourceWrapper(this.resolver.resolveURI(this.fileName),
lastModifiedDelay);
               }
  -            root = builder.build(this.source);
  -
  -            this.sitemapComponentManager = builder.getSitemapComponentManager();
  -            this.serviceManager = new ComponentManagerWrapper(this.sitemapComponentManager);
               
  -            this.disposableNodes = builder.getDisposableNodes();
  +            newLastModified = this.source.getLastModified();
  +
  +            ProcessingNode root = builder.build(this.source);
  +
  +            newProcessor.setProcessorData(builder.getSitemapComponentManager(), root, builder.getDisposableNodes());
           } finally {
               EnvironmentHelper.leaveProcessor();
               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,
  -            String uri, Logger logger) throws MalformedURLException {
  -            super(env, 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();
  +    public void dispose() {
  +        // Dispose the concrete processor. No need to check for existing requests, as there
  +        // are none when a TreeProcessor is disposed.
  +        if (this.concreteProcessor != null) {
  +                this.concreteProcessor.dispose();
           }
  -    }
   
  +        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;
  +	    }
  +	}
   }
  
  
  
  1.1                  cocoon-2.1/src/java/org/apache/cocoon/components/treeprocessor/ConcreteTreeProcessor.java
  
  Index: ConcreteTreeProcessor.java
  ===================================================================
  /*
   * 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.avalon.framework.service.ServiceManager;
  import org.apache.cocoon.ProcessingException;
  import org.apache.cocoon.Processor;
  import org.apache.cocoon.components.ChainedConfiguration;
  import org.apache.cocoon.components.container.ComponentManagerWrapper;
  import org.apache.cocoon.environment.Environment;
  import org.apache.cocoon.environment.ForwardRedirector;
  import org.apache.cocoon.environment.Redirector;
  import org.apache.cocoon.environment.SourceResolver;
  import org.apache.cocoon.environment.internal.EnvironmentHelper;
  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;
      
      private ServiceManager serviceManager;
   
      	/** 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.serviceManager = new ComponentManagerWrapper(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 InternalPipelineDescription buildPipeline(Environment environment)
      throws Exception {
          InvokeContext context = new InvokeContext( true );
  
          context.enableLogging(getLogger());
          context.setLastProcessor(this);
          try {
              if ( process(environment, context) ) {
                  return context.getInternalPipelineDescription(environment);
              } 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
      	        EnvironmentHelper.enterProcessor(this, this.serviceManager, environment);
  
      	        final Redirector oldRedirector = context.getRedirector();
  
      	        // Build a redirector
      	        TreeProcessorRedirector redirector = new TreeProcessorRedirector(environment,
context);
      	        setupLogger(redirector);
      	        context.setRedirector(redirector);
  
      	        try {
      	            boolean success = this.rootNode.invoke(environment, context);
      	            
      	            return success;
  
      	        } finally {
      	            EnvironmentHelper.leaveProcessor();
      	            // Restore old redirector 
      	            context.setRedirector(oldRedirector);
      	        }
  
      		} 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, 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.getURIPrefix().equals("") ) {
              processor = ((TreeProcessor)getRootProcessor()).concreteProcessor;
          } else {
              processor = this;
          }
          
          // Process the redirect
  // No more reset since with TreeProcessorRedirector, we need to pop values from the redirect
location
  //        context.reset();
          return processor.process(newEnv, context);
      }
      
  	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,
              String uri, Logger logger) throws MalformedURLException {
              super(env, 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();
          }
      }
  
  	public SourceResolver getSourceResolver() {
  		return wrappingProcessor.getSourceResolver();
  	}
  
  	public String getContext() {
  		return wrappingProcessor.getContext();
  	}
  }
  
  
  
  1.4       +2 -2      cocoon-2.1/src/java/org/apache/cocoon/components/treeprocessor/sitemap/MountNodeBuilder.java
  
  Index: MountNodeBuilder.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/java/org/apache/cocoon/components/treeprocessor/sitemap/MountNodeBuilder.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- MountNodeBuilder.java	25 May 2004 07:28:25 -0000	1.3
  +++ MountNodeBuilder.java	5 Jun 2004 08:18:50 -0000	1.4
  @@ -39,7 +39,7 @@
           MountNode node = new MountNode(
               VariableResolverFactory.getResolver(config.getAttribute("uri-prefix"), manager),
               VariableResolverFactory.getResolver(config.getAttribute("src"), manager),
  -            this.treeBuilder.getProcessor(),
  +            this.treeBuilder.getProcessor().getWrappingProcessor(),
               config.getAttributeAsBoolean("check-reload", true)
           );
           return (this.treeBuilder.setupNode(node, config));
  
  
  

Mime
View raw message