You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by sy...@apache.org on 2005/08/01 15:10:22 UTC

svn commit: r226786 - in /cocoon/branches/BRANCH_2_1_X: ./ src/java/org/apache/cocoon/ src/java/org/apache/cocoon/components/flow/ src/java/org/apache/cocoon/components/notification/ src/java/org/apache/cocoon/components/treeprocessor/sitemap/ src/java...

Author: sylvain
Date: Mon Aug  1 06:10:02 2005
New Revision: 226786

URL: http://svn.apache.org/viewcvs?rev=226786&view=rev
Log:
Cocoon stacktraces: new location handling stuff and refactored exception management

Added:
    cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/generation/ExceptionGenerator.java   (with props)
    cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/ExceptionUtils.java   (with props)
    cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/Locatable.java   (with props)
    cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/LocatableException.java   (with props)
    cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/LocatedException.java   (with props)
    cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/LocatedRuntimeException.java   (with props)
    cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/Location.java   (with props)
    cocoon/branches/BRANCH_2_1_X/src/test/org/apache/cocoon/util/location/
    cocoon/branches/BRANCH_2_1_X/src/test/org/apache/cocoon/util/location/LocationTestCase.java   (with props)
    cocoon/branches/BRANCH_2_1_X/src/webapp/stylesheets/system/exception2html.xslt   (with props)
Modified:
    cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/ConnectionResetException.java
    cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/ProcessingException.java
    cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/ResourceNotFoundException.java
    cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/flow/InvalidContinuationException.java
    cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/notification/DefaultNotifyingBuilder.java
    cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/CallFunctionNode.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/SerializeNode.java
    cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/selection/ExceptionSelector.java
    cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/LocationAttributes.java
    cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/log/CocoonLogFormatter.java
    cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/xml/AbstractXMLPipe.java
    cocoon/branches/BRANCH_2_1_X/src/webapp/sitemap.xmap
    cocoon/branches/BRANCH_2_1_X/status.xml

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/ConnectionResetException.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/ConnectionResetException.java?rev=226786&r1=226785&r2=226786&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/ConnectionResetException.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/ConnectionResetException.java Mon Aug  1 06:10:02 2005
@@ -20,7 +20,7 @@
  * due to a connection reset by peer.
  *
  * @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
- * @version CVS $Id: ConnectionResetException.java,v 1.2 2004/03/05 13:02:42 bdelacretaz Exp $
+ * @version CVS $Id$
  */
 public class ConnectionResetException extends ProcessingException {
 
@@ -30,7 +30,7 @@
      * @param message a <code>String</code> value
      */
     public ConnectionResetException(String message) {
-        super(message, null);
+        super(message);
     }
 
     /**

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/ProcessingException.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/ProcessingException.java?rev=226786&r1=226785&r2=226786&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/ProcessingException.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/ProcessingException.java Mon Aug  1 06:10:02 2005
@@ -15,14 +15,17 @@
  */
 package org.apache.cocoon;
 
-import org.apache.avalon.framework.CascadingException;
-
 import java.io.PrintStream;
 import java.io.PrintWriter;
 
-import org.xml.sax.SAXParseException;
-import javax.xml.transform.TransformerException;
 import javax.xml.transform.SourceLocator;
+import javax.xml.transform.TransformerException;
+
+import org.apache.avalon.framework.CascadingException;
+import org.apache.cocoon.util.location.Locatable;
+import org.apache.cocoon.util.location.LocatedException;
+import org.apache.cocoon.util.location.Location;
+import org.xml.sax.SAXParseException;
 
 /**
  * This Exception is thrown every time there is a problem in processing
@@ -30,15 +33,15 @@
  *
  * @author <a href="mailto:pier@apache.org">Pierpaolo Fumagalli</a>
  *         (Apache Software Foundation)
- * @version CVS $Id: ProcessingException.java,v 1.2 2004/03/05 13:02:42 bdelacretaz Exp $
+ * @version CVS $Id$
  */
-public class ProcessingException extends CascadingException {
-    
+public class ProcessingException extends LocatedException {
+
     /**
      * Construct a new <code>ProcessingException</code> instance.
      */
     public ProcessingException(String message) {
-        super(message, null);
+        super(message);
     }
     
     /**
@@ -58,71 +61,79 @@
         super(message, t);
     }
     
-    public String toString() {
-        StringBuffer s = new StringBuffer();
-        s.append(super.toString());
-        final Throwable t = getCause();
-        if(t!=null) {
-            s.append(": ");
-            // be more verbose try to get location info
-            s.append( extraInfo(t) );
-            s.append(t.toString());
-        }
-        return s.toString();
+    public ProcessingException(String message, Location location) {
+        super(message, location);
     }
     
-    /**
-     * Examine Throwable and try to figure out location information.
-     * <p>
-     *   At the moment only SAXParseException, and TransformerException
-     *   are considered.
-     * </p>
-     *
-     * @return String containing location information of the format
-     *  <code>{file-name}:{line}:{column}:</code>, if no location info is 
-     *  available return empty string
-     */
-    private String extraInfo( Throwable t ) {
-        StringBuffer sb = new StringBuffer();
-        if (t instanceof SAXParseException) {
-            SAXParseException spe = (SAXParseException)t;
-            sb.append( String.valueOf(spe.getSystemId()));
-            sb.append( ":" );
-            sb.append( String.valueOf(spe.getLineNumber()));
-            sb.append( ":" );
-            sb.append( String.valueOf(spe.getColumnNumber()));
-            sb.append( ":" );
-        } else if (t instanceof TransformerException) {
-            TransformerException transformerException = (TransformerException) t;
-            SourceLocator sourceLocator = transformerException.getLocator();
-            
-            if( null != sourceLocator ) {
-                sb.append( String.valueOf(sourceLocator.getSystemId()));
-                sb.append( ":" );
-                sb.append( String.valueOf(sourceLocator.getLineNumber()));
-                sb.append( ":" );
-                sb.append( String.valueOf(sourceLocator.getColumnNumber()));
-                sb.append( ":" );
-            }
-        }
-        return sb.toString();
+    public ProcessingException(String message, Throwable t, Location location) {
+        super(message, t, location);
     }
     
-    public void printStackTrace() {
-        super.printStackTrace();
-        if(getCause()!=null)
-            getCause().printStackTrace();
-    }
-    
-    public void printStackTrace( PrintStream s ) {
-        super.printStackTrace(s);
-        if(getCause()!=null)
-            getCause().printStackTrace(s);
-    }
-    
-    public void printStackTrace( PrintWriter s ) {
-        super.printStackTrace(s);
-        if(getCause()!=null)
-            getCause().printStackTrace(s);
-    }
+//    public String toString() {
+//        StringBuffer s = new StringBuffer();
+//        s.append(super.toString());
+//        final Throwable t = getCause();
+//        if(t!=null) {
+//            s.append(": ");
+//            // be more verbose try to get location info
+//            s.append( extraInfo(t) );
+//            s.append(t.toString());
+//        }
+//        return s.toString();
+//    }
+//    
+//    /**
+//     * Examine Throwable and try to figure out location information.
+//     * <p>
+//     *   At the moment only SAXParseException, and TransformerException
+//     *   are considered.
+//     * </p>
+//     *
+//     * @return String containing location information of the format
+//     *  <code>{file-name}:{line}:{column}:</code>, if no location info is 
+//     *  available return empty string
+//     */
+//    private String extraInfo( Throwable t ) {
+//        StringBuffer sb = new StringBuffer();
+//        if (t instanceof SAXParseException) {
+//            SAXParseException spe = (SAXParseException)t;
+//            sb.append( String.valueOf(spe.getSystemId()));
+//            sb.append( ":" );
+//            sb.append( String.valueOf(spe.getLineNumber()));
+//            sb.append( ":" );
+//            sb.append( String.valueOf(spe.getColumnNumber()));
+//            sb.append( ":" );
+//        } else if (t instanceof TransformerException) {
+//            TransformerException transformerException = (TransformerException) t;
+//            SourceLocator sourceLocator = transformerException.getLocator();
+//            
+//            if( null != sourceLocator ) {
+//                sb.append( String.valueOf(sourceLocator.getSystemId()));
+//                sb.append( ":" );
+//                sb.append( String.valueOf(sourceLocator.getLineNumber()));
+//                sb.append( ":" );
+//                sb.append( String.valueOf(sourceLocator.getColumnNumber()));
+//                sb.append( ":" );
+//            }
+//        }
+//        return sb.toString();
+//    }
+//    
+//    public void printStackTrace() {
+//        super.printStackTrace();
+//        if(getCause()!=null)
+//            getCause().printStackTrace();
+//    }
+//    
+//    public void printStackTrace( PrintStream s ) {
+//        super.printStackTrace(s);
+//        if(getCause()!=null)
+//            getCause().printStackTrace(s);
+//    }
+//    
+//    public void printStackTrace( PrintWriter s ) {
+//        super.printStackTrace(s);
+//        if(getCause()!=null)
+//            getCause().printStackTrace(s);
+//    }
 }

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/ResourceNotFoundException.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/ResourceNotFoundException.java?rev=226786&r1=226785&r2=226786&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/ResourceNotFoundException.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/ResourceNotFoundException.java Mon Aug  1 06:10:02 2005
@@ -15,12 +15,14 @@
  */
 package org.apache.cocoon;
 
+import org.apache.cocoon.util.location.Location;
+
 /**
  * This Exception is thrown every time there is a problem in finding
  * a resource.
  *
  * @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
- * @version CVS $Id: ResourceNotFoundException.java,v 1.2 2004/03/05 13:02:42 bdelacretaz Exp $
+ * @version CVS $Id$
  */
 public class ResourceNotFoundException extends ProcessingException {
 
@@ -28,7 +30,7 @@
      * Construct a new <code>ResourceNotFoundException</code> instance.
      */
     public ResourceNotFoundException(String message) {
-        super(message, null);
+        super(message);
     }
 
     /**
@@ -37,5 +39,13 @@
      */
     public ResourceNotFoundException(String message, Throwable t) {
         super(message, t);
+    }
+    
+    public ResourceNotFoundException(String message, Location location) {
+        super(message, location);
+    }
+    
+    public ResourceNotFoundException(String message, Throwable t, Location loc) {
+        super(message, t, loc);
     }
 }

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/flow/InvalidContinuationException.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/flow/InvalidContinuationException.java?rev=226786&r1=226785&r2=226786&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/flow/InvalidContinuationException.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/flow/InvalidContinuationException.java Mon Aug  1 06:10:02 2005
@@ -21,7 +21,7 @@
  * This Exception is thrown whenever an invalid continuation is given.
  *
  * @author <a href="mailto:tcollen@neuagency.com">Tony Collen</a>
- * @version CVS $Id: InvalidContinuationException.java,v 1.2 2004/03/05 13:02:46 bdelacretaz Exp $
+ * @version CVS $Id$
  */
 public class InvalidContinuationException extends ProcessingException {
 
@@ -29,7 +29,7 @@
      * Construct a new <code>InvalidContinuationException</code> instance.
      */
     public InvalidContinuationException(String message) {
-        super(message, null);
+        super(message);
     }
 
     /**

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/notification/DefaultNotifyingBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/notification/DefaultNotifyingBuilder.java?rev=226786&r1=226785&r2=226786&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/notification/DefaultNotifyingBuilder.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/notification/DefaultNotifyingBuilder.java Mon Aug  1 06:10:02 2005
@@ -17,8 +17,8 @@
 
 import org.apache.avalon.framework.component.Component;
 
+import org.apache.cocoon.util.ExceptionUtils;
 import org.apache.commons.lang.SystemUtils;
-import org.apache.commons.lang.exception.ExceptionUtils;
 import org.xml.sax.SAXParseException;
 
 import javax.xml.transform.SourceLocator;

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/CallFunctionNode.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/CallFunctionNode.java?rev=226786&r1=226785&r2=226786&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/CallFunctionNode.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/CallFunctionNode.java Mon Aug  1 06:10:02 2005
@@ -35,6 +35,7 @@
 import org.apache.cocoon.environment.Environment;
 import org.apache.cocoon.environment.Redirector;
 import org.apache.cocoon.sitemap.PatternException;
+import org.apache.cocoon.util.location.Location;
 
 /**
  * Node handler for calling functions and resuming continuations in
@@ -120,10 +121,13 @@
         // the function call, so we invoke it here.
         String continuation = continuationId.resolve(context, env.getObjectModel());
         if (continuation != null && continuation.length() > 0) {
-            interpreter.handleContinuation(continuation, params, redirector);
+            try {
+                interpreter.handleContinuation(continuation, params, redirector);
+            } catch(Exception e) {
+                throw new ProcessingException("Sitemap: error calling continuation", e, Location.parse(getLocation()));
+            }
             if (!redirector.hasRedirected()) {
-                throw new ProcessingException("<map:call continuation> did not send a response, at " +
-                                              getLocation());
+                throw new ProcessingException("Sitemap: <map:call continuation> did not send a response", Location.parse(getLocation()));
             }
             return true;
         }
@@ -132,15 +136,18 @@
         // the specified function
         String name = functionName.resolve(context, env.getObjectModel());
         if (name != null && name.length() > 0) {
-            interpreter.callFunction(name, params, redirector);
+            try {
+                interpreter.callFunction(name, params, redirector);
+            } catch(Exception e) {
+                throw new ProcessingException("Sitemap: error calling function '" + name + "'", e, Location.parse(getLocation()));
+            }
             if (!redirector.hasRedirected()) {
-                throw new ProcessingException("<map:call function> did not send a response, at " +
-                                              getLocation());
+                throw new ProcessingException("Sitemap: <map:call function> did not send a response", Location.parse(getLocation()));
             }
             return true;
         }
 
         // Found neither continuation nor function to call
-        throw new ProcessingException("No function nor continuation given in <map:call function> at " + getLocation());
+        throw new ProcessingException("Sitemap: no function nor continuation given in <map:call function>", Location.parse(getLocation()));
     }
 }

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?rev=226786&r1=226785&r2=226786&view=diff
==============================================================================
--- 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 Mon Aug  1 06:10:02 2005
@@ -30,6 +30,7 @@
 import org.apache.cocoon.components.treeprocessor.TreeProcessor;
 import org.apache.cocoon.components.treeprocessor.variables.VariableResolver;
 import org.apache.cocoon.environment.Environment;
+import org.apache.cocoon.util.location.Location;
 import org.apache.commons.lang.BooleanUtils;
 
 /**
@@ -116,6 +117,10 @@
                 // Processor will create its own pipelines
                 pipelineWasBuilt = processor.process(env);
             }
+        } catch(Exception e) {
+            // Wrap with our location
+            throw new ProcessingException("Sitemap: error when calling sub-sitemap", e, Location.parse(getLocation()));
+
         } finally {
             // We restore the context only if no pipeline was built. This allows the pipeline
             // environment to be left unchanged when we go back to ancestor processors.

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/SerializeNode.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/SerializeNode.java?rev=226786&r1=226785&r2=226786&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/SerializeNode.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/sitemap/SerializeNode.java Mon Aug  1 06:10:02 2005
@@ -19,6 +19,7 @@
 
 import org.apache.avalon.framework.parameters.Parameters;
 import org.apache.cocoon.Constants;
+import org.apache.cocoon.ProcessingException;
 import org.apache.cocoon.components.pipeline.ProcessingPipeline;
 import org.apache.cocoon.components.treeprocessor.InvokeContext;
 import org.apache.cocoon.components.treeprocessor.ParameterizableProcessingNode;
@@ -27,11 +28,12 @@
 import org.apache.cocoon.components.treeprocessor.variables.VariableResolver;
 import org.apache.cocoon.environment.Environment;
 import org.apache.cocoon.sitemap.PatternException;
+import org.apache.cocoon.util.location.Location;
 /**
  *
  * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
  * @author <a href="mailto:uv@upaya.co.uk">Upayavira</a>
- * @version CVS $Id: SerializeNode.java,v 1.8 2004/03/05 13:02:52 bdelacretaz Exp $
+ * @version CVS $Id$
  */
 public class SerializeNode extends PipelineEventComponentProcessingNode implements ParameterizableProcessingNode {
 
@@ -117,7 +119,12 @@
 
         if (! context.isBuildingPipelineOnly()) {
             // Process pipeline
-            return pipeline.process(env);
+            try {
+                return pipeline.process(env);
+            } catch(Exception e) {
+                // Indicate error location
+                throw new ProcessingException("Sitemap: error during pipeline execution", e, Location.parse(getLocation()));
+            }
 
         } else {
             // Return true : pipeline is finished.

Added: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/generation/ExceptionGenerator.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/generation/ExceptionGenerator.java?rev=226786&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/generation/ExceptionGenerator.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/generation/ExceptionGenerator.java Mon Aug  1 06:10:02 2005
@@ -0,0 +1,121 @@
+/*
+ * 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.generation;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.SourceResolver;
+import org.apache.cocoon.util.ExceptionUtils;
+import org.apache.cocoon.util.location.LocatableException;
+import org.apache.cocoon.util.location.Location;
+import org.apache.cocoon.xml.AttributesImpl;
+import org.apache.commons.lang.SystemUtils;
+import org.mozilla.javascript.JavaScriptException;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+public class ExceptionGenerator extends AbstractGenerator {
+    
+    private Throwable thr;
+    
+    public static String EXCEPTION_NS = "http://apache.org/cocoon/exception/1.0";
+
+    public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par) throws ProcessingException, SAXException, IOException {
+        super.setup(resolver, objectModel, src, par);
+        thr = (Throwable)objectModel.get(ObjectModelHelper.THROWABLE_OBJECT);
+        if (thr == null) {
+            throw new ProcessingException("ExceptionGenerator should be used in <map:handle-errors>");
+        }
+    }
+
+    public void generate() throws IOException, SAXException, ProcessingException {
+        this.contentHandler.startDocument();
+        toSAX(thr, this.contentHandler);
+        this.contentHandler.endDocument();
+    }
+    
+    public static void toSAX(Throwable thr, ContentHandler handler) throws SAXException {
+        Throwable root = ExceptionUtils.getRootCause(thr);
+        if (root == null) root = thr;
+
+        AttributesImpl attr = new AttributesImpl();
+        handler.startPrefixMapping("ex", EXCEPTION_NS);
+        attr.addCDATAAttribute("class", root.getClass().getName());
+        Location loc = ExceptionUtils.getLocation(root);
+        if (loc != null) {
+            attr.addCDATAAttribute("uri", loc.getURI());
+            attr.addCDATAAttribute("line", Integer.toString(loc.getLine()));
+            attr.addCDATAAttribute("column", Integer.toString(loc.getColumn()));
+        }
+        handler.startElement(EXCEPTION_NS, "exception", "ex:exception", attr);
+
+        // Root exception message
+        attr.clear();
+        textElement("message", attr, root.getMessage(), handler);
+        
+        // Locations
+        handler.startElement(EXCEPTION_NS, "locations", "ex:locations", attr);
+        Throwable current = thr;
+        while (current != null) {
+            loc = ExceptionUtils.getLocation(current);
+            if (loc != null) {
+                attr.clear();
+                attr.addCDATAAttribute("uri", loc.getURI());
+                attr.addCDATAAttribute("line", Integer.toString(loc.getLine()));
+                attr.addCDATAAttribute("column", Integer.toString(loc.getColumn()));
+                
+                // Get raw message for LocatableExceptions, message otherwise
+                String message = current instanceof LocatableException ?
+                        ((LocatableException)current).getRawMessage() :
+                        current.getMessage();
+
+                textElement("location", attr, message, handler);
+            }
+            
+            // Dump parent location
+            current = ExceptionUtils.getCause(current);
+        }
+        
+        handler.endElement(EXCEPTION_NS, "locations", "ex:locations");
+        
+        // Root exception stacktrace
+        attr.clear();
+        textElement("stacktrace", attr, ExceptionUtils.getStackTrace(root), handler);
+        
+        // Full stack trace (if exception is chained)
+        if (thr != root) {
+            String trace = SystemUtils.isJavaVersionAtLeast(140) ?
+                    ExceptionUtils.getStackTrace(thr) :
+                    ExceptionUtils.getFullStackTrace(thr);
+
+            textElement("full-stacktrace", attr, trace, handler);
+        }
+        
+        handler.endElement(EXCEPTION_NS, "exception", "ex:exception");
+        handler.endPrefixMapping("ex");
+    }
+
+    private static void textElement(String name, Attributes attr, String value, ContentHandler handler) throws SAXException {
+        handler.startElement(EXCEPTION_NS, name, "ex:" + name, attr);
+        handler.characters(value.toCharArray(), 0, value.length());
+        handler.endElement(EXCEPTION_NS, name, "ex:" + name);
+    }
+}

Propchange: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/generation/ExceptionGenerator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/generation/ExceptionGenerator.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/selection/ExceptionSelector.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/selection/ExceptionSelector.java?rev=226786&r1=226785&r2=226786&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/selection/ExceptionSelector.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/selection/ExceptionSelector.java Mon Aug  1 06:10:02 2005
@@ -23,7 +23,7 @@
 import org.apache.avalon.framework.parameters.Parameters;
 import org.apache.cocoon.environment.ObjectModelHelper;
 import org.apache.cocoon.util.ClassUtils;
-import org.apache.commons.lang.exception.ExceptionUtils;
+import org.apache.cocoon.util.ExceptionUtils;
 
 /**
  * In a &lt;map:handle-errors>, selects depending on the exception that caused the error.

Added: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/ExceptionUtils.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/ExceptionUtils.java?rev=226786&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/ExceptionUtils.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/ExceptionUtils.java Mon Aug  1 06:10:02 2005
@@ -0,0 +1,129 @@
+/*
+ * 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.util;
+
+import java.util.Vector;
+
+import javax.xml.transform.SourceLocator;
+import javax.xml.transform.TransformerException;
+
+import org.apache.cocoon.util.location.Locatable;
+import org.apache.cocoon.util.location.Location;
+import org.mozilla.javascript.EcmaError;
+import org.mozilla.javascript.JavaScriptException;
+import org.xml.sax.SAXParseException;
+
+/**
+ * This class builds on <a href="http://jakarta.apache.org/commons/lang/">Jakarta Commons Lang</a>'s
+ * <code><a href="http://jakarta.apache.org/commons/lang/api/org/apache/commons/lang/exception/ExceptionUtils.html">ExceptionUtils</a></code>
+ * to handle exception chains, with additional heuristics to unroll exceptions, and other Cocoon-specific stuff
+ * such as getting the {@link Location} of an exception.
+ * 
+ * @version $Id$
+ */
+public class ExceptionUtils extends org.apache.commons.lang.exception.ExceptionUtils {
+
+    /**
+     * Get the cause of a <code>Throwable</code>
+     * 
+     * @param thr the throwable
+     * @return <code>thr</code>'s parent, or <code>null</code> if none exists.
+     */
+    public static final Throwable getCause(Throwable thr) {
+        // Specific case of JavaScriptException, which holds the wrapped exception
+        // in its 'value' property, which ExceptionUtils cannot find
+        if (thr instanceof JavaScriptException) {
+            Object obj = ((JavaScriptException)thr).getValue();
+            if (obj instanceof Throwable) {
+                return (Throwable)obj;
+            } else {
+                return null;
+            }
+        } else {
+            return org.apache.commons.lang.exception.ExceptionUtils.getCause(thr);
+        }
+    }
+
+    /**
+     * Get the root cause of a <code>Throwable</code>.
+     * 
+     * @param thr the throwable
+     * @return <code>thr</code>'s root parent, or <code>null</code> if none exists.
+     */
+   public static final Throwable getRootCause(Throwable thr) {
+       Throwable parent;
+       Throwable current = thr;
+       while ((parent = getCause(current)) != null) {
+           current = parent;
+       }
+       
+       // Return current only if not the original throwable (happens when there's no cause)
+       return current == thr ? null : current;
+   }
+    
+    /**
+     * Get the location of a throwable. Checks various ways to get the exception location.
+     * 
+     * @param thr the throwable
+     * @return the location, or <code>null</code> if it could not be determined
+     */
+    public static Location getLocation(Throwable thr) {
+
+        if (thr instanceof Locatable) {
+            return ((Locatable)thr).getLocation();
+
+        } else if (thr instanceof SAXParseException) {
+            SAXParseException spe = (SAXParseException)thr;
+            if (spe.getSystemId() != null) {
+                return new Location(spe.getSystemId(), spe.getLineNumber(), spe.getColumnNumber());
+            } else {
+                return null;
+            }
+
+        } else if (thr instanceof TransformerException) {
+            TransformerException ex = (TransformerException)thr;
+            SourceLocator locator = ex.getLocator();
+            if (locator != null && locator.getSystemId() != null) {
+                return new Location(locator.getSystemId(), locator.getLineNumber(), locator.getColumnNumber());
+            } else {
+                return null;
+            }
+
+        } else if (thr instanceof EcmaError) {
+            EcmaError ex = (EcmaError)thr;
+            if (ex.getSourceName() != null) {
+                return new Location(ex.getSourceName(), ex.getLineNumber(), ex.getColumnNumber());
+            } else {
+                return null;
+            }
+
+        } else if (thr instanceof JavaScriptException) {
+            JavaScriptException ex = (JavaScriptException)thr;
+            Vector stackTrace = ex.getJSStackTrace();
+            if (stackTrace != null) {
+                // see JavaScriptException.getMessage()
+                int i = stackTrace.size() - 1;
+                String sourceName = (String)stackTrace.elementAt(i-2);
+                int lineNum = ((Integer)stackTrace.elementAt(i)).intValue();
+                return new Location(sourceName, lineNum, -1);
+            } else {
+                return null;
+            }
+        }
+        
+        return null;
+    }
+}

Propchange: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/ExceptionUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/ExceptionUtils.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/Locatable.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/Locatable.java?rev=226786&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/Locatable.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/Locatable.java Mon Aug  1 06:10:02 2005
@@ -0,0 +1,31 @@
+/*
+ * 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.util.location;
+
+/**
+ * A interface that should be implemented by objects knowning their location (i.e. where they
+ * have been created from).
+ * 
+ * @version $Id$
+ */
+public interface Locatable {
+    /**
+     * Get the location of this object
+     * 
+     * @return the location
+     */
+    Location getLocation();
+}

Propchange: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/Locatable.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/Locatable.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/LocatableException.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/LocatableException.java?rev=226786&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/LocatableException.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/LocatableException.java Mon Aug  1 06:10:02 2005
@@ -0,0 +1,39 @@
+/*
+ * 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.util.location;
+
+/**
+ * Extension of {@link Locatable} for exceptions.
+ * <p>
+ * In order to dump location information in the stacktrace, the <code>getMessage()</code> method of
+ * a {@link Locatable} exception should return a concatenation of the raw message (given in the
+ * constructor) and the exception's location, e.g. "<code>foo failed (file.xml:12:3)</code>". However,
+ * {@link Locatable}-aware classes will want to handle the raw message (i.e. "<code>foo failed</code>")
+ * and location separately.
+ * <p>
+ * This interface gives access to the raw message.
+ * 
+ * @version $Id$
+ */
+public interface LocatableException extends Locatable {
+    
+    /**
+     * Get the raw message of the exception (the one used in the constructor)
+     * 
+     * @return the raw message
+     */
+    public String getRawMessage();
+}

Propchange: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/LocatableException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/LocatableException.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/LocatedException.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/LocatedException.java?rev=226786&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/LocatedException.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/LocatedException.java Mon Aug  1 06:10:02 2005
@@ -0,0 +1,59 @@
+/*
+ * 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.util.location;
+
+import org.apache.avalon.framework.CascadingException;
+
+/**
+ * A cascading and located <code>Exception</code>.
+ * 
+ * @version $Id$
+ */
+public class LocatedException extends CascadingException implements LocatableException {
+    
+    private Location location;
+
+    public LocatedException(String message) {
+        super(message, null);
+    }
+    
+    public LocatedException(String message, Throwable thr) {
+        super(message, thr);
+    }
+    
+    public LocatedException(String message, Location location) {
+        super(message, null);
+        this.location = location;
+    }
+    
+    public LocatedException(String message, Throwable thr, Location location) {
+        super(message, thr);
+        this.location = location;
+    }
+
+    public Location getLocation() {
+        return this.location;
+    }
+
+    public String getRawMessage() {
+        return super.getMessage();
+    }
+
+    public String getMessage() {
+        return this.location == null ? super.getMessage() :
+            super.getMessage() + " (" + this.location.toString() + ")";
+    }
+}

Propchange: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/LocatedException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/LocatedException.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/LocatedRuntimeException.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/LocatedRuntimeException.java?rev=226786&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/LocatedRuntimeException.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/LocatedRuntimeException.java Mon Aug  1 06:10:02 2005
@@ -0,0 +1,59 @@
+/*
+ * 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.util.location;
+
+import org.apache.avalon.framework.CascadingRuntimeException;
+
+/**
+ * A cascading and located <code>RuntimeException</code>.
+ * 
+ * @version $Id$
+ */
+public class LocatedRuntimeException extends CascadingRuntimeException implements LocatableException {
+    
+    private Location location;
+
+    public LocatedRuntimeException(String message) {
+        super(message, null);
+    }
+    
+    public LocatedRuntimeException(String message, Throwable thr) {
+        super(message, thr);
+    }
+    
+    public LocatedRuntimeException(String message, Location location) {
+        super(message, null);
+        this.location = location;
+    }
+    
+    public LocatedRuntimeException(String message, Throwable thr, Location location) {
+        super(message, thr);
+        this.location = location;
+    }
+
+    public Location getLocation() {
+        return this.location;
+    }
+
+    public String getRawMessage() {
+        return super.getMessage();
+    }
+
+    public String getMessage() {
+        return this.location == null ? super.getMessage() :
+            super.getMessage() + " (" + this.location.toString() + ")";
+    }
+}

Propchange: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/LocatedRuntimeException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/LocatedRuntimeException.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/Location.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/Location.java?rev=226786&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/Location.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/Location.java Mon Aug  1 06:10:02 2005
@@ -0,0 +1,168 @@
+/*
+ * 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.util.location;
+
+import java.io.Serializable;
+
+/**
+ * A location in a resource. The location is composed of the URI of the resource, and 
+ * the line and column numbers within that resource (when available).
+ * <p>
+ * Locations are mostly used by {@link Locatable}s objects.
+ * 
+ * @version $Id$
+ */
+public class Location implements Serializable {
+    private final String uri;
+    private final int line;
+    private final int column;
+    private transient String stringValue;
+    
+    /**
+     * Constant for unknown locations.
+     */
+    public static final Location UNKNOWN = new Location();
+    
+    /**
+     * The string representation of an {@link #UNKNOWN unknown location}: "<code>[unknown location]</code>".
+     */
+    public static final String UNKNOWN_STRING = "[unknown location]";
+
+    private Location() {
+        // Null location
+        uri = "";
+        line = -1;
+        column = -1;
+        stringValue = UNKNOWN_STRING;
+    }
+    
+    /**
+     * Build a location for a given URI, with unknown line and column numbers.
+     * 
+     * @param uri the resource URI
+     */
+    public Location(String uri) {
+        this(uri, -1, -1);
+    }
+
+    /**
+     * Build a location for a given URI and line and columb numbers.
+     * 
+     * @param uri the resource URI
+     * @param line the line number (starts at 1)
+     * @param column the column number (starts at 1)
+     */
+    public Location(String uri, int line, int column) {
+        this.uri = uri;
+        this.line = line;
+        this.column = column;
+    }
+    
+    /**
+     * Parse a location string of the form "<code><em>uri</em>:<em>line</em>:<em>column</em></code>" (e.g.
+     * "<code>path/to/file.xml:3:40</code>") to a Location object.
+     * 
+     * @param text the text to parse
+     * @return the location
+     */
+    public static Location parse(String text) throws Exception {
+        if (text == null || text.equals(UNKNOWN_STRING)) {
+            return UNKNOWN;
+        }
+
+        try {
+            int colSep = text.lastIndexOf(':');
+            if (colSep > -1) {
+                int column = Integer.parseInt(text.substring(colSep + 1));
+                
+                int lineSep = text.lastIndexOf(':', colSep - 1);
+                if (lineSep > -1) {
+                    int line = Integer.parseInt(text.substring(lineSep + 1, colSep));
+                    return new Location(text.substring(0, lineSep), line, column);
+                }
+            }
+        } catch(Exception e) {
+            // Ignore: we throw another one below
+        }
+        
+        throw new IllegalArgumentException("Invalid location string: " + text);
+    }
+    
+    /**
+     * Get the URI of this location
+     * 
+     * @return the URI (empty string if unknown).
+     */
+    public String getURI() {
+        return this.uri;
+    }
+
+    /**
+     * Get the line number of this location
+     * 
+     * @return the line number (<code>-1</code> if unknown)
+     */
+    public int getLine() {
+        return this.line;
+    }
+    
+    /**
+     * Get the column number of this location
+     * 
+     * @return the column number (<code>-1</code> if unknown)
+     */
+    public int getColumn() {
+        return this.column;
+    }
+
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+
+        if (obj instanceof Location) {
+            Location other = (Location)obj;
+            return this.line == other.line && other.column == other.column && this.uri.equals(other.uri);
+        }
+        
+        return false;
+    }
+    
+    public int hashCode() {
+        return uri.hashCode() ^ line ^ column;
+    }
+    
+    /**
+     * Builds a string representation of the location, in the "<code><em>uri</em>:<em>line</em>:<em>column</em></code>"
+     * format (e.g. "<code>path/to/file.xml:3:40</code>"). For {@link #UNKNOWN an unknown location}, returns
+     * {@link #UNKNOWN_STRING}.
+     * 
+     * @return the string representation
+     */
+    public String toString() {
+        if (stringValue == null) {
+            stringValue = uri + ":" + Integer.toString(line) + ":" + Integer.toString(column);
+        }
+        return stringValue;
+    }
+    
+    /**
+     * Ensure serialized unknown location resolve to {@link UNKNOWN}.
+     */
+    private Object readResolve() {
+        return this.equals(UNKNOWN) ? UNKNOWN : this;
+    }
+}

Propchange: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/Location.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/Location.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/LocationAttributes.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/LocationAttributes.java?rev=226786&r1=226785&r2=226786&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/LocationAttributes.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/location/LocationAttributes.java Mon Aug  1 06:10:02 2005
@@ -48,9 +48,6 @@
     /** Attribute qualified name for the column number */
     public static final String Q_COL_ATTR  = "loc:column";
     
-    /** Value returned when location is unknown */
-    public static final String UNKNOWN_LOCATION = "[unknown location]";
-    
     // Private constructor, we only have static methods
     private LocationAttributes() {
         // Nothing
@@ -79,18 +76,34 @@
         
         return newAttrs;
     }
+    
+    /**
+     * Returns the {@link Location} of an element (SAX flavor).
+     * 
+     * @param attrs the element's attributes that hold the location information
+     * @return a {@link Location} object
+     */
+    public static Location getLocation(Attributes attrs) {
+        String src = attrs.getValue(URI, SRC_ATTR);
+        if (src == null) {
+            return Location.UNKNOWN;
+        }
+        
+        return new Location(src, getLine(attrs), getColumn(attrs));
+    }
 
     /**
-     * Returns the location of an element (SAX flavor).
+     * Returns the location of an element (SAX flavor). If the location is to be kept
+     * into an object built from this element, consider using {@link #getLocation(Attributes)}
+     * and the {@link Locatable} interface.
      * 
      * @param attrs the element's attributes that hold the location information
-     * @return a location string of type "<code>foo.xml:10:80</code>" or
-     *        "<code>[unknown location]</code>" if <code>attrs</code> has no location information.
+     * @return a location string as defined by {@link Location#toString()}.
      */
     public static String getLocationString(Attributes attrs) {
         String src = attrs.getValue(URI, SRC_ATTR);
         if (src == null) {
-            return UNKNOWN_LOCATION;
+            return Location.UNKNOWN_STRING;
         }
         
         return src + ":" + attrs.getValue(URI, LINE_ATTR) + ":" + attrs.getValue(URI, COL_ATTR);
@@ -105,7 +118,7 @@
      */
     public static String getURI(Attributes attrs) {
         String src = attrs.getValue(URI, SRC_ATTR);
-        return src != null ? src : UNKNOWN_LOCATION;
+        return src != null ? src : Location.UNKNOWN_STRING;
     }
     
     /**
@@ -133,16 +146,32 @@
     }
     
     /**
+     * Returns the {@link Location} of an element (DOM flavor).
+     * 
+     * @param attrs the element that holds the location information
+     * @return a {@link Location} object
+     */
+    public static Location getLocation(Element elem) {
+        Attr srcAttr = elem.getAttributeNodeNS(URI, SRC_ATTR);
+        if (srcAttr == null) {
+            return Location.UNKNOWN;
+        }
+        
+        return new Location(srcAttr.getValue(), getLine(elem), getColumn(elem));
+    }
+
+    /**
      * Returns the location of an element that has been processed by this pipe (DOM flavor).
+     * If the location is to be kept into an object built from this element, consider using
+     * {@link #getLocation(Element)} and the {@link Locatable} interface.
      * 
      * @param elem the element that holds the location information
-     * @return a location string of type "<code>foo.xml:10:80</code>" or
-     *        "<code>[unknown location]</code>" if <code>attrs</code> has no location information.
+     * @return a location string as defined by {@link Location#toString()}.
      */
     public static String getLocationString(Element elem) {
         Attr srcAttr = elem.getAttributeNodeNS(URI, SRC_ATTR);
         if (srcAttr == null) {
-            return UNKNOWN_LOCATION;
+            return Location.UNKNOWN_STRING;
         }
         
         return srcAttr.getValue() + ":" + elem.getAttributeNS(URI, LINE_ATTR) + ":" + elem.getAttributeNS(URI, COL_ATTR);
@@ -157,7 +186,7 @@
      */
     public static String getURI(Element elem) {
         Attr attr = elem.getAttributeNodeNS(URI, SRC_ATTR);
-        return attr != null ? attr.getValue() : UNKNOWN_LOCATION;
+        return attr != null ? attr.getValue() : Location.UNKNOWN_STRING;
     }
 
     /**

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/log/CocoonLogFormatter.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/log/CocoonLogFormatter.java?rev=226786&r1=226785&r2=226786&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/log/CocoonLogFormatter.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/log/CocoonLogFormatter.java Mon Aug  1 06:10:02 2005
@@ -20,9 +20,9 @@
 
 import org.apache.cocoon.environment.ObjectModelHelper;
 import org.apache.cocoon.environment.Request;
+import org.apache.cocoon.util.ExceptionUtils;
 
 import org.apache.commons.lang.ClassUtils;
-import org.apache.commons.lang.exception.ExceptionUtils;
 import org.apache.log.ContextMap;
 import org.apache.log.LogEvent;
 import org.apache.log.Logger;

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/xml/AbstractXMLPipe.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/xml/AbstractXMLPipe.java?rev=226786&r1=226785&r2=226786&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/xml/AbstractXMLPipe.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/xml/AbstractXMLPipe.java Mon Aug  1 06:10:02 2005
@@ -36,7 +36,7 @@
      *                document event.
      */
     public void setDocumentLocator(Locator locator) {
-        if (contentHandler != null) contentHandler.setDocumentLocator(locator);
+        contentHandler.setDocumentLocator(locator);
     }
 
     /**
@@ -44,7 +44,7 @@
      */
     public void startDocument()
     throws SAXException {
-        if (contentHandler != null) contentHandler.startDocument();
+        contentHandler.startDocument();
     }
 
     /**
@@ -52,7 +52,7 @@
      */
     public void endDocument()
     throws SAXException {
-        if (contentHandler != null) contentHandler.endDocument();
+        contentHandler.endDocument();
     }
 
     /**
@@ -63,7 +63,7 @@
      */
     public void startPrefixMapping(String prefix, String uri)
     throws SAXException {
-        if (contentHandler != null) contentHandler.startPrefixMapping(prefix, uri);
+        contentHandler.startPrefixMapping(prefix, uri);
     }
 
     /**
@@ -73,7 +73,7 @@
      */
     public void endPrefixMapping(String prefix)
     throws SAXException {
-        if (contentHandler != null) contentHandler.endPrefixMapping(prefix);
+        contentHandler.endPrefixMapping(prefix);
     }
 
     /**
@@ -91,7 +91,7 @@
      */
     public void startElement(String uri, String loc, String raw, Attributes a)
     throws SAXException {
-        if (contentHandler != null) contentHandler.startElement(uri, loc, raw, a);
+        contentHandler.startElement(uri, loc, raw, a);
     }
 
 
@@ -108,7 +108,7 @@
      */
     public void endElement(String uri, String loc, String raw)
     throws SAXException {
-        if (contentHandler != null) contentHandler.endElement(uri, loc, raw);
+        contentHandler.endElement(uri, loc, raw);
     }
 
     /**
@@ -120,7 +120,7 @@
      */
     public void characters(char c[], int start, int len)
     throws SAXException {
-        if (contentHandler != null) contentHandler.characters(c, start, len);
+        contentHandler.characters(c, start, len);
     }
 
     /**
@@ -132,7 +132,7 @@
      */
     public void ignorableWhitespace(char c[], int start, int len)
     throws SAXException {
-        if (contentHandler != null) contentHandler.ignorableWhitespace(c, start, len);
+        contentHandler.ignorableWhitespace(c, start, len);
     }
 
     /**
@@ -144,7 +144,7 @@
      */
     public void processingInstruction(String target, String data)
     throws SAXException {
-        if (contentHandler != null) contentHandler.processingInstruction(target, data);
+        contentHandler.processingInstruction(target, data);
     }
 
     /**
@@ -155,7 +155,7 @@
      */
     public void skippedEntity(String name)
     throws SAXException {
-        if (contentHandler != null) contentHandler.skippedEntity(name);
+        contentHandler.skippedEntity(name);
     }
 
     /**
@@ -169,7 +169,7 @@
      */
     public void startDTD(String name, String publicId, String systemId)
     throws SAXException {
-        if (lexicalHandler != null) lexicalHandler.startDTD(name, publicId, systemId);
+        lexicalHandler.startDTD(name, publicId, systemId);
     }
 
     /**
@@ -177,7 +177,7 @@
      */
     public void endDTD()
     throws SAXException {
-        if (lexicalHandler != null) lexicalHandler.endDTD();
+        lexicalHandler.endDTD();
     }
 
     /**
@@ -188,7 +188,7 @@
      */
     public void startEntity(String name)
     throws SAXException {
-        if (lexicalHandler != null) lexicalHandler.startEntity(name);
+        lexicalHandler.startEntity(name);
     }
 
     /**
@@ -198,7 +198,7 @@
      */
     public void endEntity(String name)
     throws SAXException {
-        if (lexicalHandler != null) lexicalHandler.endEntity(name);
+        lexicalHandler.endEntity(name);
     }
 
     /**
@@ -206,7 +206,7 @@
      */
     public void startCDATA()
     throws SAXException {
-        if (lexicalHandler != null) lexicalHandler.startCDATA();
+        lexicalHandler.startCDATA();
     }
 
     /**
@@ -214,7 +214,7 @@
      */
     public void endCDATA()
     throws SAXException {
-        if (lexicalHandler != null) lexicalHandler.endCDATA();
+        lexicalHandler.endCDATA();
     }
 
     /**
@@ -226,6 +226,6 @@
      */
     public void comment(char ch[], int start, int len)
     throws SAXException {
-        if (lexicalHandler != null) lexicalHandler.comment(ch, start, len);
+        lexicalHandler.comment(ch, start, len);
     }
 }

Added: cocoon/branches/BRANCH_2_1_X/src/test/org/apache/cocoon/util/location/LocationTestCase.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/test/org/apache/cocoon/util/location/LocationTestCase.java?rev=226786&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/test/org/apache/cocoon/util/location/LocationTestCase.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/test/org/apache/cocoon/util/location/LocationTestCase.java Mon Aug  1 06:10:02 2005
@@ -0,0 +1,70 @@
+/*
+ * 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.util.location;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import junit.framework.TestCase;
+
+public class LocationTestCase extends TestCase {
+    
+    public LocationTestCase(String name) {
+        super(name);
+    }
+    
+    static final String str = "path/to/file.xml:1:40";
+
+    public void testParse() throws Exception {
+        String str = "path/to/file.xml:1:40";
+        Location loc = Location.parse(str);
+        
+        assertEquals("URI", "path/to/file.xml", loc.getURI());
+        assertEquals("line", 1, loc.getLine());
+        assertEquals("column", 40, loc.getColumn());
+        assertEquals("string representation", str, loc.toString());
+    }
+    
+    public void testEquals() throws Exception {
+        Location loc1 = Location.parse(str);
+        Location loc2 = new Location("path/to/file.xml", 1, 40);
+        
+        assertEquals("locations", loc1, loc2);
+        assertEquals("hashcode", loc1.hashCode(), loc2.hashCode());
+        assertEquals("string representation", loc1.toString(), loc2.toString());
+    }
+    
+    /**
+     * Test that Location.UNKNOWN is kept identical on deserialization
+     */
+    public void testSerializeUnknown() throws Exception {
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        ObjectOutputStream oos = new ObjectOutputStream(bos);
+        
+        oos.writeObject(Location.UNKNOWN);
+        oos.close();
+        bos.close();
+        
+        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
+        ObjectInputStream ois = new ObjectInputStream(bis);
+        
+        Object obj = ois.readObject();
+        
+        assertSame("unknown location", Location.UNKNOWN, obj);
+    }
+}

Propchange: cocoon/branches/BRANCH_2_1_X/src/test/org/apache/cocoon/util/location/LocationTestCase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/branches/BRANCH_2_1_X/src/test/org/apache/cocoon/util/location/LocationTestCase.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: cocoon/branches/BRANCH_2_1_X/src/webapp/sitemap.xmap
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/webapp/sitemap.xmap?rev=226786&r1=226785&r2=226786&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/webapp/sitemap.xmap (original)
+++ cocoon/branches/BRANCH_2_1_X/src/webapp/sitemap.xmap Mon Aug  1 06:10:02 2005
@@ -74,9 +74,11 @@
     <map:generator label="content" logger="sitemap.generator.stream" name="stream" pool-max="16" src="org.apache.cocoon.generation.StreamGenerator"/>
     <map:generator label="content" logger="sitemap.generator.status" name="status" pool-max="16" src="org.apache.cocoon.generation.StatusGenerator"/>
     <map:generator label="content" logger="sitemap.generator.jx" name="jx" pool-max="16" src="org.apache.cocoon.generation.JXTemplateGenerator"/>
-    <!-- The notifying generator can only be used in a <handle-errors> section : it produces an XML
-         representation of the exception that caused the error handler to be executed -->
+    <!-- The notifying generator can only be used in a <handle-errors> section -->
     <map:generator name="notifying" src="org.apache.cocoon.sitemap.NotifyingGenerator"/>
+    <!-- The exception generator can only be used in a <handle-errors> section : it produces an XML
+         representation of the exception that caused the error handler to be executed -->
+    <map:generator name="exception" src="org.apache.cocoon.generation.ExceptionGenerator"/>
   </map:generators>
 
 
@@ -676,27 +678,30 @@
       <map:select type="exception">
 
         <map:when test="not-found">
-          <map:generate type="notifying"/>
-          <map:transform src="stylesheets/system/error2html.xslt">
+          <map:generate type="exception"/>
+          <map:transform src="stylesheets/system/exception2html.xslt">
             <map:parameter name="contextPath" value="{request:contextPath}"/>
+            <map:parameter name="realPath" value="{realpath:}"/>
             <map:parameter name="pageTitle" value="Resource not found"/>
           </map:transform>
           <map:serialize status-code="404"/>
         </map:when>
 
         <map:when test="invalid-continuation">
-          <map:generate type="notifying"/>
-          <map:transform src="stylesheets/system/error2html.xslt">
+          <map:generate type="exception"/>
+          <map:transform src="stylesheets/system/exception2html.xslt">
             <map:parameter name="contextPath" value="{request:contextPath}"/>
+            <map:parameter name="realPath" value="{realpath:}"/>
             <map:parameter name="pageTitle" value="Invalid Continuation"/>
           </map:transform>
           <map:serialize status-code="404"/>
         </map:when>
 
         <map:otherwise>
-          <map:generate type="notifying"/>
-          <map:transform src="stylesheets/system/error2html.xslt">
+          <map:generate type="exception"/>
+          <map:transform src="stylesheets/system/exception2html.xslt">
             <map:parameter name="contextPath" value="{request:contextPath}"/>
+            <map:parameter name="realPath" value="{realpath:}"/>
           </map:transform>
           <map:serialize status-code="500"/>
         </map:otherwise>

Added: cocoon/branches/BRANCH_2_1_X/src/webapp/stylesheets/system/exception2html.xslt
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/webapp/stylesheets/system/exception2html.xslt?rev=226786&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/webapp/stylesheets/system/exception2html.xslt (added)
+++ cocoon/branches/BRANCH_2_1_X/src/webapp/stylesheets/system/exception2html.xslt Mon Aug  1 06:10:02 2005
@@ -0,0 +1,152 @@
+<?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.
+-->
+
+<!-- CVS $Id$ -->
+
+<xsl:stylesheet version="1.0"
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                xmlns:ex="http://apache.org/cocoon/exception/1.0">
+
+  <xsl:param name="contextPath"/>
+  <xsl:param name="realPath"/>
+
+  <!-- let sitemap override default page title -->
+  <xsl:param name="pageTitle">An error has occured</xsl:param>
+
+  <xsl:template match="ex:exception">
+    <html>
+      <head>
+        <title>
+          <xsl:value-of select="$pageTitle"/>
+        </title>
+        <link href="{$contextPath}/styles/main.css" type="text/css" rel="stylesheet"/>
+        <style>
+          h1 { color: #336699; text-align: left; margin: 0px 0px 30px 0px; padding: 0px; border-width: 0px 0px 1px 0px; border-style: solid; border-color: #336699;}
+          p.message { padding: 10px 30px 10px 30px; font-weight: bold; font-size: 130%; border-width: 1px; border-style: dashed; border-color: #336699; }
+          p.description { padding: 10px 30px 20px 30px; border-width: 0px 0px 1px 0px; border-style: solid; border-color: #336699;}
+          p.topped { padding-top: 10px; border-width: 1px 0px 0px 0px; border-style: solid; border-color: #336699; }
+          pre { font-size: 120%; }
+        </style>
+        <script src="{$contextPath}/scripts/main.js" type="text/javascript"/>
+      </head>
+      <body>
+        <xsl:attribute name="onload">
+          <xsl:if test="ex:stacktrace">toggle('stacktrace');</xsl:if>
+          <xsl:if test="ex:full-stacktrace">toggle('full-stacktrace');</xsl:if>
+        </xsl:attribute>
+
+        <h1><xsl:value-of select="$pageTitle"/></h1>
+        <p class="message">
+          <xsl:value-of select="@class"/>:<br/><xsl:value-of select="ex:message"/>
+          <xsl:if test="@uri">
+             <br/><span style="font-weight: normal"><xsl:call-template name="dump-location"/></span>
+          </xsl:if>
+        </p>
+
+        <xsl:if test="count(ex:locations/*)">
+          <p><span class="description">Cocoon stacktrace</span>
+             <span class="switch" id="locations-switch" onclick="toggle('locations')">[hide]</span>
+          </p>
+          <div id="locations">
+            <xsl:for-each select="ex:locations/*">
+              <xsl:sort select="position()" order="descending"/>
+              <p><strong><xsl:value-of select="."/></strong><br/>
+              <xsl:call-template name="dump-location"/>
+              </p>
+            </xsl:for-each>
+          </div>
+        </xsl:if>
+
+        <xsl:apply-templates select="ex:stacktrace"/>
+        <xsl:apply-templates select="ex:full-stacktrace"/>
+
+<!-- Do we really need all that stuff?
+     Application developers know this, and application users get really confused by this information.
+
+        <p class="topped">
+          If you need help and this information is not enough, you
+          are invited to read the
+          <a href="http://cocoon.apache.org/2.1/faq/">Cocoon FAQ</a>.<br/>
+          If you still don't find the answers you need,
+          can send a mail to the
+          <a href="http://cocoon.apache.org/community/mail-lists.html">
+          Cocoon mailing lists</a>,
+          remembering to:
+        </p>
+
+        <ul>
+          <li>specify the version of Cocoon you're using, or we'll assume that you
+              are talking about the latest released version;</li>
+          <li>specify the platform-operating system-version-servlet container version;</li>
+          <li>send any pertinent error message;</li>
+          <li>send pertinent log snippets;</li>
+          <li>send pertinent sitemap snippets;</li>
+          <li>send pertinent parts of the page that give you problems.</li>
+        </ul>
+
+        <p>
+          For more detailed technical information, take a look at the log
+          files in the log directory of Cocoon, which is placed by default in
+          the <code>WEB-INF/logs/</code> folder of your cocoon webapp context.<br/>
+          If the logs don't give you enough information, you might want to increase the
+          log level by changing the Logging configuration which is by default the
+          <code>WEB-INF/logkit.xconf</code> file.
+        </p>
+
+        <p>
+          If you think you found a bug, please report it to
+          <a href="http://issues.apache.org/bugzilla/">Apache's Bugzilla</a>;
+          a message will automatically be sent to the developer mailing list and you'll
+          be kept in contact automatically with the further progress on that bug.
+        </p>
+
+        <p>
+          Thanks, and sorry for the trouble if this is our fault.
+        </p>
+-->
+        <p class="topped">
+          The <a href="http://cocoon.apache.org/">Apache Cocoon</a> Project
+        </p>
+      </body>
+    </html>
+  </xsl:template>
+
+  <xsl:template match="ex:stacktrace|ex:full-stacktrace">
+      <p class="stacktrace">
+       <span class="description">Java <xsl:value-of select="translate(local-name(), '-', ' ')"/></span>
+       <span class="switch" id="{local-name()}-switch" onclick="toggle('{local-name()}')">[hide]</span>
+       <pre id="{local-name()}">
+         <xsl:value-of select="translate(.,'&#13;','')"/>
+       </pre>
+      </p>
+  </xsl:template>
+  
+  <xsl:template name="dump-location">
+   <xsl:choose>
+     <xsl:when test="contains(@uri, $realPath)">
+       <xsl:text>context:/</xsl:text>
+       <xsl:value-of select="substring-after(@uri, $realPath)"/>
+     </xsl:when>
+     <xsl:otherwise>
+       <xsl:value-of select="@uri"/>
+     </xsl:otherwise>
+    </xsl:choose>
+    <xsl:text> - </xsl:text>
+    <xsl:value-of select="@line"/>:<xsl:value-of select="@column"/>
+  </xsl:template>
+
+</xsl:stylesheet>

Propchange: cocoon/branches/BRANCH_2_1_X/src/webapp/stylesheets/system/exception2html.xslt
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/branches/BRANCH_2_1_X/src/webapp/stylesheets/system/exception2html.xslt
------------------------------------------------------------------------------
    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?rev=226786&r1=226785&r2=226786&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/status.xml (original)
+++ cocoon/branches/BRANCH_2_1_X/status.xml Mon Aug  1 06:10:02 2005
@@ -196,6 +196,10 @@
 
   <changes>
   <release version="@version@" date="@date@">
+    <action dev="SW" type="add">
+      Added Cocoon stacktraces. This is based on location classes in the new org.apache.cocoon.util.location package
+      and a refactoring of the exception management to attach locations to exceptions.
+    </action>
     <action dev="AG" type="update">
       Updated hsqldb to 1.8.0.
     </action>