Save This Page
Home » cocoon-2.1.11-src » org.apache » cocoon » components » treeprocessor » sitemap » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   package org.apache.cocoon.components.treeprocessor.sitemap;
   18   
   19   import java.util.HashMap;
   20   import java.util.Iterator;
   21   import java.util.Map;
   22   
   23   import org.apache.avalon.framework.activity.Disposable;
   24   import org.apache.avalon.framework.component.ComponentException;
   25   import org.apache.avalon.framework.component.ComponentManager;
   26   import org.apache.avalon.framework.component.Composable;
   27   import org.apache.cocoon.ProcessingException;
   28   import org.apache.cocoon.components.pipeline.ProcessingPipeline;
   29   import org.apache.cocoon.components.treeprocessor.AbstractProcessingNode;
   30   import org.apache.cocoon.components.treeprocessor.InvokeContext;
   31   import org.apache.cocoon.components.treeprocessor.TreeProcessor;
   32   import org.apache.cocoon.components.treeprocessor.variables.VariableResolver;
   33   import org.apache.cocoon.environment.Environment;
   34   import org.apache.commons.lang.BooleanUtils;
   35   
   36   /**
   37    *
   38    * @author <a href="mailto:bluetkemeier@s-und-n.de">Bj&ouml;rn L&uuml;tkemeier</a>
   39    * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
   40    * @version CVS $Id: MountNode.java 433543 2006-08-22 06:22:54Z crossley $
   41    */
   42   public class MountNode extends AbstractProcessingNode
   43                          implements Composable, Disposable {
   44   
   45       /** The key to get the pass_through value from the Environment */
   46       public final static String COCOON_PASS_THROUGH = "COCOON_PASS_THROUGH";
   47   
   48       /** The 'uri-prefix' attribute */
   49       private final VariableResolver prefix;
   50   
   51       /** The 'src' attribute */
   52       private final VariableResolver source;
   53   
   54       /** Processors for sources */
   55       private Map processors = new HashMap();
   56   
   57       /** The processor for this node */
   58       private final TreeProcessor parentProcessor;
   59   
   60       /** The value of the 'check-reload' attribute */
   61       private final boolean checkReload;
   62   
   63       /** The component manager to be used by the mounted processor */
   64       private ComponentManager manager;
   65   
   66       /** The value of the 'pass-through' attribute */
   67       private final Boolean passThrough;
   68   
   69       public MountNode(VariableResolver prefix,
   70                        VariableResolver source,
   71                        TreeProcessor parentProcessor,
   72                        boolean checkReload,
   73                        boolean passThrough) {
   74           this.prefix = prefix;
   75           this.source = source;
   76           this.parentProcessor = parentProcessor;
   77           this.checkReload = checkReload;
   78           this.passThrough = BooleanUtils.toBooleanObject(passThrough);
   79       }
   80   
   81       public void compose(ComponentManager manager) throws ComponentException {
   82           this.manager = manager;
   83       }
   84   
   85       public final boolean invoke(Environment env, InvokeContext context)
   86         throws Exception {
   87           final Map objectModel = env.getObjectModel();
   88   
   89           String resolvedSource = this.source.resolve(context, objectModel);
   90           String resolvedPrefix = this.prefix.resolve(context, objectModel);
   91   
   92           if (resolvedSource.length() == 0) {
   93               throw new ProcessingException("Source of mount statement is empty");
   94           }
   95           TreeProcessor processor = getProcessor(resolvedSource);
   96   
   97           // Save context
   98           String oldPrefix = env.getURIPrefix();
   99           String oldURI    = env.getURI();
  100           String oldContext   = env.getContext();
  101           Object oldPassThrough = env.getAttribute(COCOON_PASS_THROUGH);
  102           env.setAttribute(COCOON_PASS_THROUGH, this.passThrough);
  103   
  104           boolean pipelineWasBuilt = false;
  105   
  106           try {
  107               env.changeContext(resolvedPrefix, resolvedSource);
  108   
  109               if (context.isBuildingPipelineOnly()) {
  110                   // Propagate pipelines
  111                   ProcessingPipeline pp = processor.buildPipeline(env);
  112                   if (pp != null) {
  113                       context.setProcessingPipeline( pp );
  114                       pipelineWasBuilt = true;
  115                   }
  116               } else {
  117                   // Processor will create its own pipelines
  118                   pipelineWasBuilt = processor.process(env);
  119               }
  120           } catch(Exception e) {
  121               // Wrap with our location
  122               throw ProcessingException.throwLocated("Sitemap: error when calling sub-sitemap", e, getLocation());
  123   
  124           } finally {
  125               // We restore the context only if no pipeline was built. This allows the pipeline
  126               // environment to be left unchanged when we go back to ancestor processors.
  127               // If no pipeline was built, we restore the context, so that the current processor
  128               // continues executing the sitemap in the correct environment.
  129               if (!pipelineWasBuilt) {
  130                   env.setContext(oldPrefix, oldURI, oldContext);
  131               }
  132   
  133               if (oldPassThrough != null) {
  134                   env.setAttribute(COCOON_PASS_THROUGH, oldPassThrough);
  135               } else {
  136                   env.removeAttribute(COCOON_PASS_THROUGH);
  137               }
  138   
  139               // Turning recomposing as a test, according to:
  140               // http://marc.theaimsgroup.com/?t=106802211400005&r=1&w=2
  141               // Recompose pipelines which may have been recomposed by subsitemap
  142               // context.recompose(this.manager);
  143           }
  144   
  145           return pipelineWasBuilt;
  146       }
  147   
  148       private synchronized TreeProcessor getProcessor(String source)
  149       throws Exception {
  150   
  151           TreeProcessor processor = (TreeProcessor) processors.get(source);
  152           if (processor == null) {
  153               // Handle directory mounts
  154               String actualSource;
  155               if (source.charAt(source.length() - 1) == '/') {
  156                   actualSource = source + "sitemap.xmap";
  157               } else {
  158                   actualSource = source;
  159               }
  160   
  161               processor = this.parentProcessor.createChildProcessor(this.manager, actualSource, this.checkReload);
  162   
  163               // Associate to the original source
  164               processors.put(source, processor);
  165           }
  166   
  167           return processor;
  168       }
  169   
  170       /**
  171        *
  172        */
  173       public void dispose() {
  174           Iterator iter = this.processors.values().iterator();
  175           while(iter.hasNext()) {
  176               ((TreeProcessor)iter.next()).dispose();
  177           }
  178       }
  179   }

Save This Page
Home » cocoon-2.1.11-src » org.apache » cocoon » components » treeprocessor » sitemap » [javadoc | source]