001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.components.treeprocessor.sitemap;
018:
019: import org.apache.avalon.framework.component.ComponentManager;
020: import org.apache.avalon.framework.component.Composable;
021: import org.apache.avalon.framework.logger.Logger;
022:
023: import org.apache.cocoon.ConnectionResetException;
024: import org.apache.cocoon.ResourceNotFoundException;
025: import org.apache.cocoon.components.treeprocessor.AbstractParentProcessingNode;
026: import org.apache.cocoon.components.treeprocessor.InvokeContext;
027: import org.apache.cocoon.components.treeprocessor.ParameterizableProcessingNode;
028: import org.apache.cocoon.components.treeprocessor.ProcessingNode;
029: import org.apache.cocoon.environment.Environment;
030: import org.apache.cocoon.sitemap.SitemapErrorHandler;
031:
032: import java.util.Map;
033:
034: /**
035: * Handles <map:pipeline>
036: *
037: * @author <a href="mailto:juergen.seitz@basf-it-services.com">Jürgen Seitz</a>
038: * @author <a href="mailto:bluetkemeier@s-und-n.de">Björn Lütkemeier</a>
039: * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
040: * @author <a href="mailto:gianugo@apache.org">Gianugo Rabellino</a>
041: * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
042: * @version $Id: PipelineNode.java 433543 2006-08-22 06:22:54Z crossley $
043: */
044: public class PipelineNode extends AbstractParentProcessingNode
045: implements Composable, ParameterizableProcessingNode {
046:
047: // TODO: handle a 'fail-hard' environment attribute
048: // can be useful to stop off-line generation when there's an error
049:
050: private ProcessingNode[] children;
051:
052: private ErrorHandlerHelper errorHandlerHelper;
053:
054: private boolean internalOnly;
055:
056: /** Is it the last <pipeline> in the enclosing <pipelines> ? */
057: private boolean isLast;
058:
059: /** The component name of the processing pipeline */
060: protected String processingPipeline;
061:
062: /** Optional sitemap parameters */
063: protected Map parameters;
064:
065: /**
066: * A constructor to receive the optional expires parameter
067: * and optional parameters for the processing pipeline
068: */
069: public PipelineNode(String name) {
070: this .processingPipeline = name;
071: this .errorHandlerHelper = new ErrorHandlerHelper();
072: }
073:
074: /**
075: * The component manager is used to create error pipelines
076: */
077: public void compose(ComponentManager manager) {
078: this .errorHandlerHelper.compose(manager);
079: }
080:
081: public void enableLogging(Logger logger) {
082: super .enableLogging(logger);
083: this .errorHandlerHelper.enableLogging(logger);
084: }
085:
086: public void setChildren(ProcessingNode[] nodes) {
087: this .children = nodes;
088: }
089:
090: public void setParameters(Map parameterMap) {
091: this .parameters = parameterMap;
092: }
093:
094: public void setLast(boolean isLast) {
095: this .isLast = isLast;
096: }
097:
098: public void set404Handler(ProcessingNode node) {
099: this .errorHandlerHelper.set404Handler(node);
100: }
101:
102: public void set500Handler(ProcessingNode node) {
103: this .errorHandlerHelper.set500Handler(node);
104: }
105:
106: public void setInternalOnly(boolean internalOnly) {
107: this .internalOnly = internalOnly;
108: }
109:
110: public final boolean invoke(Environment env, InvokeContext context)
111: throws Exception {
112: boolean passThrough;
113: Object passThroughRaw = env
114: .getAttribute(MountNode.COCOON_PASS_THROUGH);
115: if (passThroughRaw == null) {
116: // Use default value
117: passThrough = false;
118: } else {
119: passThrough = ((Boolean) passThroughRaw).booleanValue();
120: }
121:
122: // Always fail on external request if pipeline is internal only.
123: if (this .internalOnly && env.isExternal()) {
124: if (!this .isLast || passThrough) {
125: return false;
126: }
127:
128: // Do not use internal-only pipeline error handler for external requests.
129: throw new ResourceNotFoundException(
130: "No pipeline matched request: "
131: + env.getURIPrefix() + env.getURI());
132: }
133:
134: context.inform(this .processingPipeline, this .parameters, env
135: .getObjectModel());
136: try {
137: if (this .errorHandlerHelper.isInternal()) {
138: // Set internal error handler in the pipeline
139: context.setErrorHandler(new SitemapErrorHandler(
140: this .errorHandlerHelper, env, context));
141: } else {
142: // Reset internal error handler (previous pipeline might had set it)
143: context.setErrorHandler(null);
144: }
145:
146: if (invokeNodes(children, env, context)) {
147: return true;
148: } else if (!this .isLast || passThrough) {
149: return false;
150: }
151:
152: throw new ResourceNotFoundException(
153: "No pipeline matched request: "
154: + env.getURIPrefix() + env.getURI());
155:
156: } catch (ConnectionResetException e) {
157: // Will be reported by CocoonServlet, rethrowing
158: throw e;
159: } catch (Exception e) {
160: // Invoke error handler
161: return this.errorHandlerHelper.invokeErrorHandler(e, env,
162: context);
163: }
164: }
165: }
|