Permalink
Browse files

Attempt to work around issue #97 by dealing with exceptions that aren…

…'t caught by the error listener; its better but could probably still be improved
  • Loading branch information...
ndw committed Jul 30, 2013
1 parent 05ac4ad commit 1f1c05e380803713bb529cc2579914454ff1041c
@@ -40,6 +40,7 @@
import java.util.Hashtable;
import java.util.Locale;
import java.util.Map;
+import java.util.Stack;
import java.util.Vector;
import java.util.logging.Logger;
@@ -932,7 +933,11 @@ public void finest(XProcRunnable step, XdmNode node, String message) {
// ===========================================================
+ private Stack<XStep> runningSteps = new Stack<XStep>();
+
public void start(XStep step) {
+ runningSteps.push(step);
+
if (profile == null) {
return;
}
@@ -963,7 +968,13 @@ public void start(XStep step) {
profileWriter.startContent();
}
+ public XStep runningStep() {
+ return runningSteps.peek();
+ }
+
public void finish(XStep step) {
+ runningSteps.pop();
+
if (profile == null) {
return;
}
@@ -51,10 +51,8 @@ public void add(XdmNode document) {
if (closed) {
throw new XProcException("You can't add a document to a closed DocumentSequence.");
} else {
- if (!S9apiUtils.isDocument(document)) {
- throw XProcException.dynamicError(1);
- }
-
+ S9apiUtils.assertDocument(document);
+
//runtime.finest(logger, null, "Wrote " + (document == null ? "null" : document.getBaseURI()) + " to " + toString());
documents.add(document);
if (outputlog != null) {
@@ -588,7 +588,9 @@ private void doPutOrPostSinglepart(HttpEntityEnclosingRequest method, XdmNode bo
} else if (xmlContentType(contentType)) {
Serializer serializer = makeSerializer();
- if (!S9apiUtils.isDocumentContent(body.axisIterator(Axis.CHILD))) {
+ try {
+ S9apiUtils.assertDocumentContent(body.axisIterator(Axis.CHILD));
+ } catch (XProcException xe) {
throw XProcException.stepError(22);
}
@@ -6,10 +6,14 @@
import com.xmlcalabash.util.TreeWriter;
import com.xmlcalabash.io.WritablePipe;
import com.xmlcalabash.model.*;
+import net.sf.saxon.om.StructuredQName;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.XdmNode;
import net.sf.saxon.s9api.QName;
+import net.sf.saxon.trans.XPathException;
+import javax.xml.transform.SourceLocator;
+import javax.xml.transform.TransformerException;
import java.util.Vector;
/**
@@ -21,6 +25,11 @@
*/
public class XTry extends XCompoundStep {
private static final QName c_errors = new QName("c", XProcConstants.NS_XPROC_STEP, "errors");
+ private static final QName c_error = new QName("c", XProcConstants.NS_XPROC_STEP, "error");
+ private static QName _href = new QName("", "href");
+ private static QName _line = new QName("", "line");
+ private static QName _column = new QName("", "column");
+ private static QName _code = new QName("", "code");
private Vector<XdmNode> errors = new Vector<XdmNode> ();
public XTry(XProcRuntime runtime, Step step, XCompoundStep parent) {
@@ -92,12 +101,67 @@ public void run() throws SaxonApiException {
treeWriter.addStartElement(c_errors);
treeWriter.startContent();
+ boolean reported = false;
for (XdmNode doc : runtime.getXProcData().errors()) {
treeWriter.addSubtree(doc);
+ reported = true;
}
for (XdmNode doc : errors) {
treeWriter.addSubtree(doc);
+ reported = true;
+ }
+
+ if (!reported) {
+ // Hey, no one reported this exception. We better do it.
+ treeWriter.addStartElement(c_error);
+
+ String message = xe.getMessage();
+ StructuredQName qCode = null;
+
+ if (xe instanceof XPathException) {
+ XPathException xxx = (XPathException) xe;
+ qCode = xxx.getErrorCodeQName();
+
+ Throwable underlying = xe.getCause();
+ if (underlying != null) {
+ message = underlying.toString();
+ }
+ }
+
+ if (xe instanceof XProcException) {
+ XProcException xxx = (XProcException) xe;
+ QName code = xxx.getErrorCode();
+ qCode = new StructuredQName(code.getPrefix(), code.getNamespaceURI(), code.getLocalName());
+ message = xxx.getMessage();
+ Throwable underlying = xe.getCause();
+ if (underlying != null) {
+ message = underlying.getMessage();
+ }
+ }
+
+ if (qCode != null) {
+ treeWriter.addNamespace(qCode.getPrefix(), qCode.getNamespaceBinding().getURI());
+ treeWriter.addAttribute(_code, qCode.getDisplayName());
+ }
+
+ XStep step = runtime.runningStep();
+ if (step != null && step.getNode() != null) {
+ XdmNode node = step.getNode();
+ if (node.getBaseURI() != null) {
+ treeWriter.addAttribute(_href, node.getBaseURI().toString());
+ }
+ if (node.getLineNumber() > 0) {
+ treeWriter.addAttribute(_line, ""+node.getLineNumber());
+ }
+ if (node.getColumnNumber() > 0) {
+ treeWriter.addAttribute(_column, ""+node.getColumnNumber());
+ }
+ }
+
+ treeWriter.startContent();
+ treeWriter.addText(message);
+ treeWriter.addEndElement();
}
treeWriter.addEndElement();
@@ -382,42 +382,35 @@ public static boolean xpathSyntaxError(SaxonApiException sae) {
return (cause != null && cause instanceof XPathException);
}
- public static
- boolean isDocument(XdmNode doc) {
- boolean ok = true;
-
+ public static void assertDocument(XdmNode doc) {
if (doc.getNodeKind() == XdmNodeKind.DOCUMENT) {
- ok = S9apiUtils.isDocumentContent(doc.axisIterator(Axis.CHILD));
+ S9apiUtils.assertDocumentContent(doc.axisIterator(Axis.CHILD));
} else if (doc.getNodeKind() == XdmNodeKind.ELEMENT) {
// this is ok
} else {
- ok = false;
+ throw XProcException.dynamicError(1, "Document root cannot be " + doc.getNodeKind());
}
-
- return ok;
}
- public static
- boolean isDocumentContent(XdmSequenceIterator iter) {
- boolean ok = true;
-
+ public static void assertDocumentContent(XdmSequenceIterator iter) {
int elemCount = 0;
- while (ok && iter.hasNext()) {
+ while (iter.hasNext()) {
XdmNode child = (XdmNode) iter.next();
if (child.getNodeKind() == XdmNodeKind.ELEMENT) {
elemCount++;
- ok = ok && elemCount == 1;
+ if (elemCount > 1) {
+ throw XProcException.dynamicError(1, "Document must have exactly one top-level element");
+ }
} else if (child.getNodeKind() == XdmNodeKind.PROCESSING_INSTRUCTION
|| child.getNodeKind() == XdmNodeKind.COMMENT) {
// that's ok
} else if (child.getNodeKind() == XdmNodeKind.TEXT) {
- ok = ok && "".equals(child.getStringValue().trim());
+ if (!"".equals(child.getStringValue().trim()))
+ throw XProcException.dynamicError(1, "Only whitespace text nodes can appear at the top level in a document");
} else {
- ok = false;
+ throw XProcException.dynamicError(1, "Document cannot have top level " + child.getNodeKind());
}
}
-
- return ok;
}
// FIXME: This method exists only to work around a bug in SaxonHE 9.5.1.1

0 comments on commit 1f1c05e

Please sign in to comment.