You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by vg...@apache.org on 2005/03/15 16:49:37 UTC

svn commit: r157555 - in cocoon/trunk: ./ src/java/org/apache/cocoon/components/pipeline/ src/java/org/apache/cocoon/components/pipeline/impl/ src/java/org/apache/cocoon/components/treeprocessor/sitemap/ src/java/org/apache/cocoon/sitemap/ src/samples/org/apache/cocoon/samples/errorhandling/ src/webapp/samples/errorhandling/internal/

Author: vgritsenko
Date: Tue Mar 15 07:49:32 2005
New Revision: 157555

URL: http://svn.apache.org/viewcvs?view=rev&rev=157555
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/trunk/src/java/org/apache/cocoon/sitemap/SitemapErrorHandler.java   (contents, props changed)
      - copied, changed from r157541, cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/sitemap/SitemapErrorHandler.java
    cocoon/trunk/src/webapp/samples/errorhandling/internal/
      - copied from r157541, cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/
    cocoon/trunk/src/webapp/samples/errorhandling/internal/error2xml.xslt   (props changed)
      - copied unchanged from r157541, cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/error2xml.xslt
    cocoon/trunk/src/webapp/samples/errorhandling/internal/include.xslt   (props changed)
      - copied unchanged from r157541, cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/include.xslt
    cocoon/trunk/src/webapp/samples/errorhandling/internal/one.xml   (props changed)
      - copied unchanged from r157541, cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/one.xml
    cocoon/trunk/src/webapp/samples/errorhandling/internal/samples.xml   (props changed)
      - copied unchanged from r157541, cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/samples.xml
    cocoon/trunk/src/webapp/samples/errorhandling/internal/sitemap.xmap   (props changed)
      - copied unchanged from r157541, cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/sitemap.xmap
    cocoon/trunk/src/webapp/samples/errorhandling/internal/two.xml   (props changed)
      - copied unchanged from r157541, cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/two.xml
Modified:
    cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/AbstractProcessingPipeline.java
    cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/ProcessingPipeline.java
    cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/VirtualProcessingPipeline.java
    cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/impl/AbstractCachingProcessingPipeline.java
    cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ErrorHandlerHelper.java
    cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/HandleErrorsNode.java
    cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/HandleErrorsNodeBuilder.java
    cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/MountNode.java
    cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/PipelineNode.java
    cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/PipelineNodeBuilder.java
    cocoon/trunk/src/samples/org/apache/cocoon/samples/errorhandling/ExceptionGenerator.java
    cocoon/trunk/status.xml

Modified: cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/AbstractProcessingPipeline.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/AbstractProcessingPipeline.java?view=diff&r1=157554&r2=157555
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/AbstractProcessingPipeline.java (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/AbstractProcessingPipeline.java Tue Mar 15 07:49:32 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;
@@ -86,6 +88,10 @@
     protected String readerSource;
     protected String readerMimeType;
 
+    // Error handler stuff
+    private SitemapErrorHandler errorHandler;
+    private Processor.InternalPipelineDescription errorPipeline;
+
     /** True when pipeline has been prepared. */
     private boolean prepared;
 
@@ -108,7 +114,7 @@
     protected long configuredExpires;
 
     /** Configured Output Buffer Size */
-    protected int  configuredOutputBufferSize;
+    protected int configuredOutputBufferSize;
 
     /** The parameters */
     protected Parameters parameters;
@@ -192,7 +198,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 +
@@ -222,7 +228,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
@@ -246,7 +252,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
@@ -278,7 +284,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
@@ -301,6 +307,14 @@
         this.readerMimeType = mimeType;
     }
 
+    /**
+     * 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
@@ -459,7 +473,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.processingPipeline.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;
     }
 
     /**
@@ -650,6 +695,13 @@
         this.parameters = null;
         this.processor = null;
         this.lastConsumer = null;
+
+        // Release error handler
+        this.errorHandler = null;
+        if (this.errorPipeline != null) {
+            this.errorPipeline.release();
+            this.errorPipeline = null;
+        }
     }
 
     /**
@@ -658,13 +710,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.processingPipeline.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.processingPipeline.prepareInternal(environment);
+                    return this.errorPipeline.processingPipeline.process(environment, consumer);
+                }
+            } catch (Exception ignored) {
+                getLogger().debug("Exception in error handler", ignored);
+            }
+        }
+
+        throw e;
     }
 
     /**

Modified: cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/ProcessingPipeline.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/ProcessingPipeline.java?view=diff&r1=157554&r2=157555
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/ProcessingPipeline.java (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/ProcessingPipeline.java Tue Mar 15 07:49:32 2005
@@ -19,6 +19,7 @@
 import org.apache.avalon.framework.service.ServiceManager;
 
 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;
@@ -106,6 +107,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/trunk/src/java/org/apache/cocoon/components/pipeline/VirtualProcessingPipeline.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/VirtualProcessingPipeline.java?view=diff&r1=157554&r2=157555
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/VirtualProcessingPipeline.java (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/VirtualProcessingPipeline.java Tue Mar 15 07:49:32 2005
@@ -33,9 +33,11 @@
 import org.apache.cocoon.serialization.Serializer;
 import org.apache.cocoon.sitemap.SitemapModelComponent;
 import org.apache.cocoon.sitemap.SitemapParameters;
+import org.apache.cocoon.sitemap.SitemapErrorHandler;
 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;
@@ -71,6 +73,10 @@
     protected String serializerSource;
     protected String serializerMimeType;
 
+    // Error handler stuff
+    private SitemapErrorHandler errorHandler;
+    private Processor.InternalPipelineDescription errorPipeline;
+
     /**
      * True when pipeline has been prepared.
      */
@@ -96,7 +102,7 @@
         this.resolver = (EnvironmentHelper) context.get(Constants.CONTEXT_ENV_HELPER);
     }
 
-    public void service (ServiceManager manager)
+    public void service(ServiceManager manager)
     throws ServiceException {
         this.manager = manager;
         this.newManager = manager;
@@ -105,7 +111,7 @@
     /**
      * Set the processor's service manager
      */
-    public void setProcessorManager (ServiceManager manager) {
+    public void setProcessorManager(ServiceManager manager) {
         this.newManager = manager;
     }
 
@@ -141,7 +147,7 @@
      * @param param the parameters for the generator.
      * @throws org.apache.cocoon.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 +
@@ -169,7 +175,7 @@
      * @param param the parameters for the transfomer.
      * @throws org.apache.cocoon.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.generator == null) {
             throw new ProcessingException ("Must set a generator before adding transformer '" + role +
@@ -189,7 +195,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
@@ -214,6 +220,15 @@
     }
 
     /**
+     * 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
      * @return true if the pipeline is 'sane', false otherwise.
      */
@@ -326,7 +341,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.processingPipeline.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;
     }
 
     public void setReader(String role, String source, Parameters param, String mimeType) throws ProcessingException {
@@ -382,6 +428,13 @@
         this.serializer = null;
         this.processor = null;
         this.lastConsumer = null;
+
+        // Release error handler
+        this.errorHandler = null;
+        if (this.errorPipeline != null) {
+            this.errorPipeline.release();
+            this.errorPipeline = null;
+        }
     }
 
     /**
@@ -390,9 +443,46 @@
      */
     public boolean process(Environment environment, XMLConsumer consumer)
     throws ProcessingException {
-        this.lastConsumer = consumer;
-        connectPipeline(environment);
-        return processXMLPipeline(environment);
+        // Exception happened during setup and was handled
+        if (this.errorPipeline != null) {
+            return this.errorPipeline.processingPipeline.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.processingPipeline.prepareInternal(environment);
+                    return this.errorPipeline.processingPipeline.process(environment, consumer);
+                }
+            } catch (Exception ignored) {
+                getLogger().debug("Exception in error handler", ignored);
+            }
+        }
+
+        throw e;
     }
 
     /**

Modified: cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/impl/AbstractCachingProcessingPipeline.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/impl/AbstractCachingProcessingPipeline.java?view=diff&r1=157554&r2=157555
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/impl/AbstractCachingProcessingPipeline.java (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/impl/AbstractCachingProcessingPipeline.java Tue Mar 15 07:49:32 2005
@@ -790,6 +790,10 @@
      * Otherwise return <code>null</code>
      */
     public SourceValidity getValidityForEventPipeline() {
+        if (isInternalError()) {
+            return null;
+        }
+
         if (this.cachedResponse != null) {
             if (this.toCacheSourceValidities != null) {
                 // This means the pipeline is valid based on the validities
@@ -832,16 +836,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/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ErrorHandlerHelper.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ErrorHandlerHelper.java?view=diff&r1=157554&r2=157555
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ErrorHandlerHelper.java (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ErrorHandlerHelper.java Tue Mar 15 07:49:32 2005
@@ -22,6 +22,7 @@
 import org.apache.avalon.framework.service.Serviceable;
 
 import org.apache.cocoon.Constants;
+import org.apache.cocoon.Processor;
 import org.apache.cocoon.ResourceNotFoundException;
 import org.apache.cocoon.components.notification.Notifying;
 import org.apache.cocoon.components.notification.NotifyingBuilder;
@@ -38,7 +39,7 @@
  *
  * @author <a href="mailto:juergen.seitz@basf-it-services.com">J&uuml;rgen Seitz</a>
  * @author <a href="mailto:bluetkemeier@s-und-n.de">Bj&ouml;rn L&uuml;tkemeier</a>
- * @version CVS $Id$
+ * @version $Id$
  */
 public class ErrorHandlerHelper extends AbstractLogEnabled
                                 implements Serviceable {
@@ -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 Processor.InternalPipelineDescription 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 Processor.InternalPipelineDescription 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.getInternalPipelineDescription(env);
                 }
             } 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, ServiceException {
         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/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/HandleErrorsNode.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/HandleErrorsNode.java?view=diff&r1=157554&r2=157555
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/HandleErrorsNode.java (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/HandleErrorsNode.java Tue Mar 15 07:49:32 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 &lt;map:handle-errors&gt;
  *
  * @author <a href="mailto:sylvain@apache.org">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/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/HandleErrorsNodeBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/HandleErrorsNodeBuilder.java?view=diff&r1=157554&r2=157555
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/HandleErrorsNodeBuilder.java (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/HandleErrorsNodeBuilder.java Tue Mar 15 07:49:32 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 &lt;map:handle-errors&gt;
  *
  * @author <a href="mailto:sylvain@apache.org">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/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/MountNode.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/MountNode.java?view=diff&r1=157554&r2=157555
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/MountNode.java (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/MountNode.java Tue Mar 15 07:49:32 2005
@@ -127,7 +127,8 @@
         }
     }
 
-    private synchronized TreeProcessor getProcessor(String source, String prefix) throws Exception {
+    private synchronized TreeProcessor getProcessor(String source, String prefix)
+    throws Exception {
 
         TreeProcessor processor = (TreeProcessor) processors.get(source);
         if (processor == null) {

Modified: cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/PipelineNode.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/PipelineNode.java?view=diff&r1=157554&r2=157555
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/PipelineNode.java (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/PipelineNode.java Tue Mar 15 07:49:32 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/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/PipelineNodeBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/PipelineNodeBuilder.java?view=diff&r1=157554&r2=157555
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/PipelineNodeBuilder.java (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/PipelineNodeBuilder.java Tue Mar 15 07:49:32 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 &lt;map:pipeline&gt;
+ *
  * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
  * @author <a href="mailto:gianugo@apache.org">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);
         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;
     }
-
-
-
 }
-

Copied: cocoon/trunk/src/java/org/apache/cocoon/sitemap/SitemapErrorHandler.java (from r157541, cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/sitemap/SitemapErrorHandler.java)
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/sitemap/SitemapErrorHandler.java?view=diff&rev=157555&p1=cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/sitemap/SitemapErrorHandler.java&r1=157541&p2=cocoon/trunk/src/java/org/apache/cocoon/sitemap/SitemapErrorHandler.java&r2=157555
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/sitemap/SitemapErrorHandler.java (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/sitemap/SitemapErrorHandler.java Tue Mar 15 07:49:32 2005
@@ -15,9 +15,9 @@
  */
 package org.apache.cocoon.sitemap;
 
+import org.apache.cocoon.Processor;
 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;
 
 /**
@@ -46,7 +46,6 @@
     // Environment state
     private String envPrefix;
     private String envURI;
-    private String envContext;
 
     /**
      * Construct error handler with everything needed to handle an error.
@@ -60,7 +59,6 @@
 
         this.envPrefix = environment.getURIPrefix();
         this.envURI = environment.getURI();
-        this.envContext = environment.getContext();
     }
 
     /**
@@ -69,7 +67,7 @@
      */
     public boolean handleError(Exception e) throws Exception {
         // Restore environment state
-        this.environment.setContext(this.envPrefix, this.envURI, this.envContext);
+        this.environment.setURI(this.envPrefix, this.envURI);
 
         return this.handler.invokeErrorHandler(e, this.environment, this.context);
     }
@@ -78,9 +76,9 @@
      * Build error handling pipeline.
      * @return error handling pipeline, or null if error was not handled.
      */
-    public ProcessingPipeline prepareErrorPipeline(Exception e) throws Exception {
+    public Processor.InternalPipelineDescription prepareErrorPipeline(Exception e) throws Exception {
         // Restore environment state
-        this.environment.setContext(this.envPrefix, this.envURI, this.envContext);
+        this.environment.setURI(this.envPrefix, this.envURI);
 
         return this.handler.prepareErrorHandler(e, this.environment, this.context);
     }

Propchange: cocoon/trunk/src/java/org/apache/cocoon/sitemap/SitemapErrorHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/src/java/org/apache/cocoon/sitemap/SitemapErrorHandler.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: cocoon/trunk/src/samples/org/apache/cocoon/samples/errorhandling/ExceptionGenerator.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/samples/org/apache/cocoon/samples/errorhandling/ExceptionGenerator.java?view=diff&r1=157554&r2=157555
==============================================================================
--- cocoon/trunk/src/samples/org/apache/cocoon/samples/errorhandling/ExceptionGenerator.java (original)
+++ cocoon/trunk/src/samples/org/apache/cocoon/samples/errorhandling/ExceptionGenerator.java Tue Mar 15 07:49:32 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");

Copied: cocoon/trunk/src/webapp/samples/errorhandling/internal/error2xml.xslt (from r157541, cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/error2xml.xslt)
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/webapp/samples/errorhandling/internal/error2xml.xslt?view=diff&rev=157555&p1=cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/error2xml.xslt&r1=157541&p2=cocoon/trunk/src/webapp/samples/errorhandling/internal/error2xml.xslt&r2=157555
==============================================================================
    (empty)

Propchange: cocoon/trunk/src/webapp/samples/errorhandling/internal/error2xml.xslt
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/src/webapp/samples/errorhandling/internal/error2xml.xslt
------------------------------------------------------------------------------
    svn:keywords = Id

Copied: cocoon/trunk/src/webapp/samples/errorhandling/internal/include.xslt (from r157541, cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/include.xslt)
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/webapp/samples/errorhandling/internal/include.xslt?view=diff&rev=157555&p1=cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/include.xslt&r1=157541&p2=cocoon/trunk/src/webapp/samples/errorhandling/internal/include.xslt&r2=157555
==============================================================================
    (empty)

Propchange: cocoon/trunk/src/webapp/samples/errorhandling/internal/include.xslt
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/src/webapp/samples/errorhandling/internal/include.xslt
------------------------------------------------------------------------------
    svn:keywords = Id

Copied: cocoon/trunk/src/webapp/samples/errorhandling/internal/one.xml (from r157541, cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/one.xml)
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/webapp/samples/errorhandling/internal/one.xml?view=diff&rev=157555&p1=cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/one.xml&r1=157541&p2=cocoon/trunk/src/webapp/samples/errorhandling/internal/one.xml&r2=157555
==============================================================================
    (empty)

Propchange: cocoon/trunk/src/webapp/samples/errorhandling/internal/one.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/src/webapp/samples/errorhandling/internal/one.xml
------------------------------------------------------------------------------
    svn:keywords = Id

Copied: cocoon/trunk/src/webapp/samples/errorhandling/internal/samples.xml (from r157541, cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/samples.xml)
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/webapp/samples/errorhandling/internal/samples.xml?view=diff&rev=157555&p1=cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/samples.xml&r1=157541&p2=cocoon/trunk/src/webapp/samples/errorhandling/internal/samples.xml&r2=157555
==============================================================================
    (empty)

Propchange: cocoon/trunk/src/webapp/samples/errorhandling/internal/samples.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/src/webapp/samples/errorhandling/internal/samples.xml
------------------------------------------------------------------------------
    svn:keywords = Id

Copied: cocoon/trunk/src/webapp/samples/errorhandling/internal/sitemap.xmap (from r157541, cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/sitemap.xmap)
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/webapp/samples/errorhandling/internal/sitemap.xmap?view=diff&rev=157555&p1=cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/sitemap.xmap&r1=157541&p2=cocoon/trunk/src/webapp/samples/errorhandling/internal/sitemap.xmap&r2=157555
==============================================================================
    (empty)

Propchange: cocoon/trunk/src/webapp/samples/errorhandling/internal/sitemap.xmap
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/src/webapp/samples/errorhandling/internal/sitemap.xmap
------------------------------------------------------------------------------
    svn:keywords = Id

Copied: cocoon/trunk/src/webapp/samples/errorhandling/internal/two.xml (from r157541, cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/two.xml)
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/webapp/samples/errorhandling/internal/two.xml?view=diff&rev=157555&p1=cocoon/branches/BRANCH_2_1_X/src/webapp/samples/errorhandling/internal/two.xml&r1=157541&p2=cocoon/trunk/src/webapp/samples/errorhandling/internal/two.xml&r2=157555
==============================================================================
    (empty)

Propchange: cocoon/trunk/src/webapp/samples/errorhandling/internal/two.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/src/webapp/samples/errorhandling/internal/two.xml
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: cocoon/trunk/status.xml
URL: http://svn.apache.org/viewcvs/cocoon/trunk/status.xml?view=diff&r1=157554&r2=157555
==============================================================================
--- cocoon/trunk/status.xml (original)
+++ cocoon/trunk/status.xml Tue Mar 15 07:49:32 2005
@@ -429,6 +429,29 @@
    </action>
  </release>
  <release version="2.1.7" date="TBD">
+   <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>