suppress handled error message in processing xpath
when it contains an XML 1.1 escape sequence
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/xstream/XmlUtil.java b/core/src/main/java/org/apache/brooklyn/util/core/xstream/XmlUtil.java
index e989d5f..2699eeb 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/xstream/XmlUtil.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/xstream/XmlUtil.java
@@ -30,12 +30,16 @@
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
+import com.sun.org.apache.xerces.internal.xni.parser.XMLErrorHandler;
+import com.sun.org.apache.xml.internal.utils.DefaultErrorHandler;
import org.apache.brooklyn.util.exceptions.Exceptions;
import org.w3c.dom.Document;
+import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import com.google.common.annotations.Beta;
+import org.xml.sax.SAXParseException;
public class XmlUtil {
@@ -45,12 +49,40 @@
*/
private static class SharedDocumentBuilder {
private static ThreadLocal<DocumentBuilder> instance = new ThreadLocal<DocumentBuilder>();
-
- public static DocumentBuilder get() throws ParserConfigurationException {
+
+ /** xpath in particular prints to stderr and then throws or swallows; do the same, but without printing to stderr */
+ public static DocumentBuilder getSwallowingOrThrowingErrors(boolean throwIfWarning, boolean throwIfError, boolean throwIfFatal) {
+ ErrorHandler eh = new ErrorHandler() {
+ @Override
+ public void warning(SAXParseException exception) throws SAXException {
+ if (throwIfWarning) throw exception;
+ }
+ @Override
+ public void error(SAXParseException exception) throws SAXException {
+ if (throwIfError) throw exception;
+ }
+ @Override
+ public void fatalError(SAXParseException exception) throws SAXException {
+ if (throwIfFatal) throw exception;
+ }
+ };
+ return get(eh);
+ }
+
+ public static DocumentBuilder get() {
+ return get(null);
+ }
+
+ public static DocumentBuilder get(ErrorHandler errorHandler) {
DocumentBuilder result = instance.get();
if (result == null) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- result = factory.newDocumentBuilder();
+ try {
+ result = factory.newDocumentBuilder();
+ } catch (ParserConfigurationException e) {
+ throw Exceptions.propagate(e);
+ }
+ if (errorHandler!=null) result.setErrorHandler(errorHandler);
instance.set(result);
} else {
result.reset();
@@ -64,16 +96,16 @@
}
public static Object xpath(String xml, String xpath, QName returnType) {
+ return xpath(SharedDocumentBuilder.get(), xml, xpath, returnType);
+ }
+ public static Object xpath(DocumentBuilder builder, String xml, String xpath, QName returnType) {
try {
- DocumentBuilder builder = SharedDocumentBuilder.get();
Document doc = builder.parse(new InputSource(new StringReader(xml)));
XPathFactory xPathfactory = XPathFactory.newInstance();
XPathExpression expr = xPathfactory.newXPath().compile(xpath);
-
+
return expr.evaluate(doc, returnType);
- } catch (ParserConfigurationException e) {
- throw Exceptions.propagate(e);
} catch (SAXException e) {
throw Exceptions.propagate(e);
} catch (IOException e) {
@@ -97,7 +129,8 @@
@Beta
public static Object xpathHandlingIllegalChars(String xml, String xpath, QName returnType) {
try {
- return xpath(xml, xpath, returnType);
+ return xpath(SharedDocumentBuilder.getSwallowingOrThrowingErrors(false, false, true),
+ xml, xpath, returnType);
} catch (Exception e) {
SAXException saxe = Exceptions.getFirstThrowableOfType(e, SAXException.class);
if (saxe != null && saxe.toString().contains("&#")) {
diff --git a/core/src/test/java/org/apache/brooklyn/util/core/xstream/XmlUtilTest.java b/core/src/test/java/org/apache/brooklyn/util/core/xstream/XmlUtilTest.java
index 94ff2c8..31acda0 100644
--- a/core/src/test/java/org/apache/brooklyn/util/core/xstream/XmlUtilTest.java
+++ b/core/src/test/java/org/apache/brooklyn/util/core/xstream/XmlUtilTest.java
@@ -26,6 +26,7 @@
import javax.xml.xpath.XPathConstants;
+import org.apache.brooklyn.test.Asserts;
import org.apache.brooklyn.util.core.xstream.XmlUtil.Escaper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -100,6 +101,17 @@
}
@Test
+ public void testWeirdStrings() throws Exception {
+ // should work, and shouldn't print error to stderr anymore
+ Asserts.assertEquals(XmlUtil
+ .xpathHandlingIllegalChars("<x>" +
+// "\u001b" +
+ ""+
+ "abc<y>a</y></x>", "/x/y[text()]"),
+ "a");
+ }
+
+ @Test
public void testXpathWithEscapedCharsAndXmlUnversioned() throws Exception {
StringBuilder xml = new StringBuilder("<a><b>myb</b><c>");
for (int i = 0; i < Integer.valueOf("FFFF", 16); i++) {