I got fed up with XALAN wrapping all sorts of exception in stupid
RuntimeException, without declaring them as the init cause (see
org.apache.xalan.transformer.TransformerImpl.run(TransformerImpl.java:
3418) for an example).
So, I wrote a little patch that might (if very lucky) reconstruct the
original exception from the message of a wrapped one by Xalan.
This happens when (for example) you have cinclude after xalan, if
cinclude fails, xalan will throw a RuntimeException without wrapping
the original ResourceNotFoundException, but simply including it in
its name.
What this patch does is that if the exception being processed is a
RuntimeException (not a subclass of), and the cause is null, it will
try to recreate an exception instance from the detail message, and if
successful, will declare that as the cause (thus allowing the
ExceptionSelector to process almost correctly).
Pier
--- ExceptionSelector.java.orig 2004-05-24 09:12:09.000000000 +0100
+++ ExceptionSelector.java 2005-07-25 13:53:16.000000000 +0100
@@ -15,6 +15,7 @@
*/
package org.apache.cocoon.selection;
+import java.lang.reflect.Constructor;
import java.util.Map;
import org.apache.avalon.framework.configuration.Configurable;
@@ -22,6 +23,7 @@
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.selection.AbstractSwitchSelector;
import org.apache.cocoon.util.ClassUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
@@ -128,8 +130,26 @@
// return the cause name, if not null (recursively)
if (this.unroll[i]) {
Throwable cause = ExceptionUtils.getCause(thr);
+
+ // XALAN throws rogue RuntimeException in its "run()"
method (???)
+ if ((cause == null) && (thr.getClass() ==
RuntimeException.class)) try {
+ int pos = thr.getMessage().indexOf(": ");
+ if (pos > 0) {
+ String clnam = thr.getMessage().substring(0, pos);
+ String messg = "(Rebuilt) " +
thr.getMessage().substring(pos + 2);
+ Class clazz = Class.forName(clnam);
+ Constructor cstrc = clazz.getConstructor(new
Class[] {String.class});
+ cause = (Throwable) cstrc.newInstance(new String[]
{messg});
+ thr.initCause(cause);
+ }
+ } catch (Throwable throwable) {
+ // Ignore anything that might occur above
+ }
+
+ // We should have a cause even if Xalan wrapped it!
if (cause != null) {
FindResult result = find(cause);
+ System.err.println("RESULT FOR " +
cause.getClass().getName() + ": " + result);
if (result != null) {
return result;
}