You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by de...@apache.org on 2014/08/26 14:47:15 UTC

git commit: https://issues.apache.org/jira/browse/AMQ-5333 - make xpath parser features configurable

Repository: activemq
Updated Branches:
  refs/heads/trunk 4fa10356f -> b9696ac80


https://issues.apache.org/jira/browse/AMQ-5333 - make xpath parser features configurable


Project: http://git-wip-us.apache.org/repos/asf/activemq/repo
Commit: http://git-wip-us.apache.org/repos/asf/activemq/commit/b9696ac8
Tree: http://git-wip-us.apache.org/repos/asf/activemq/tree/b9696ac8
Diff: http://git-wip-us.apache.org/repos/asf/activemq/diff/b9696ac8

Branch: refs/heads/trunk
Commit: b9696ac80bb496b52d05c3884f81b0746d9af9e2
Parents: 4fa1035
Author: Dejan Bosanac <de...@nighttale.net>
Authored: Tue Aug 26 14:46:45 2014 +0200
Committer: Dejan Bosanac <de...@nighttale.net>
Committed: Tue Aug 26 14:47:06 2014 +0200

----------------------------------------------------------------------
 .../activemq/filter/JAXPXPathEvaluator.java     | 37 +++++++------
 .../activemq/filter/XalanXPathEvaluator.java    | 37 ++++++-------
 .../apache/activemq/filter/XPathExpression.java | 57 +++++++++++++++++++-
 3 files changed, 94 insertions(+), 37 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/activemq/blob/b9696ac8/activemq-broker/src/main/java/org/apache/activemq/filter/JAXPXPathEvaluator.java
----------------------------------------------------------------------
diff --git a/activemq-broker/src/main/java/org/apache/activemq/filter/JAXPXPathEvaluator.java b/activemq-broker/src/main/java/org/apache/activemq/filter/JAXPXPathEvaluator.java
index 0ce5055..e458181 100644
--- a/activemq-broker/src/main/java/org/apache/activemq/filter/JAXPXPathEvaluator.java
+++ b/activemq-broker/src/main/java/org/apache/activemq/filter/JAXPXPathEvaluator.java
@@ -16,32 +16,33 @@
  */
 package org.apache.activemq.filter;
 
-import java.io.StringReader;
+import org.apache.activemq.command.Message;
+import org.apache.activemq.util.ByteArrayInputStream;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+
 import javax.jms.BytesMessage;
 import javax.jms.JMSException;
 import javax.jms.TextMessage;
+import javax.xml.parsers.DocumentBuilder;
 import javax.xml.xpath.XPath;
 import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathExpressionException;
 import javax.xml.xpath.XPathFactory;
-
-import org.apache.activemq.command.Message;
-import org.apache.activemq.util.ByteArrayInputStream;
-import org.xml.sax.InputSource;
+import java.io.StringReader;
 
 public class JAXPXPathEvaluator implements XPathExpression.XPathEvaluator {
 
     private static final XPathFactory FACTORY = XPathFactory.newInstance();
-    private final javax.xml.xpath.XPathExpression expression;
     private final String xpathExpression;
+    private final DocumentBuilder builder;
+    private final XPath xpath = FACTORY.newXPath();
 
-    public JAXPXPathEvaluator(String xpathExpression) {
+    public JAXPXPathEvaluator(String xpathExpression, DocumentBuilder builder) throws Exception {
         this.xpathExpression = xpathExpression;
-        try {
-            XPath xpath = FACTORY.newXPath();
-            expression = xpath.compile(xpathExpression);
-        } catch (XPathExpressionException e) {
-            throw new RuntimeException("Invalid XPath expression: " + xpathExpression);
+        if (builder != null) {
+            this.builder = builder;
+        } else {
+            throw new RuntimeException("No document builder available");
         }
     }
 
@@ -61,8 +62,9 @@ public class JAXPXPathEvaluator implements XPathExpression.XPathEvaluator {
     private boolean evaluate(byte[] data) {
         try {
             InputSource inputSource = new InputSource(new ByteArrayInputStream(data));
-            return ((Boolean)expression.evaluate(inputSource, XPathConstants.BOOLEAN)).booleanValue();
-        } catch (XPathExpressionException e) {
+            Document inputDocument = builder.parse(inputSource);
+            return ((Boolean)xpath.evaluate(xpathExpression, inputDocument, XPathConstants.BOOLEAN)).booleanValue();
+        } catch (Exception e) {
             return false;
         }
     }
@@ -70,8 +72,9 @@ public class JAXPXPathEvaluator implements XPathExpression.XPathEvaluator {
     private boolean evaluate(String text) {
         try {
             InputSource inputSource = new InputSource(new StringReader(text));
-            return ((Boolean)expression.evaluate(inputSource, XPathConstants.BOOLEAN)).booleanValue();
-        } catch (XPathExpressionException e) {
+            Document inputDocument = builder.parse(inputSource);
+            return ((Boolean)xpath.evaluate(xpathExpression, inputDocument, XPathConstants.BOOLEAN)).booleanValue();
+        } catch (Exception e) {
             return false;
         }
     }

http://git-wip-us.apache.org/repos/asf/activemq/blob/b9696ac8/activemq-broker/src/main/java/org/apache/activemq/filter/XalanXPathEvaluator.java
----------------------------------------------------------------------
diff --git a/activemq-broker/src/main/java/org/apache/activemq/filter/XalanXPathEvaluator.java b/activemq-broker/src/main/java/org/apache/activemq/filter/XalanXPathEvaluator.java
index 1ea092f..7bfdaf0 100755
--- a/activemq-broker/src/main/java/org/apache/activemq/filter/XalanXPathEvaluator.java
+++ b/activemq-broker/src/main/java/org/apache/activemq/filter/XalanXPathEvaluator.java
@@ -16,34 +16,33 @@
  */
 package org.apache.activemq.filter;
 
-import java.io.StringReader;
+import org.apache.activemq.command.Message;
+import org.apache.activemq.util.ByteArrayInputStream;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
 
 import javax.jms.BytesMessage;
 import javax.jms.JMSException;
 import javax.jms.TextMessage;
+import javax.xml.parsers.DocumentBuilder;
 import javax.xml.xpath.XPath;
 import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathExpressionException;
 import javax.xml.xpath.XPathFactory;
-
-import org.apache.activemq.command.Message;
-import org.apache.activemq.util.ByteArrayInputStream;
-
-import org.xml.sax.InputSource;
+import java.io.StringReader;
 
 public class XalanXPathEvaluator implements XPathExpression.XPathEvaluator {
 
     private static final XPathFactory FACTORY = XPathFactory.newInstance();
-    private final javax.xml.xpath.XPathExpression expression;
     private final String xpathExpression;
+    private final DocumentBuilder builder;
+    private final XPath xpath = FACTORY.newXPath();
 
-    public XalanXPathEvaluator(String xpathExpression) {
+    public XalanXPathEvaluator(String xpathExpression, DocumentBuilder builder) throws Exception {
         this.xpathExpression = xpathExpression;
-        try {
-            XPath xpath = FACTORY.newXPath();
-            expression = xpath.compile(xpathExpression);
-        } catch (XPathExpressionException e) {
-            throw new RuntimeException("Invalid XPath expression: " + xpathExpression);
+        if (builder != null) {
+            this.builder = builder;
+        } else {
+            throw new RuntimeException("No document builder available");
         }
     }
 
@@ -63,8 +62,9 @@ public class XalanXPathEvaluator implements XPathExpression.XPathEvaluator {
     private boolean evaluate(byte[] data) {
         try {
             InputSource inputSource = new InputSource(new ByteArrayInputStream(data));
-            return ((Boolean)expression.evaluate(inputSource, XPathConstants.BOOLEAN)).booleanValue();
-        } catch (XPathExpressionException e) {
+            Document inputDocument = builder.parse(inputSource);
+            return ((Boolean) xpath.evaluate(xpathExpression, inputDocument, XPathConstants.BOOLEAN)).booleanValue();
+        } catch (Exception e) {
             return false;
         }
     }
@@ -72,8 +72,9 @@ public class XalanXPathEvaluator implements XPathExpression.XPathEvaluator {
     private boolean evaluate(String text) {
         try {
             InputSource inputSource = new InputSource(new StringReader(text));
-            return ((Boolean)expression.evaluate(inputSource, XPathConstants.BOOLEAN)).booleanValue();
-        } catch (XPathExpressionException e) {
+            Document inputDocument = builder.parse(inputSource);
+            return ((Boolean) xpath.evaluate(xpathExpression, inputDocument, XPathConstants.BOOLEAN)).booleanValue();
+        } catch (Exception e) {
             return false;
         }
     }

http://git-wip-us.apache.org/repos/asf/activemq/blob/b9696ac8/activemq-client/src/main/java/org/apache/activemq/filter/XPathExpression.java
----------------------------------------------------------------------
diff --git a/activemq-client/src/main/java/org/apache/activemq/filter/XPathExpression.java b/activemq-client/src/main/java/org/apache/activemq/filter/XPathExpression.java
index c29a312..75ab087 100755
--- a/activemq-client/src/main/java/org/apache/activemq/filter/XPathExpression.java
+++ b/activemq-client/src/main/java/org/apache/activemq/filter/XPathExpression.java
@@ -19,8 +19,15 @@ package org.apache.activemq.filter;
 import java.io.IOException;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
 
 import javax.jms.JMSException;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
 
 import org.apache.activemq.command.Message;
 import org.apache.activemq.util.JMSExceptionSupport;
@@ -35,8 +42,10 @@ public final class XPathExpression implements BooleanExpression {
     private static final Logger LOG = LoggerFactory.getLogger(XPathExpression.class);
     private static final String EVALUATOR_SYSTEM_PROPERTY = "org.apache.activemq.XPathEvaluatorClassName";
     private static final String DEFAULT_EVALUATOR_CLASS_NAME = "org.apache.activemq.filter.XalanXPathEvaluator";
+    public static final String DOCUMENT_BUILDER_FACTORY_FEATURE = "org.apache.activemq.documentBuilderFactory.feature";
 
     private static final Constructor EVALUATOR_CONSTRUCTOR;
+    private static DocumentBuilder builder = null;
 
     static {
         String cn = System.getProperty(EVALUATOR_SYSTEM_PROPERTY, DEFAULT_EVALUATOR_CLASS_NAME);
@@ -44,6 +53,21 @@ public final class XPathExpression implements BooleanExpression {
         try {
             try {
                 m = getXPathEvaluatorConstructor(cn);
+                DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
+                builderFactory.setNamespaceAware(true);
+                builderFactory.setIgnoringElementContentWhitespace(true);
+                builderFactory.setIgnoringComments(true);
+                try {
+                    // set some reasonable defaults
+                    builderFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
+                    builderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
+                    builderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+                } catch (ParserConfigurationException e) {
+                    LOG.warn("Error setting document builder factory feature", e);
+                }
+                // setup the feature from the system property
+                setupFeatures(builderFactory);
+                builder = builderFactory.newDocumentBuilder();
             } catch (Throwable e) {
                 LOG.warn("Invalid " + XPathEvaluator.class.getName() + " implementation: " + cn + ", reason: " + e, e);
                 cn = DEFAULT_EVALUATOR_CLASS_NAME;
@@ -75,12 +99,41 @@ public final class XPathExpression implements BooleanExpression {
         if (!XPathEvaluator.class.isAssignableFrom(c)) {
             throw new ClassCastException("" + c + " is not an instance of " + XPathEvaluator.class);
         }
-        return c.getConstructor(new Class[] {String.class});
+        return c.getConstructor(new Class[] {String.class, DocumentBuilder.class});
+    }
+
+    protected static void setupFeatures(DocumentBuilderFactory factory) {
+        Properties properties = System.getProperties();
+        List<String> features = new ArrayList<String>();
+        for (Map.Entry<Object, Object> prop : properties.entrySet()) {
+            String key = (String) prop.getKey();
+            if (key.startsWith(DOCUMENT_BUILDER_FACTORY_FEATURE)) {
+                String uri = key.split(DOCUMENT_BUILDER_FACTORY_FEATURE + ":")[1];
+                Boolean value = Boolean.valueOf((String)prop.getValue());
+                try {
+                    factory.setFeature(uri, value);
+                    features.add("feature " + uri + " value " + value);
+                } catch (ParserConfigurationException e) {
+                    LOG.warn("DocumentBuilderFactory doesn't support the feature {} with value {}, due to {}.", new Object[]{uri, value, e});
+                }
+            }
+        }
+        if (features.size() > 0) {
+            StringBuffer featureString = new StringBuffer();
+            // just log the configured feature
+            for (String feature : features) {
+                if (featureString.length() != 0) {
+                    featureString.append(", ");
+                }
+                featureString.append(feature);
+            }
+        }
+
     }
 
     private XPathEvaluator createEvaluator(String xpath2) {
         try {
-            return (XPathEvaluator)EVALUATOR_CONSTRUCTOR.newInstance(new Object[] {xpath});
+            return (XPathEvaluator)EVALUATOR_CONSTRUCTOR.newInstance(new Object[] {xpath, builder});
         } catch (InvocationTargetException e) {
             Throwable cause = e.getCause();
             if (cause instanceof RuntimeException) {