Author: vgritsenko Date: Tue Mar 15 06:26:31 2005 New Revision: 157541 URL: http://svn.apache.org/viewcvs?view=rev&rev=157541 Log: Internal Error Handling Implementation: * Added ProcessingPipeline method: setErrorHandler(SitemapErrorHandler) * Added SitemapErrorHandler class * Added samples for internal error handling Bugfixes: * Sitemap now properly throws ResourceNotFound exception for not matched requests even if last pipeline marked as an internal pipeline. * Sitemap handle-errors now reports an error if generator is missing, or if type attribute (deprecated) specified and generator is present. (code was there but was not working)
Added: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/sitemap/SitemapErrorHandler.java (with props) cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/ cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/error2xml.xslt (with props) cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/include.xslt (with props) cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/one.xml (with props) cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/samples.xml (with props) cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/sitemap.xmap (with props) cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/two.xml (with props) Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/pipeline/AbstractProcessingPipeline.java cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/pipeline/ProcessingPipeline.java cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/pipeline/impl/AbstractCachingProcessingPipeline.java cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ErrorHandlerHelper.java cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/HandleErrorsNode.java cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/HandleErrorsNodeBuilder.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/PipelineNode.java cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/PipelineNodeBuilder.java cocoon/branches/BRANCH_2_1_X/src/samples/org/apache/cocoon/samples/errorhandling/ExceptionGenerator.java cocoon/branches/BRANCH_2_1_X/status.xml Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/pipeline/AbstractProcessingPipeline.java URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/pipeline/AbstractProcessingPipeline.java?view=diff&r1=157540&r2=157541 ============================================================================== --- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/pipeline/AbstractProcessingPipeline.java (original) +++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/pipeline/AbstractProcessingPipeline.java Tue Mar 15 06:26:31 2005 @@ -34,11 +34,13 @@ import org.apache.cocoon.generation.Generator; import org.apache.cocoon.reading.Reader; import org.apache.cocoon.serialization.Serializer; +import org.apache.cocoon.sitemap.SitemapErrorHandler; import org.apache.cocoon.sitemap.SitemapModelComponent; import org.apache.cocoon.sitemap.SitemapParameters; import org.apache.cocoon.transformation.Transformer; import org.apache.cocoon.xml.XMLConsumer; import org.apache.cocoon.xml.XMLProducer; +import org.apache.cocoon.xml.SaxBuffer; import org.apache.excalibur.source.SourceValidity; import org.xml.sax.SAXException; @@ -90,6 +92,10 @@ protected String sitemapReaderMimeType; protected OutputComponentSelector readerSelector; + // Error handler stuff + private SitemapErrorHandler errorHandler; + private ProcessingPipeline errorPipeline; + /** True when pipeline has been prepared. */ private boolean prepared; @@ -112,7 +118,7 @@ protected long configuredExpires; /** Configured Output Buffer Size */ - protected int configuredOutputBufferSize; + protected int configuredOutputBufferSize; /** The parameters */ protected Parameters parameters; @@ -210,7 +216,7 @@ * @param param the parameters for the generator. * @throws ProcessingException if the generator couldn't be obtained. */ - public void setGenerator (String role, String source, Parameters param, Parameters hintParam) + public void setGenerator(String role, String source, Parameters param, Parameters hintParam) throws ProcessingException { if (this.generator != null) { throw new ProcessingException ("Generator already set. Cannot set generator '" + role + @@ -246,7 +252,7 @@ * @param param the parameters for the transfomer. * @throws ProcessingException if the generator couldn't be obtained. */ - public void addTransformer (String role, String source, Parameters param, Parameters hintParam) + public void addTransformer(String role, String source, Parameters param, Parameters hintParam) throws ProcessingException { if (this.reader != null) { // Should normally never happen as setting a reader starts pipeline processing @@ -277,7 +283,7 @@ * Set the serializer for this pipeline * @param mimeType Can be null */ - public void setSerializer (String role, String source, Parameters param, Parameters hintParam, String mimeType) + public void setSerializer(String role, String source, Parameters param, Parameters hintParam, String mimeType) throws ProcessingException { if (this.serializer != null) { // Should normally not happen as adding a serializer starts pipeline processing @@ -315,7 +321,7 @@ * Set the reader for this pipeline * @param mimeType Can be null */ - public void setReader (String role, String source, Parameters param, String mimeType) + public void setReader(String role, String source, Parameters param, String mimeType) throws ProcessingException { if (this.reader != null) { // Should normally never happen as setting a reader starts pipeline processing @@ -344,6 +350,14 @@ this.sitemapReaderMimeType = readerSelector.getMimeTypeForHint(role); } + /** + * Sets error handler for this pipeline. + * Used for handling errors in the internal pipelines. + * @param errorHandler error handler + */ + public void setErrorHandler(SitemapErrorHandler errorHandler) { + this.errorHandler = errorHandler; + } /** * Sanity check @@ -499,7 +513,38 @@ public void prepareInternal(Environment environment) throws ProcessingException { this.lastConsumer = null; - preparePipeline(environment); + try { + preparePipeline(environment); + } catch (ProcessingException e) { + prepareInternalErrorHandler(environment, e); + } + } + + /** + * If prepareInternal fails, prepare internal error handler. + */ + protected void prepareInternalErrorHandler(Environment environment, ProcessingException ex) + throws ProcessingException { + if (this.errorHandler != null) { + try { + this.errorPipeline = this.errorHandler.prepareErrorPipeline(ex); + if (this.errorPipeline != null) { + this.errorPipeline.prepareInternal(environment); + return; + } + } catch (ProcessingException e) { + throw e; + } catch (Exception e) { + throw new ProcessingException("Failed to handle exception <" + ex + ">", e); + } + } + } + + /** + * @return true if error happened during internal pipeline prepare call. + */ + protected boolean isInternalError() { + return this.errorPipeline != null; } /** @@ -706,6 +751,13 @@ this.serializer = null; this.parameters = null; this.lastConsumer = null; + + // Release error handler + this.errorHandler = null; + if (this.errorPipeline != null) { + this.errorPipeline.release(); + this.errorPipeline = null; + } } /** @@ -714,13 +766,50 @@ */ public boolean process(Environment environment, XMLConsumer consumer) throws ProcessingException { - this.lastConsumer = consumer; if (this.reader != null) { throw new ProcessingException("Streaming of an internal pipeline is not possible with a reader."); } - connectPipeline(environment); - return processXMLPipeline(environment); + // Exception happened during setup and was handled + if (this.errorPipeline != null) { + return this.errorPipeline.process(environment, consumer); + } + + // Have to buffer events if error handler is specified. + SaxBuffer buffer = null; + this.lastConsumer = this.errorHandler == null? consumer: (buffer = new SaxBuffer()); + try { + connectPipeline(environment); + return processXMLPipeline(environment); + } catch (ProcessingException e) { + buffer = null; + return processErrorHandler(environment, e, consumer); + } finally { + if (buffer != null) { + try { + buffer.toSAX(consumer); + } catch (SAXException e) { + throw new ProcessingException("Failed to execute pipeline.", e); + } + } + } + } + + protected boolean processErrorHandler(Environment environment, ProcessingException e, XMLConsumer consumer) + throws ProcessingException { + if (this.errorHandler != null) { + try { + this.errorPipeline = this.errorHandler.prepareErrorPipeline(e); + if (this.errorPipeline != null) { + this.errorPipeline.prepareInternal(environment); + return this.errorPipeline.process(environment, consumer); + } + } catch (Exception ignored) { + getLogger().debug("Exception in error handler", ignored); + } + } + + throw e; } /** Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/pipeline/ProcessingPipeline.java URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/pipeline/ProcessingPipeline.java?view=diff&r1=157540&r2=157541 ============================================================================== --- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/pipeline/ProcessingPipeline.java (original) +++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/pipeline/ProcessingPipeline.java Tue Mar 15 06:26:31 2005 @@ -20,6 +20,7 @@ import org.apache.avalon.framework.parameters.Parameters; import org.apache.cocoon.ProcessingException; +import org.apache.cocoon.sitemap.SitemapErrorHandler; import org.apache.cocoon.environment.Environment; import org.apache.cocoon.generation.Generator; import org.apache.cocoon.xml.XMLConsumer; @@ -116,6 +117,13 @@ * @param mimeType Can be null */ void setReader(String role, String source, Parameters param, String mimeType) + throws ProcessingException; + + /** + * Sets error handler for this pipeline. + * Used for handling errors in the internal pipelines. + */ + void setErrorHandler(SitemapErrorHandler errorHandler) throws ProcessingException; /** Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/pipeline/impl/AbstractCachingProcessingPipeline.java URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/pipeline/impl/AbstractCachingProcessingPipeline.java?view=diff&r1=157540&r2=157541 ============================================================================== --- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/pipeline/impl/AbstractCachingProcessingPipeline.java (original) +++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/pipeline/impl/AbstractCachingProcessingPipeline.java Tue Mar 15 06:26:31 2005 @@ -814,6 +814,10 @@ * Otherwise return <code>null</code> */ public SourceValidity getValidityForEventPipeline() { + if (isInternalError()) { + return null; + } + if (this.cachedResponse != null) { if (this.toCacheSourceValidities != null) { // This means that the pipeline is valid based on the validities @@ -898,16 +902,21 @@ * @see org.apache.cocoon.components.pipeline.ProcessingPipeline#getKeyForEventPipeline() */ public String getKeyForEventPipeline() { - if ( null != this.toCacheKey + if (isInternalError()) { + return null; + } + + if (null != this.toCacheKey && !this.cacheCompleteResponse && this.firstNotCacheableTransformerIndex == super.transformers.size()) { return String.valueOf(HashUtil.hash(this.toCacheKey.toString())); } - if ( null != this.fromCacheKey + if (null != this.fromCacheKey && !this.completeResponseIsCached && this.firstProcessedTransformerIndex == super.transformers.size()) { return String.valueOf(HashUtil.hash(this.fromCacheKey.toString())); } + return null; } Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ErrorHandlerHelper.java URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ErrorHandlerHelper.java?view=diff&r1=157540&r2=157541 ============================================================================== --- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ErrorHandlerHelper.java (original) +++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ErrorHandlerHelper.java Tue Mar 15 06:26:31 2005 @@ -25,6 +25,7 @@ import org.apache.cocoon.ResourceNotFoundException; import org.apache.cocoon.components.notification.Notifying; import org.apache.cocoon.components.notification.NotifyingBuilder; +import org.apache.cocoon.components.pipeline.ProcessingPipeline; import org.apache.cocoon.components.treeprocessor.InvokeContext; import org.apache.cocoon.components.treeprocessor.ProcessingNode; import org.apache.cocoon.environment.Environment; @@ -38,7 +39,7 @@ * * @author <a href="mailto:[EMAIL PROTECTED]">Jürgen Seitz</a> * @author <a href="mailto:[EMAIL PROTECTED]">Björn Lütkemeier</a> - * @version CVS $Id$ + * @version $Id$ */ public class ErrorHandlerHelper extends AbstractLogEnabled implements Composable { @@ -52,14 +53,14 @@ /** * Error handling node for the ResourceNotFoundException + * (deprecated) */ - private ProcessingNode error404; + private HandleErrorsNode error404; /** * Error handling node for all other exceptions */ - private ProcessingNode error500; - + private HandleErrorsNode error500; public void enableLogging(Logger logger) { super.enableLogging(logger); @@ -73,46 +74,98 @@ this.manager = manager; } - void setHandledErrorsLogger(Logger logger) { - this.handledErrorsLogger = logger; - } - void set404Handler(ProcessingNode node) { - this.error404 = node; + this.error404 = (HandleErrorsNode) node; } void set500Handler(ProcessingNode node) { - this.error500 = node; + this.error500 = (HandleErrorsNode) node; + } + + /** + * @return true if has no error handler nodes set + */ + public boolean isEmpty() { + return this.error404 == null && this.error500 == null; + } + + public boolean isInternal() { + return this.error500 != null && this.error500.isInternal(); + } + + public boolean isExternal() { + return this.error500 != null && this.error500.isExternal(); } + /** + * Handle error. + */ public boolean invokeErrorHandler(Exception ex, Environment env, InvokeContext context) throws Exception { - if (!env.isExternal() && !env.isInternalRedirect()) { - // Propagate exception on internal requests + return prepareErrorHandler(ex, env, context) != null; + } + + /** + * Prepare error handler for the internal pipeline error handling. + * + * <p>If building pipeline only, error handling pipeline will be + * built and returned. If building and executing pipeline, + * error handling pipeline will be built and executed.</p> + */ + public ProcessingPipeline prepareErrorHandler(Exception ex, + Environment env, + InvokeContext context) + throws Exception { + boolean internal = !env.isExternal() && !env.isInternalRedirect(); + + if (internal && !isInternal()) { + // Propagate exception on internal request: No internal handler. + throw ex; + } else if (!internal && !isExternal()) { + // Propagate exception on external request: No external handler. throw ex; - } else if (error404 != null && ex instanceof ResourceNotFoundException) { - // Invoke 404-specific handler - return invokeErrorHandler(error404, ex, env, context); + } else if (!internal && error404 != null && ex instanceof ResourceNotFoundException) { + // Invoke 404-specific handler: Only on external requests. Deprecated. + return prepareErrorHandler(error404, ex, env, context); } else if (error500 != null) { // Invoke global handler - return invokeErrorHandler(error500, ex, env, context); + return prepareErrorHandler(error500, ex, env, context); } - // No handler : propagate + // Exception was not handled in this error handler, propagate. throw ex; } + /** + * Handle error using specified error handler processing node. + */ public boolean invokeErrorHandler(ProcessingNode node, Exception ex, Environment env, InvokeContext context) throws Exception { + return prepareErrorHandler(node, ex, env, context) != null; + } + + /** + * Prepare (or execute) error handler using specified error handler + * processing node. + * + * <p>If building pipeline only, error handling pipeline will be + * built and returned. If building and executing pipeline, + * error handling pipeline will be built and executed.</p> + */ + private ProcessingPipeline prepareErrorHandler(ProcessingNode node, + Exception ex, + Environment env, + InvokeContext context) + throws Exception { this.handledErrorsLogger.error(ex.getMessage(), ex); try { - prepare(env, ex); + prepare(context, env, ex); // Create error context InvokeContext errorContext = new InvokeContext(context.isBuildingPipelineOnly()); @@ -123,7 +176,7 @@ // Process error handling node if (node.invoke(env, errorContext)) { // Exception was handled. - return true; + return errorContext.getProcessingPipeline(); } } finally { errorContext.dispose(); @@ -138,7 +191,10 @@ throw ex; } - private void prepare(Environment env, Exception ex) + /** + * Build notifying object + */ + private void prepare(InvokeContext context, Environment env, Exception ex) throws IOException, ComponentException { Map objectModel = env.getObjectModel(); if (objectModel.get(Constants.NOTIFYING_OBJECT) == null) { @@ -146,7 +202,9 @@ // Try to reset the response to avoid mixing already produced output // and error page. - env.tryResetResponse(); + if (!context.isBuildingPipelineOnly()) { + env.tryResetResponse(); + } // Create a Notifying NotifyingBuilder notifyingBuilder = (NotifyingBuilder) this.manager.lookup(NotifyingBuilder.ROLE); Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/HandleErrorsNode.java URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/HandleErrorsNode.java?view=diff&r1=157540&r2=157541 ============================================================================== --- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/HandleErrorsNode.java (original) +++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/HandleErrorsNode.java Tue Mar 15 06:26:31 2005 @@ -1,12 +1,12 @@ /* - * Copyright 1999-2004 The Apache Software Foundation. - * + * Copyright 1999-2005 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. @@ -16,7 +16,10 @@ package org.apache.cocoon.components.treeprocessor.sitemap; import org.apache.avalon.framework.parameters.Parameters; +import org.apache.avalon.framework.configuration.ConfigurationException; + import org.apache.cocoon.ProcessingException; +import org.apache.cocoon.Constants; import org.apache.cocoon.components.treeprocessor.AbstractParentProcessingNode; import org.apache.cocoon.components.treeprocessor.InvokeContext; import org.apache.cocoon.components.treeprocessor.ProcessingNode; @@ -26,29 +29,53 @@ * Handles <map:handle-errors> * * @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a> - * @version CVS $Id: HandleErrorsNode.java,v 1.3 2004/03/05 13:02:52 bdelacretaz Exp $ + * @version $Id$ */ - public final class HandleErrorsNode extends AbstractParentProcessingNode { private ProcessingNode[] children; private int statusCode; + private boolean internal; + private boolean external; - public HandleErrorsNode(int statusCode) { + /** + * @param statusCode Value of the type attribute: 404 (deprecated), 500 (deprecated), or -1 (no attribute present). + * @param scope Value of the error handler scope attribute: external, internal, always. + */ + public HandleErrorsNode(int statusCode, String scope) + throws ConfigurationException { this.statusCode = statusCode; + if ("internal".equals(scope)) { + this.internal = true; + } else if ("external".equals(scope)) { + this.external = true; + } else if ("always".equals(scope)) { + this.internal = true; + this.external = true; + } else { + throw new ConfigurationException("Unrecognized value of when attribute on <handle-errors> at " + + getLocation()); + } } public int getStatusCode() { return this.statusCode; } - public void setChildren(ProcessingNode[] nodes) - { + public boolean isInternal() { + return this.internal; + } + + public boolean isExternal() { + return this.external; + } + + public void setChildren(ProcessingNode[] nodes) { this.children = nodes; } public final boolean invoke(Environment env, InvokeContext context) - throws Exception { + throws Exception { if (getLogger().isInfoEnabled()) { getLogger().info("Processing handle-errors at " + getLocation()); @@ -58,35 +85,42 @@ // No 'type' attribute : new Cocoon 2.1 behaviour, no implicit generator try { return invokeNodes(this.children, env, context); - - } catch(ProcessingException pe) { + + } catch (ProcessingException e) { // Handle the various cases related to the transition from implicit generators in handle-errors to // explicit ones, in order to provide meaningful messages that will ease the migration - if (statusCode == - 1 && - pe.getMessage().indexOf("must set a generator first before you can use a transformer") != -1) { + if (e.getMessage().indexOf("Must set a generator before adding") != -1) { + env.getObjectModel().remove(Constants.NOTIFYING_OBJECT); throw new ProcessingException( - "Incomplete pipeline : 'handle-error' without a 'type' must include a generator, at " + - this.getLocation() + System.getProperty("line.separator") + + "Incomplete pipeline: 'handle-error' without a 'type' must include a generator, at " + + getLocation() + System.getProperty("line.separator") + "Either add a generator (preferred) or a type='500' attribute (deprecated) on 'handle-errors'"); - - } else if (statusCode != -1 && - pe.getMessage().indexOf("Generator already set") != -1){ - - throw new ProcessingException( - "Error : 'handle-error' with a 'type' attribute has an implicit generator, at " + - this.getLocation() + System.getProperty("line.separator") + - "Please remove the 'type' attribute on 'handle-error'"); - - } else { - // Rethrow the exception - throw pe; } + + // Rethrow the exception + throw e; } + } else { // A 'type' attribute is present : add the implicit generator context.getProcessingPipeline().setGenerator("<notifier>", "", Parameters.EMPTY_PARAMETERS, Parameters.EMPTY_PARAMETERS); - return invokeNodes(this.children, env, context); - } + + try { + return invokeNodes(this.children, env, context); + } catch (ProcessingException e) { + if (e.getMessage().indexOf("Generator already set") != -1){ + + env.getObjectModel().remove(Constants.NOTIFYING_OBJECT); + throw new ProcessingException( + "Error: 'handle-error' with a 'type' attribute has an implicit generator, at " + + getLocation() + System.getProperty("line.separator") + + "Please remove the 'type' attribute on 'handle-error'"); + } + + // Rethrow the exception + throw e; + } + } } } Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/HandleErrorsNodeBuilder.java URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/HandleErrorsNodeBuilder.java?view=diff&r1=157540&r2=157541 ============================================================================== --- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/HandleErrorsNodeBuilder.java (original) +++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/HandleErrorsNodeBuilder.java Tue Mar 15 06:26:31 2005 @@ -1,12 +1,12 @@ /* - * Copyright 1999-2004 The Apache Software Foundation. - * + * Copyright 1999-2005 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. @@ -25,10 +25,10 @@ * Builds a <map:handle-errors> * * @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a> - * @version CVS $Id: HandleErrorsNodeBuilder.java,v 1.3 2004/03/05 13:02:52 bdelacretaz Exp $ + * @version $Id$ */ - -public class HandleErrorsNodeBuilder extends AbstractParentProcessingNodeBuilder implements ThreadSafe { +public class HandleErrorsNodeBuilder extends AbstractParentProcessingNodeBuilder + implements ThreadSafe { /** This builder has no parameters -- return <code>false</code> */ protected boolean hasParameters() { @@ -37,17 +37,19 @@ public ProcessingNode buildNode(Configuration config) throws Exception { - HandleErrorsNode node = new HandleErrorsNode(config.getAttributeAsInteger("type", -1)); + HandleErrorsNode node = new HandleErrorsNode(config.getAttributeAsInteger("type", -1), + config.getAttribute("when", "external")); this.treeBuilder.setupNode(node, config); - - // Set a flag that will prevent redirects - ((SitemapLanguage)this.treeBuilder).setBuildingErrorHandler(true); - - // Get all children - node.setChildren(buildChildNodes(config)); - // And clear the flag - ((SitemapLanguage)this.treeBuilder).setBuildingErrorHandler(false); + // Set a flag that will prevent redirects + ((SitemapLanguage) this.treeBuilder).setBuildingErrorHandler(true); + try { + // Get all children + node.setChildren(buildChildNodes(config)); + } finally { + // And clear the flag + ((SitemapLanguage) this.treeBuilder).setBuildingErrorHandler(false); + } return node; } Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/MountNode.java URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/MountNode.java?view=diff&r1=157540&r2=157541 ============================================================================== --- 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 Tue Mar 15 06:26:31 2005 @@ -91,7 +91,7 @@ if (resolvedSource.length() == 0) { throw new ProcessingException("Source of mount statement is empty"); } - TreeProcessor processor = getProcessor(resolvedSource, resolvedPrefix); + TreeProcessor processor = getProcessor(resolvedSource); // Save context String oldPrefix = env.getURIPrefix(); @@ -101,7 +101,7 @@ env.setAttribute(COCOON_PASS_THROUGH, BooleanUtils.toBooleanObject(passThrough)); boolean pipelineWasBuilt = false; - + try { env.changeContext(resolvedPrefix, resolvedSource); @@ -111,8 +111,6 @@ if (pp != null) { context.setProcessingPipeline( pp ); pipelineWasBuilt = true; - } else { - pipelineWasBuilt = false; } } else { // Processor will create its own pipelines @@ -126,7 +124,7 @@ if (!pipelineWasBuilt) { env.setContext(oldPrefix, oldURI, oldContext); } - + if (oldPassThrough != null) { env.setAttribute(COCOON_PASS_THROUGH, oldPassThrough); } else { @@ -138,14 +136,14 @@ // Recompose pipelines which may have been recomposed by subsitemap // context.recompose(this.manager); } - + return pipelineWasBuilt; } - private synchronized TreeProcessor getProcessor(String source, String prefix) throws Exception { - - TreeProcessor processor = (TreeProcessor)processors.get(source); + private synchronized TreeProcessor getProcessor(String source) + throws Exception { + TreeProcessor processor = (TreeProcessor) processors.get(source); if (processor == null) { // Handle directory mounts String actualSource; Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/PipelineNode.java URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/PipelineNode.java?view=diff&r1=157540&r2=157541 ============================================================================== --- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/PipelineNode.java (original) +++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/PipelineNode.java Tue Mar 15 06:26:31 2005 @@ -26,6 +26,7 @@ import org.apache.cocoon.components.treeprocessor.ParameterizableProcessingNode; import org.apache.cocoon.components.treeprocessor.ProcessingNode; import org.apache.cocoon.environment.Environment; +import org.apache.cocoon.sitemap.SitemapErrorHandler; import java.util.Map; @@ -118,11 +119,22 @@ // Always fail on external request if pipeline is internal only. if (this.internalOnly && env.isExternal()) { - return false; + if (!this.isLast || passThrough) { + return false; + } + + // Do not use internal-only pipeline error handler for external requests. + throw new ResourceNotFoundException("No pipeline matched request: " + + env.getURIPrefix() + env.getURI()); } context.inform(this.processingPipeline, this.parameters, env.getObjectModel()); try { + if (this.errorHandlerHelper.isInternal()) { + context.getProcessingPipeline().setErrorHandler( + new SitemapErrorHandler(this.errorHandlerHelper, env, context)); + } + if (invokeNodes(children, env, context)) { return true; } else if (!this.isLast || passThrough) { Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/PipelineNodeBuilder.java URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/PipelineNodeBuilder.java?view=diff&r1=157540&r2=157541 ============================================================================== --- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/PipelineNodeBuilder.java (original) +++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/PipelineNodeBuilder.java Tue Mar 15 06:26:31 2005 @@ -1,5 +1,5 @@ /* - * Copyright 1999-2004 The Apache Software Foundation. + * Copyright 1999-2005 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. @@ -28,14 +28,13 @@ /** * Builds a <map:pipeline> + * * @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a> * @author <a href="mailto:[EMAIL PROTECTED]">Gianugo Rabellino</a> - * @version CVS $Id$ + * @version $Id$ */ - -public class PipelineNodeBuilder - extends AbstractParentProcessingNodeBuilder - implements ThreadSafe { +public class PipelineNodeBuilder extends AbstractParentProcessingNodeBuilder + implements ThreadSafe { /** This builder can have parameters -- return <code>true</code> */ protected boolean hasParameters() { @@ -44,14 +43,13 @@ public ProcessingNode buildNode(Configuration config) throws Exception { - String type = this.treeBuilder.getTypeForStatement(config, ProcessingPipeline.ROLE + "Selector"); PipelineNode node = new PipelineNode(type); this.treeBuilder.setupNode(node, config); node.setInternalOnly(config.getAttributeAsBoolean("internal-only", false)); - // Main (with no "type" attribute) error handler : new in Cocoon 2.1, must have a generator + // Main (with no "type" attribute) error handler: new in Cocoon 2.1, must have a generator ProcessingNode mainHandler = null; // 404 & 500 error handlers as in Cocoon 2.0.x, have an implicit generator @@ -61,7 +59,6 @@ Configuration[] childConfigs = config.getChildren(); List children = new ArrayList(); for (int i = 0; i < childConfigs.length; i++) { - Configuration childConfig = childConfigs[i]; if (isChild(childConfig)) { @@ -71,57 +68,55 @@ HandleErrorsNode handler = (HandleErrorsNode)builder.buildNode(childConfig); int status = handler.getStatusCode(); - switch(status) { - case -1: // main handler (needs generator) - if (mainHandler != null) { - throw new ConfigurationException("Duplicate <handle-errors> at " + handler.getLocation()); - } else if (error500Handler != null || error404Handler != null) { - throw new ConfigurationException("Cannot mix <handle-errors> with and without 'type' attribute at " + - handler.getLocation()); - } else { - mainHandler = handler; - } - break; - - case 404: - if (error404Handler != null) { - throw new ConfigurationException("Duplicate <handle-errors type='404' at " + handler.getLocation()); - } else if(mainHandler != null) { + switch(status) { + case -1: // main handler (needs generator) + if (mainHandler != null) { + throw new ConfigurationException("Duplicate <handle-errors> at " + handler.getLocation()); + } else if (error500Handler != null || error404Handler != null) { + throw new ConfigurationException("Cannot mix <handle-errors> with and without 'type' attribute at " + + handler.getLocation()); + } else { + mainHandler = handler; + } + break; + + case 404: + if (error404Handler != null) { + throw new ConfigurationException("Duplicate <handle-errors type='404' at " + handler.getLocation()); + } else if(mainHandler != null) { throw new ConfigurationException("Cannot mix <handle-errors> with and without 'type' attribute at " + - handler.getLocation()); - } else { - error404Handler = handler; - } - break; + handler.getLocation()); + } else { + error404Handler = handler; + } + break; - case 500: - if (error500Handler != null) { + case 500: + if (error500Handler != null) { throw new ConfigurationException("Duplicate <handle-errors type='500' at " + handler.getLocation()); - } else if (mainHandler != null) { + } else if (mainHandler != null) { throw new ConfigurationException("Cannot mix <handle-errors> with and without 'type' attribute at " + - handler.getLocation()); + handler.getLocation()); } else { error500Handler = handler; } - break; + break; - default: - throw new ConfigurationException("Unknown handle-errors type (" + type + ") at " + handler.getLocation()); - } + default: + throw new ConfigurationException("Unknown handle-errors type (" + type + ") at " + handler.getLocation()); + } } else { // Regular builder children.add(builder.buildNode(childConfig)); } } } + node.setChildren(toNodeArray(children)); node.set404Handler(error404Handler); // Set either main or error500 handler as only one can exist node.set500Handler(error500Handler == null ? mainHandler : error500Handler); + return node; } - - - } - Added: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/sitemap/SitemapErrorHandler.java URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/sitemap/SitemapErrorHandler.java?view=auto&rev=157541 ============================================================================== --- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/sitemap/SitemapErrorHandler.java (added) +++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/sitemap/SitemapErrorHandler.java Tue Mar 15 06:26:31 2005 @@ -0,0 +1,87 @@ +/* + * Copyright 2005 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.sitemap; + +import org.apache.cocoon.components.treeprocessor.InvokeContext; +import org.apache.cocoon.components.treeprocessor.sitemap.ErrorHandlerHelper; +import org.apache.cocoon.components.pipeline.ProcessingPipeline; +import org.apache.cocoon.environment.Environment; + +/** + * Class providing error handling capabilities to the pipeline + * as configured in the sitemap. + * + * @since 2.1.7 + * @version $Id$ + */ +public class SitemapErrorHandler { + /** + * Error handler helper of the pipeline node + */ + private ErrorHandlerHelper handler; + + /** + * Environment of the pipeline node + */ + private Environment environment; + + /** + * Sitemap invocation context + */ + private InvokeContext context; + + // Environment state + private String envPrefix; + private String envURI; + private String envContext; + + /** + * Construct error handler with everything needed to handle an error. + */ + public SitemapErrorHandler(ErrorHandlerHelper handler, + Environment environment, + InvokeContext context) { + this.handler = handler; + this.environment = environment; + this.context = context; + + this.envPrefix = environment.getURIPrefix(); + this.envURI = environment.getURI(); + this.envContext = environment.getContext(); + } + + /** + * Handle an error. + * @return true if error was handled. + */ + public boolean handleError(Exception e) throws Exception { + // Restore environment state + this.environment.setContext(this.envPrefix, this.envURI, this.envContext); + + return this.handler.invokeErrorHandler(e, this.environment, this.context); + } + + /** + * Build error handling pipeline. + * @return error handling pipeline, or null if error was not handled. + */ + public ProcessingPipeline prepareErrorPipeline(Exception e) throws Exception { + // Restore environment state + this.environment.setContext(this.envPrefix, this.envURI, this.envContext); + + return this.handler.prepareErrorHandler(e, this.environment, this.context); + } +} Propchange: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/sitemap/SitemapErrorHandler.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/sitemap/SitemapErrorHandler.java ------------------------------------------------------------------------------ svn:keywords = Id Modified: cocoon/branches/BRANCH_2_1_X/src/samples/org/apache/cocoon/samples/errorhandling/ExceptionGenerator.java URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/samples/org/apache/cocoon/samples/errorhandling/ExceptionGenerator.java?view=diff&r1=157540&r2=157541 ============================================================================== --- cocoon/branches/BRANCH_2_1_X/src/samples/org/apache/cocoon/samples/errorhandling/ExceptionGenerator.java (original) +++ cocoon/branches/BRANCH_2_1_X/src/samples/org/apache/cocoon/samples/errorhandling/ExceptionGenerator.java Tue Mar 15 06:26:31 2005 @@ -59,13 +59,15 @@ */ public void generate() throws ProcessingException , SAXException, IOException { - String text = ExceptionAction.exception(this.exception, this.code); Attributes noAttrs = new AttributesImpl(); this.contentHandler.startDocument(); this.contentHandler.startElement("", "html", "html", noAttrs); this.contentHandler.startElement("", "body", "body", noAttrs); this.contentHandler.startElement("", "p", "p", noAttrs); + + String text = ExceptionAction.exception(this.exception, this.code); this.contentHandler.characters(text.toCharArray(), 0, text.length()); + this.contentHandler.endElement("", "p", "p"); this.contentHandler.endElement("", "body", "body"); this.contentHandler.endElement("", "html", "html"); Added: cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/error2xml.xslt URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/error2xml.xslt?view=auto&rev=157541 ============================================================================== --- cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/error2xml.xslt (added) +++ cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/error2xml.xslt Tue Mar 15 06:26:31 2005 @@ -0,0 +1,35 @@ +<?xml version="1.0"?> +<!-- + Copyright 1999-2005 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. +--> + +<!--+ + | $Id$ + +--> +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:error="http://apache.org/cocoon/error/2.1"> + + <!-- let sitemap override default page title --> + <xsl:param name="pageTitle" select="//error:notify/error:title"/> + + <xsl:template match="error:notify"> + <div style="margin: 5px; border: 1px solid red;"> + <div style="margin: 1px; background-color: #FF8888;"><xsl:value-of select="$pageTitle"/></div> + <xsl:value-of select="error:description"/> + </div> + </xsl:template> + +</xsl:stylesheet> Propchange: cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/error2xml.xslt ------------------------------------------------------------------------------ svn:eol-style = native Propchange: cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/error2xml.xslt ------------------------------------------------------------------------------ svn:keywords = Id Added: cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/include.xslt URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/include.xslt?view=auto&rev=157541 ============================================================================== --- cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/include.xslt (added) +++ cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/include.xslt Tue Mar 15 06:26:31 2005 @@ -0,0 +1,33 @@ +<?xml version="1.0"?> +<!-- + Copyright 2005 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. +--> + +<!--+ + | $Id$ + +--> +<xsl:stylesheet version="1.0" + xmlns:i="http://apache.org/cocoon/include/1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + <xsl:param name="uri"/> + + <xsl:template match="/"> + <html> + <i:include src="one.xml"/> + <i:include src="cocoon:/{$uri}"/> + <i:include src="two.xml"/> + </html> + </xsl:template> +</xsl:stylesheet> Propchange: cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/include.xslt ------------------------------------------------------------------------------ svn:eol-style = native Propchange: cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/include.xslt ------------------------------------------------------------------------------ svn:keywords = Id Added: cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/one.xml URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/one.xml?view=auto&rev=157541 ============================================================================== --- cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/one.xml (added) +++ cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/one.xml Tue Mar 15 06:26:31 2005 @@ -0,0 +1,21 @@ +<?xml version="1.0"?> +<!-- + Copyright 2005 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. +--> + +<div style="margin: 5px; border: 1px solid blue;"> + <div style="margin: 1px; background-color: #8888FF;">Page One</div> + This is page number one, with some content in it. +</div> Propchange: cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/one.xml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/one.xml ------------------------------------------------------------------------------ svn:keywords = Id Added: cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/samples.xml URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/samples.xml?view=auto&rev=157541 ============================================================================== --- cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/samples.xml (added) +++ cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/samples.xml Tue Mar 15 06:26:31 2005 @@ -0,0 +1,137 @@ +<?xml version="1.0"?> +<!-- + 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. +--> + +<!-- + - $Id$ + --> +<samples name="Internal Requests Error Handling Samples"> + + <group name="Back"> + <sample name="Back" href="../"> + Back to the error handling samples page. + </sample> + </group> + + <group name="Types of Errors"> + <note> + Request processing in the Cocoon consists of several phases. + First one is pipeline assembly phase, when sitemap processor + traverses sitemaps, finds, and builds a pipeline for the + request. + </note> + <note> + Second phase is the pipeline setup phase, when pipeline is + initialized with the request parameters. + </note> + <note> + Third phase is the pipeline execution phase, when generator + starts streaming SAX events down the pipeline, which end up + in the serializer, writing bytes into the output stream. + </note> + </group> + + <group name="Default Error Handling"> + <sample name="sitemap" href="default-sitemap"> + Exception in the sitemap during pipeline assembly phase + </sample> + <sample name="setup" href="default-setup"> + Exception in the pipeline during setup phase + </sample> + <sample name="pipeline" href="default-pipeline"> + Exception in the pipeline during processing phase + </sample> + </group> + + <group name="Custom Error Handling"> + <sample name="sitemap" href="custom-sitemap"> + Exception in the sitemap during pipeline assembly phase + </sample> + <sample name="setup" href="custom-setup"> + Exception in the pipeline during setup phase + </sample> + <sample name="pipeline" href="custom-pipeline"> + Exception in the pipeline during processing phase + </sample> + </group> + + <group name="Aggregate (Default Error Handling)"> + <note> + Attempt to aggregate several pages, were one contains an error, + with default error handling. + </note> + <sample name="sitemap" href="aggregate/default-sitemap"> + Aggegate Exception in the sitemap during pipeline assembly phase + </sample> + <sample name="setup" href="aggregate/default-setup"> + Aggegate Exception in the pipeline during setup phase + </sample> + <sample name="pipeline" href="aggregate/default-pipeline"> + Aggegate Exception in the pipeline during processing phase + </sample> + </group> + + <group name="Aggregate (Custom Error Handling)"> + <note> + Attempt to aggregate several pages, were one contains an error, + with custom error handling. + </note> + <sample name="sitemap" href="aggregate/custom-sitemap"> + Aggegate Exception in the sitemap during pipeline assembly phase + </sample> + <sample name="setup" href="aggregate/custom-setup"> + Aggegate Exception in the pipeline during setup phase + </sample> + <sample name="pipeline" href="aggregate/custom-pipeline"> + Aggegate Exception in the pipeline during processing phase + </sample> + </group> + + <group name="Include (Default Error Handling)"> + <note> + Attempt to include several pages, were one contains an error, + with default error handling. Include happens after xslt + transformation. + </note> + <sample name="sitemap" href="include/default-sitemap"> + Include Exception in the sitemap during pipeline assembly phase + </sample> + <sample name="setup" href="include/default-setup"> + Include Exception in the pipeline during setup phase + </sample> + <sample name="pipeline" href="include/default-pipeline"> + Include Exception in the pipeline during processing phase + </sample> + </group> + + <group name="Include (Custom Error Handling)"> + <note> + Attempt to include several pages, were one contains an error, + with custom error handling. Include happens after xslt + transformation. + </note> + <sample name="sitemap" href="include/custom-sitemap"> + Include Exception in the sitemap during pipeline assembly phase + </sample> + <sample name="setup" href="include/custom-setup"> + Include Exception in the pipeline during setup phase + </sample> + <sample name="pipeline" href="include/custom-pipeline"> + Include Exception in the pipeline during processing phase + </sample> + </group> + +</samples> Propchange: cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/samples.xml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/samples.xml ------------------------------------------------------------------------------ svn:keywords = Id Added: cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/sitemap.xmap URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/sitemap.xmap?view=auto&rev=157541 ============================================================================== --- cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/sitemap.xmap (added) +++ cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/sitemap.xmap Tue Mar 15 06:26:31 2005 @@ -0,0 +1,96 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright 1999-2005 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. +--> + +<!--+ + | Demonstrates internal pipeline error handling. + | + | $Id$ + +--> +<map:sitemap xmlns:map="http://apache.org/cocoon/sitemap/1.0"> + <map:pipelines> + + <map:pipeline> + <map:match pattern="default-sitemap"> + <map:act type="exception" src="validation"/> + </map:match> + <map:match pattern="default-setup"> + <map:generate type="exception" src="validation"> + <map:parameter name="setup" value="true"/> + </map:generate> + <map:serialize type="xml"/> + </map:match> + <map:match pattern="default-pipeline"> + <map:generate type="exception" src="validation"/> + <map:serialize type="xml"/> + </map:match> + </map:pipeline> + + <map:pipeline> + <map:match pattern="custom-sitemap"> + <map:act type="exception" src="validation"/> + </map:match> + <map:match pattern="custom-setup"> + <map:generate type="exception" src="validation"> + <map:parameter name="setup" value="true"/> + </map:generate> + <map:serialize type="xml"/> + </map:match> + <map:match pattern="custom-pipeline"> + <map:generate type="exception" src="validation"/> + <map:serialize type="xml"/> + </map:match> + <map:handle-errors when="always"> + <map:generate type="notifying"/> + <map:transform src="error2xml.xslt"/> + <map:serialize type="html"/> + </map:handle-errors> + </map:pipeline> + + <map:pipeline> + <map:match pattern=""> + <map:redirect-to uri="welcome"/> + </map:match> + + <map:match pattern="welcome"> + <map:generate src="samples.xml"/> + <map:transform src="context://samples/common/style/xsl/html/simple-samples2html.xsl"> + <map:parameter name="contextPath" value="{request:contextPath}"/> + </map:transform> + <map:serialize/> + </map:match> + + <map:match pattern="aggregate/*"> + <map:aggregate element="html"> + <map:part src="one.xml"/> + <map:part src="cocoon:/{1}"/> + <map:part src="two.xml"/> + </map:aggregate> + <map:serialize type="html"/> + </map:match> + + <map:match pattern="include/*"> + <map:generate src="one.xml"/> + <map:transform src="include.xslt"> + <map:parameter name="uri" value="{1}"/> + </map:transform> + <map:transform type="cinclude"/> + <map:serialize type="html"/> + </map:match> + </map:pipeline> + + </map:pipelines> +</map:sitemap> Propchange: cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/sitemap.xmap ------------------------------------------------------------------------------ svn:eol-style = native Propchange: cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/sitemap.xmap ------------------------------------------------------------------------------ svn:keywords = Id Added: cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/two.xml URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/two.xml?view=auto&rev=157541 ============================================================================== --- cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/two.xml (added) +++ cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/two.xml Tue Mar 15 06:26:31 2005 @@ -0,0 +1,21 @@ +<?xml version="1.0"?> +<!-- + Copyright 2005 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. +--> + +<div style="margin: 5px; border: 1px solid green;"> + <div style="margin: 1px; background-color: #88FF88;">Page Two</div> + This is page number two, with some content in it, too. +</div> Propchange: cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/two.xml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/two.xml ------------------------------------------------------------------------------ svn:keywords = Id Modified: cocoon/branches/BRANCH_2_1_X/status.xml URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/status.xml?view=diff&r1=157540&r2=157541 ============================================================================== --- cocoon/branches/BRANCH_2_1_X/status.xml (original) +++ cocoon/branches/BRANCH_2_1_X/status.xml Tue Mar 15 06:26:31 2005 @@ -202,6 +202,29 @@ <changes> <release version="@version@" date="@date@"> + <action dev="VG" type="add"> + Implemented error handling for the internal requests. Error handling for + the internal requests configured using <code>when</code> attribute on + the <code>handle-errors</code> element. Supported values are: <ul> + <li><code>external</code>: This error handler should be used only on + external requests (default);</li> + <li><code>internal</code>: This error handler should be used only on + internal requests;</li> + <li><code>always</code>: This error handler can be used for all + requests.</li> + </ul> + Currently, if internal error handling is enabled, only inner most error handler + will be used for errors which happened during internal pipeline + processing. + </action> + <action dev="VG" type="fix"> + Sitemap now properly throws ResourceNotFound exception for not matched + requests even if last pipeline marked as an internal pipeline. + </action> + <action dev="VG" type="fix"> + Sitemap handle-errors now reports an error if generator is missing, or + if type attribute (deprecated) specified and generator is present. + </action> <action dev="AG" type="update"> Updated quartz to 1.4.5, jcs to 1.2.5-dev-20050313. </action>