The idea is to allow a Cocoon processing element that operates on source code (sitemap, flowscript, jxtemplate, etc...) to provide location information about the execution stack of that processing element when the exception occurred (see also http://marc.theaimsgroup.com/?t=105597249800001&r=1&w=2).
To accomplish this I chose not to use the JVM exception stack trace but instead to store a "Cocoon" stack trace in the current object model. I added the following to the class o.a.c.Cocoon:
public class Cocoon { .... public interface StackTraceElement { public String getComponent(); public String getMessage(); public String getMethod(); public String getURI(); public int getLineNumber(); public int getColumnNumber(); }
public static void addCocoonStackTrace( Map objectModel, String message, String component, String method, String uri, int lineNumber, int columnNumber);
public static ArrayList /* of StackTraceElement */ getStackTrace(Map objectModel)
}
I added calls to addCocoonStackTrace() in JXTemplateGenerator, FOM_JavaScriptInterpreter, and in MountNode.java and CallNode.java.
With a method like the following:
private static void dumpStackTrace(Map objectModel) { ArrayList stackTrace = Cocoon.getStackTrace(objectModel); for (int i = 0, len = stackTrace.size(); i < len; i++) { StackTraceElement e = (StackTraceElement)stackTrace.get(i); String component = e.getComponent(); String message = e.getMessage(); String method = e.getMethod(); String uri = e.getURI(); int lineNum = e.getLineNumber(); int colNum = e.getColumnNumber(); String out = component + ": "; if (message != null) { out += message; out += " "; } out += "("; if (method != null) { out += method + " "; } out += "at " + uri; if (lineNum > 0) { out += ", Line " + lineNum; if (colNum >= 0) { out += "." + colNum; } } out += ")"; System.out.println(out); } }
I was able to produce the following output:
jxtemplate: No pointer for xpath: $blah (at file:/C:/cocoon4/build/webapp/samples/flow/jxcalc/screens/getNumberA.xml, Line 26.13)
sitemap: (mount at file:/C:/cocoon4/build/webapp/samples/flow/sitemap.xmap:38:68)
sitemap: (mount at file:/C:/cocoon4/build/webapp/samples/sitemap.xmap:154:65)
sitemap: (mount at file:/C:/cocoon4/build/webapp/sitemap.xmap:738:66)
flowscript: (at resource://org/apache/cocoon/components/flow/javascript/fom/fom_system.js, Line 4)
flowscript: (getNumber at file:/C:/cocoon4/build/webapp/samples/flow/jxcalc/../calc/calc.js, Line 31)
flowscript: (calculator at file:/C:/cocoon4/build/webapp/samples/flow/jxcalc/../calc/calc.js, Line 11)
sitemap: (call at file:/C:/cocoon4/build/webapp/samples/flow/jxcalc/sitemap.xmap:48:42)
sitemap: (mount at file:/C:/cocoon4/build/webapp/samples/flow/sitemap.xmap:38:68)
sitemap: (mount at file:/C:/cocoon4/build/webapp/samples/sitemap.xmap:154:65)
sitemap: (mount at file:/C:/cocoon4/build/webapp/sitemap.xmap:738:66)
It seems straightforward to hook this into Cocoon's error reporter.
WDYT?
In the process of doing this, however, I found that pipeline processing doesn't actually occur during sendPage*(). Instead, it simply sets a flag to redirect to the passed uri and returns. Pipeline processing actually occurs after the flowscript has completed. This is also a problem for the solution proposed here to release components after pipeline processing: http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=107360524206262&w=2.
To solve both problems I modified the implementation of sendPage*() to call the sitemap processor recursively instead. It seems to work. Does anyone know of a problem with this approach?
Regards,
Chris