sylvain 2003/04/01 13:25:10
Modified: . changes.xml todo.xml
lib jars.xml
src/java/org/apache/cocoon/components/treeprocessor/sitemap
HandleErrorsNode.java HandleErrorsNodeBuilder.java
PipelineNode.java PipelineNodeBuilder.java
RedirectToNodeBuilder.java SitemapLanguage.java
src/java/org/apache/cocoon/environment
ObjectModelHelper.java
src/targets webapp-build.xml
src/webapp sitemap.xmap
Added: lib/core commons-lang-1.0.1.jar
src/java/org/apache/cocoon/selection ExceptionSelector.java
src/webapp not-found.xml
Removed: src/blocks/databases/lib commons-lang-1.0.1.jar
Log:
New error handling : we can now set a generator in <map:handle-errors>
Revision Changes Path
1.13 +15 -5 cocoon-2.1/changes.xml
Index: changes.xml
===================================================================
RCS file: /home/cvs/cocoon-2.1/changes.xml,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- changes.xml 24 Mar 2003 12:09:16 -0000 1.12
+++ changes.xml 1 Apr 2003 21:25:08 -0000 1.13
@@ -42,6 +42,17 @@
</devs>
<release version="@version@" date="@date@">
+ <action dev="SW" type="add">
+ 'handle-errors' sections in the sitemap not more have an implicit generator :
+ any generator can be used whearas it was before fixed and produced an XML
representation
+ of the error.
+ <br/>
+ To ensure backwards compatibility, 'handle-errors' sections having a 'type'
attribute
+ keep the implicit-generator behaviour, but are now to be considered as
deprecated.
+ <br/>
+ A new ExceptionSelector is also available to drive the error-handling pipeline
constuction
+ depending on the error type.
+ </action>
<action dev="TC" type="update">
EsqlConnection no longer implements java.sql.Connection.
No jvm dependency any more.
@@ -66,10 +77,9 @@
Enhancements to the CLI to reduce the number of times it
needs to render a page. Using the option to prevent checking of extensions, it
is now possible to generate a site generating each page only once.
-
- Allow the configuration of the CLI using
- an xconf file.
-
+ <br/>
+ Allow the configuration of the CLI using an xconf file.
+ <br/>
Switch cli to using the Jakarta Commons CLI package.
</action>
<action dev="MC" type="add">
1.10 +1 -7 cocoon-2.1/todo.xml
Index: todo.xml
===================================================================
RCS file: /home/cvs/cocoon-2.1/todo.xml,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- todo.xml 23 Mar 2003 07:17:16 -0000 1.9
+++ todo.xml 1 Apr 2003 21:25:08 -0000 1.10
@@ -72,12 +72,6 @@
as a NotifyingBuilder.
</action>
- <action context="code" assigned-to="SW">
- Change the handle-errors to enable use of any Generator.
- DOUBLE CHECK THAT REDIRECTS ARE FORBIDDEN.
- http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=102633389301850&w=2
- </action>
-
<action context="code" assigned-to="open">
Finish the design and contracts of flow. Add more tests and samples and
documentation.
1.22 +11 -6 cocoon-2.1/lib/jars.xml
Index: jars.xml
===================================================================
RCS file: /home/cvs/cocoon-2.1/lib/jars.xml,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -r1.21 -r1.22
--- jars.xml 1 Apr 2003 16:34:17 -0000 1.21
+++ jars.xml 1 Apr 2003 21:25:08 -0000 1.22
@@ -757,10 +757,15 @@
</file>
<file>
- <title>???</title>
- <description>???</description>
- <used-by>Database block</used-by>
- <lib>databases/lib/commons-lang-1.0.1.jar</lib>
- <homepage>???</homepage>
+ <title>Jakarta Commons lang</title>
+ <description>
+ Part of jakarta-commons, it's a package that
+ provides extended services on base classes of the JDK,
+ such as unrolling exceptions.
+ </description>
+ <used-by>Cocoon</used-by>
+ <lib>core/commons-lang-1.0.1.jar</lib>
+ <homepage>http://jakarta.apache.org/commons/lang/</homepage>
</file>
+
</jars>
1.1 cocoon-2.1/lib/core/commons-lang-1.0.1.jar
<<Binary file>>
1.2 +36 -4
cocoon-2.1/src/java/org/apache/cocoon/components/treeprocessor/sitemap/HandleErrorsNode.java
Index: HandleErrorsNode.java
===================================================================
RCS file:
/home/cvs/cocoon-2.1/src/java/org/apache/cocoon/components/treeprocessor/sitemap/HandleErrorsNode.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- HandleErrorsNode.java 9 Mar 2003 00:09:21 -0000 1.1
+++ HandleErrorsNode.java 1 Apr 2003 21:25:09 -0000 1.2
@@ -51,6 +51,7 @@
package org.apache.cocoon.components.treeprocessor.sitemap;
import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.components.treeprocessor.AbstractParentProcessingNode;
import org.apache.cocoon.components.treeprocessor.InvokeContext;
import org.apache.cocoon.components.treeprocessor.ProcessingNode;
@@ -88,8 +89,39 @@
getLogger().info("Processing handle-errors at " + getLocation());
}
- context.getProcessingPipeline().setGenerator("<notifier>", "",
Parameters.EMPTY_PARAMETERS, Parameters.EMPTY_PARAMETERS);
-
- return invokeNodes(this.children, env, context);
+ if (statusCode == -1) {
+ // No 'type' attribute : new Cocoon 2.1 behaviour, no implicit generator
+ try {
+ return invokeNodes(this.children, env, context);
+
+ } catch(ProcessingException pe) {
+ // 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) {
+
+ throw new ProcessingException(
+ "Incomplete pipeline : 'handle-error' without a 'type' must
include a generator, at " +
+ this.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;
+ }
+ }
+ } 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);
+ }
}
}
1.2 +8 -2
cocoon-2.1/src/java/org/apache/cocoon/components/treeprocessor/sitemap/HandleErrorsNodeBuilder.java
Index: HandleErrorsNodeBuilder.java
===================================================================
RCS file:
/home/cvs/cocoon-2.1/src/java/org/apache/cocoon/components/treeprocessor/sitemap/HandleErrorsNodeBuilder.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- HandleErrorsNodeBuilder.java 9 Mar 2003 00:09:21 -0000 1.1
+++ HandleErrorsNodeBuilder.java 1 Apr 2003 21:25:09 -0000 1.2
@@ -72,11 +72,17 @@
public ProcessingNode buildNode(Configuration config) throws Exception {
- HandleErrorsNode node = new
HandleErrorsNode(config.getAttributeAsInteger("type", 500));
+ HandleErrorsNode node = new
HandleErrorsNode(config.getAttributeAsInteger("type", -1));
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);
return node;
}
1.2 +27 -19
cocoon-2.1/src/java/org/apache/cocoon/components/treeprocessor/sitemap/PipelineNode.java
Index: PipelineNode.java
===================================================================
RCS file:
/home/cvs/cocoon-2.1/src/java/org/apache/cocoon/components/treeprocessor/sitemap/PipelineNode.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- PipelineNode.java 9 Mar 2003 00:09:22 -0000 1.1
+++ PipelineNode.java 1 Apr 2003 21:25:09 -0000 1.2
@@ -63,6 +63,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.environment.ObjectModelHelper;
import java.util.Map;
@@ -86,7 +87,7 @@
private ProcessingNode error404;
private ProcessingNode error500;
-
+
private ComponentManager manager;
private boolean internalOnly = false;
@@ -161,22 +162,25 @@
} catch (ConnectionResetException cre) {
// Will be reported by CocoonServlet, rethrowing
throw cre;
- } catch(ResourceNotFoundException rnfe) {
- if (error404 != null) {
- // There's a handler
- return invokeErrorHandler(error404, rnfe, env);
- } else {
- // No handler : propagate
- throw rnfe;
- }
- } catch(Exception e) {
- // Rethrow exception for internal requests
- if (error500 != null && !context.isInternalRequest()) {
- return invokeErrorHandler(error500, e, env);
- } else {
- // No handler : propagate
- throw e;
- }
+
+ } catch(Exception ex) {
+
+ if (context.isInternalRequest()) {
+ // Propagate exception on internal requests
+ throw ex;
+
+ } else if (error404 != null && ex instanceof ResourceNotFoundException)
{
+ // Invoke 404-specific handler
+ return invokeErrorHandler(error404, ex, env);
+
+ } else if (error500 != null) {
+ // Invoke global handler
+ return invokeErrorHandler(error500, ex, env);
+
+ } else {
+ // No handler : propagate
+ throw ex;
+ }
}
}
@@ -203,8 +207,12 @@
this.manager.release(notifyingBuilder);
}
+ Map objectModel = env.getObjectModel();
// Add it to the object model
- env.getObjectModel().put(Constants.NOTIFYING_OBJECT, currentNotifying );
+ objectModel.put(Constants.NOTIFYING_OBJECT, currentNotifying);
+
+ // Also add the exception
+ objectModel.put(ObjectModelHelper.THROWABLE_OBJECT, ex);
// <notifier> is added in HandleErrorsNode
return node.invoke(env, errorContext);
1.2 +47 -17
cocoon-2.1/src/java/org/apache/cocoon/components/treeprocessor/sitemap/PipelineNodeBuilder.java
Index: PipelineNodeBuilder.java
===================================================================
RCS file:
/home/cvs/cocoon-2.1/src/java/org/apache/cocoon/components/treeprocessor/sitemap/PipelineNodeBuilder.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- PipelineNodeBuilder.java 9 Mar 2003 00:09:22 -0000 1.1
+++ PipelineNodeBuilder.java 1 Apr 2003 21:25:09 -0000 1.2
@@ -69,7 +69,7 @@
extends AbstractParentProcessingNodeBuilder
implements ThreadSafe {
- /** This builder has no parameters -- return <code>false</code> */
+ /** This builder can have parameters -- return <code>true</code> */
protected boolean hasParameters() {
return true;
}
@@ -80,8 +80,14 @@
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
+ ProcessingNode mainHandler = null;
+
+ // 404 & 500 error handlers as in Cocoon 2.0.x, have an implicit generator
ProcessingNode error404Handler = null;
ProcessingNode error500Handler = null;
+
Configuration[] childConfigs = config.getChildren();
List children = new ArrayList();
for (int i = 0; i < childConfigs.length; i++) {
@@ -95,20 +101,43 @@
HandleErrorsNode handler =
(HandleErrorsNode)builder.buildNode(childConfig);
int type = handler.getStatusCode();
- if ( (type == 404 && error404Handler != null) ||
- (type == 500 && error500Handler != null) ) {
- String msg = "Duplicate handle-errors at " +
handler.getLocation();
- throw new ConfigurationException(msg);
- }
-
- if (type == 404) {
- error404Handler = handler;
- } else if (type == 500) {
- error500Handler = handler;
- } else {
- String msg = "Unknown handle-errors type (" + type + ") at
" + handler.getLocation();
- throw new ConfigurationException(msg);
- }
+ switch(type) {
+ 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;
+
+ case 500:
+ if (error500Handler != null) {
+ throw new ConfigurationException("Duplicate
<handle-errors type='500' at " + handler.getLocation());
+ } else if (mainHandler != null) {
+ throw new ConfigurationException("Cannot mix
<handle-errors> with and without 'type' attribute at " +
+ handler.getLocation());
+ } else {
+ error500Handler = handler;
+ }
+ break;
+
+ default:
+ throw new
ConfigurationException("Unknown handle-errors type (" + type + ") at " +
handler.getLocation());
+ }
} else {
// Regular builder
children.add(builder.buildNode(childConfig));
@@ -117,7 +146,8 @@
}
node.setChildren(toNodeArray(children));
node.set404Handler(error404Handler);
- node.set500Handler(error500Handler);
+ // Set either main or error500 handler as only one can exist
+ node.set500Handler(error500Handler == null ? mainHandler : error500Handler);
return node;
}
1.2 +6 -1
cocoon-2.1/src/java/org/apache/cocoon/components/treeprocessor/sitemap/RedirectToNodeBuilder.java
Index: RedirectToNodeBuilder.java
===================================================================
RCS file:
/home/cvs/cocoon-2.1/src/java/org/apache/cocoon/components/treeprocessor/sitemap/RedirectToNodeBuilder.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- RedirectToNodeBuilder.java 9 Mar 2003 00:09:22 -0000 1.1
+++ RedirectToNodeBuilder.java 1 Apr 2003 21:25:09 -0000 1.2
@@ -81,6 +81,11 @@
public ProcessingNode buildNode(Configuration config) throws Exception {
+ if (((SitemapLanguage)this.treeBuilder).isBuildingErrorHandler()) {
+ throw new ConfigurationException("'map:redirect' is forbidden inside a
'map:handle-errors', at "
+ + config.getLocation());
+ }
+
// Is it a redirect to resource ?
this.resourceName = config.getAttribute("resource", null);
if (this.resourceName != null) {
1.3 +19 -1
cocoon-2.1/src/java/org/apache/cocoon/components/treeprocessor/sitemap/SitemapLanguage.java
Index: SitemapLanguage.java
===================================================================
RCS file:
/home/cvs/cocoon-2.1/src/java/org/apache/cocoon/components/treeprocessor/sitemap/SitemapLanguage.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- SitemapLanguage.java 24 Mar 2003 14:33:55 -0000 1.2
+++ SitemapLanguage.java 1 Apr 2003 21:25:09 -0000 1.3
@@ -161,6 +161,9 @@
/** Are we currently building a view ? */
private boolean isBuildingView = false;
+ /** Are we currently building a view ? */
+ private boolean isBuildingErrorHandler = false;
+
/**
* Pseudo-label for views <code>from-position="first"</code> (i.e. generator).
*/
@@ -178,6 +181,7 @@
this.labelViews.clear();
this.viewsNode = null;
this.isBuildingView = false;
+ this.isBuildingErrorHandler = false;
}
/**
@@ -192,6 +196,20 @@
*/
public boolean isBuildingView() {
return this.isBuildingView;
+ }
+
+ /**
+ * Set to <code>true</code> while building the internals of a
<map:handle-errors>
+ */
+ public void setBuildingErrorHandler(boolean building) {
+ this.isBuildingErrorHandler = building;
+ }
+
+ /**
+ * Are we currently building an error handler ?
+ */
+ public boolean isBuildingErrorHandler() {
+ return this.isBuildingErrorHandler;
}
/**
1.3 +8 -1
cocoon-2.1/src/java/org/apache/cocoon/environment/ObjectModelHelper.java
Index: ObjectModelHelper.java
===================================================================
RCS file:
/home/cvs/cocoon-2.1/src/java/org/apache/cocoon/environment/ObjectModelHelper.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- ObjectModelHelper.java 17 Mar 2003 02:28:12 -0000 1.2
+++ ObjectModelHelper.java 1 Apr 2003 21:25:09 -0000 1.3
@@ -85,6 +85,9 @@
/** Key for the expiration value (Long) in the object model. */
public final static String EXPIRES_OBJECT = "expires";
+
+ /** Key for the throwable object, only available within a
<map:handle-errors>. */
+ public final static String THROWABLE_OBJECT = "throwable";
/**
* Key for a [EMAIL PROTECTED] Map} containing information from
@@ -111,5 +114,9 @@
public static final Long getExpires(Map objectModel) {
return (Long)objectModel.get(EXPIRES_OBJECT);
+ }
+
+ public static final Throwable getThrowable(Map objectModel) {
+ return (Throwable)objectModel.get(THROWABLE_OBJECT);
}
}
1.1
cocoon-2.1/src/java/org/apache/cocoon/selection/ExceptionSelector.java
Index: ExceptionSelector.java
===================================================================
/*
============================================================================
The Apache Software License, Version 1.1
============================================================================
Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without modifica-
tion, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. The end-user documentation included with the redistribution, if any, must
include the following acknowledgment: "This product includes software
developed by the Apache Software Foundation (http://www.apache.org/)."
Alternately, this acknowledgment may appear in the software itself, if
and wherever such third-party acknowledgments normally appear.
4. The names "Apache Cocoon" and "Apache Software Foundation" must not be
used to endorse or promote products derived from this software without
prior written permission. For written permission, please contact
[EMAIL PROTECTED]
5. Products derived from this software may not be called "Apache", nor may
"Apache" appear in their name, without prior written permission of the
Apache Software Foundation.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This software consists of voluntary contributions made by many individuals
on behalf of the Apache Software Foundation and was originally created by
Stefano Mazzocchi <[EMAIL PROTECTED]>. For more information on the Apache
Software Foundation, please see <http://www.apache.org/>.
*/
package org.apache.cocoon.selection;
import java.util.Map;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
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;
/**
* In a <map:handle-errors>, selects depending on the exception that caused the
error.
* The configuration of this selector allows to map exception class names to
symbolic names
* that are used in the <map:when> alternatives.
* <p>
* Example configuration :
* <pre>
* <map:selector type="error" src="....ExceptionSelector">
* <exception class="org.xml.sax.SAXException" name="sax" unroll="true"/>
* <exception name="not-found"
class="org.apache.cocoon.ResourceNotFoundException"/>
* <exception class="org.apache.cocoon.ProcessingException" unroll="true"/>
* <exception name="denied" class="java.security.SecurityException"/>
* <exception name="denied" class="my.comp.auth.AuthenticationFailure"/>
* </map:selector>
* </pre>
* This example shows several features :
* <li>the "class" is the class name of the exception (which can be any
<code>Throwable</code>),</li>
* <li>an exception can be given a name, which is used in the <map:when>
tests,</li>
* <li>an exception can be unrolled, meaning we try to get its cause and then
consider this cause for
* the exception name</li>
* Note that both "name" and "unroll" can be specified. In that case, we first try
to unroll the exception,
* and if no cause is found, then the "name" attribute is considered.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a>
* @since 2.1
* @version CVS $Id: ExceptionSelector.java,v 1.1 2003/04/01 21:25:09 sylvain Exp $
*/
public class ExceptionSelector extends AbstractSwitchSelector implements
Configurable {
/** Exception classes */
private Class[] clazz;
/** Associated symbolic names (can be null) */
private String[] name;
/** Do we want to unroll them ? */
private boolean[] unroll;
public void configure(Configuration conf) throws ConfigurationException {
Configuration[] children = conf.getChildren("exception");
this.clazz = new Class[children.length];
this.name = new String[children.length];
this.unroll = new boolean[children.length];
for (int i = 0; i < children.length; i++) {
Configuration child = children[i];
String childClassName = child.getAttribute("class");
Class childClass = null;
try {
childClass = ClassUtils.loadClass(childClassName);
}
catch (Exception e) {
throw new ConfigurationException("Cannot load class '" +
childClassName + "' at " + child.getLocation());
}
// Check that this class is not hidden by a more general class already
declared
for (int j = 0; j < i; j++) {
if (this.clazz[j].isAssignableFrom(childClass)) {
throw new ConfigurationException("Class '" +
this.clazz[j].getName() + "' hides its subclass '" +
childClassName + "' at " + child.getLocation());
}
}
this.clazz[i] = childClass;
this.name[i] = child.getAttribute("name", null);
this.unroll[i] = child.getAttributeAsBoolean("unroll", false);
if (this.name[i] == null && !this.unroll[i]) {
throw new ConfigurationException("Must specify one of 'name' or
'unroll' at " + child.getLocation());
}
}
}
/**
* Compute the exception type, given the configuration and the exception stored
in the object model.
*
* @see ObjectModelHelper#getThrowable()
*/
public Object getSelectorContext(Map objectModel, Parameters parameters) {
// Get the name of the exception
Throwable thr = ObjectModelHelper.getThrowable(objectModel);
if (thr == null) {
throw new IllegalStateException("No exception in object model.
ExceptionSelector can only be used in <map:handle-errors>");
}
return findName(thr);
}
private String findName(Throwable thr) {
// Now find the proper name
for (int i = 0; i < this.clazz.length; i++) {
if (this.clazz[i].isInstance(thr)) {
//getLogger().debug("Throwable of class " + thr.getClass().getName()
+ " is instance of " +
// this.clazz[i].getName() + ". Name='" + this.name[i] + ",
Unroll=" + this.unroll[i]);
if (this.unroll[i]) {
Throwable cause = ExceptionUtils.getCause(thr);
if (cause != null) {
return findName(cause);
}
}
// Not unrolled
return this.name[i];
}
}
// Not found
return null;
}
public boolean select(String expression, Object selectorContext) {
// Just compare the expression with the previously found name
return expression.equals(selectorContext);
}
}
1.10 +1 -0 cocoon-2.1/src/targets/webapp-build.xml
Index: webapp-build.xml
===================================================================
RCS file: /home/cvs/cocoon-2.1/src/targets/webapp-build.xml,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- webapp-build.xml 27 Mar 2003 18:48:33 -0000 1.9
+++ webapp-build.xml 1 Apr 2003 21:25:09 -0000 1.10
@@ -4,6 +4,7 @@
<mkdir dir="${build.webapp}"/>
<copy file="${webapp}/welcome.xml" tofile="${build.webapp}/welcome.xml"
filtering="on"/>
+ <copy file="${webapp}/not-found.xml" tofile="${build.webapp}/not-found.xml"
filtering="on"/>
<copy file="${webapp}/welcome.xslt" tofile="${build.webapp}/welcome.xslt"
filtering="on"/>
<copy file="${webapp}/sitemap.xmap" tofile="${build.webapp}/sitemap.xmap"/>
1.10 +42 -8 cocoon-2.1/src/webapp/sitemap.xmap
Index: sitemap.xmap
===================================================================
RCS file: /home/cvs/cocoon-2.1/src/webapp/sitemap.xmap,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- sitemap.xmap 30 Mar 2003 12:48:33 -0000 1.9
+++ sitemap.xmap 1 Apr 2003 21:25:10 -0000 1.10
@@ -58,6 +58,9 @@
<map:generator label="content,data" logger="sitemap.generator.stream"
name="stream" pool-grow="2" pool-max="16" pool-min="1"
src="org.apache.cocoon.generation.StreamGenerator"/>
<map:generator label="data" logger="sitemap.generator.status" name="status"
pool-grow="2" pool-max="16" pool-min="2"
src="org.apache.cocoon.generation.StatusGenerator"/>
<map:generator label="data" logger="sitemap.generator.proxy" name="proxy"
pool-grow="2" pool-max="16" pool-min="2"
src="org.apache.cocoon.generation.WebServiceProxyGenerator"/>
+ <!-- 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 -->
+ <map:generator name="notifying"
src="org.apache.cocoon.sitemap.NotifyingGenerator"/>
</map:generators>
<!--+
@@ -195,6 +198,21 @@
<browser name="mozilla5" useragent="Netscape6/"/>
<browser name="netscape" useragent="Mozilla"/>
</map:selector>
+
+ <!--+
+ | Exception selector : used in <map:handle> errors to build different
pipelines
+ | depending on the error that occured.
+ | The configuration allows to associate a symbolic name to exception classes
+ | which is used in the <map:when> tests.
+ | An exception can also be "unrolled", meaning that cascaded exception will
be checked.
+ +-->
+ <map:selector logger="sitemap.selector.exception" name="exception"
src="org.apache.cocoon.selection.ExceptionSelector">
+ <exception name="not-found"
class="org.apache.cocoon.ResourceNotFoundException"/>
+ <!-- The statement below tells the selector to unroll as much exceptions as
possible -->
+ <exception class="java.lang.Throwable" unroll="true"/>
+ </map:selector>
+
+
<map:selector logger="sitemap.selector.request-parameter"
name="request-parameter" src="org.apache.cocoon.selection.RequestParameterSelector">
<!-- Define now which request parameter to use; or do it later,
when using this selector, via "parameter-name" parameter.
@@ -492,17 +510,33 @@
| At the very end of a pipeline, you can catch the errors triggered
| by the pipeline execution. The error handler is an internal sitemap
| component that when triggered by an error takes over the normal
- | pipeline execution and generates an XML representation
- | of the error found and jump down here where you can futher
- | manipulate the error screen.
+ | pipeline execution.
+ | You can here use the "notifying" generator that produces an XML
+ | representation and further manipulate this document for presentation
+ | on screen.
+ | You can also use any other generator you want if you don't want the
+ | error to be displayed on screen. The "exception" selector can help
+ | you to define different screens for different error types.
+-->
<map:handle-errors>
- <map:transform src="stylesheets/system/error2html.xslt">
- <map:parameter name="contextPath" value="{request:contextPath}"/>
- </map:transform>
+ <map:select type="exception">
+
+ <map:when test="not-found">
+ <map:generate src="not-found.xml"/>
+ <map:transform src="welcome.xslt"/>
+ </map:when>
+
+ <map:otherwise>
+ <map:generate type="notifying"/>
+ <map:transform src="stylesheets/system/error2html.xslt">
+ <map:parameter name="contextPath" value="{request:contextPath}"/>
+ </map:transform>
+ </map:otherwise>
+ </map:select>
+
<map:serialize/>
+
</map:handle-errors>
-
</map:pipeline>
</map:pipelines>
1.1 cocoon-2.1/src/webapp/not-found.xml
Index: not-found.xml
===================================================================
<?xml version="1.0" encoding="UTF-8"?>
<!--+
| This a simple message page that is shown when a resource is not found.
|
| CVS $Id: not-found.xml,v 1.1 2003/04/01 21:25:10 sylvain Exp $
+-->
<welcome>
<message>
Sorry, Cocoon coudln't find the resource you requested.
</message>
</welcome>