mirror of https://github.com/apache/activemq.git
https://issues.apache.org/jira/browse/AMQ-5333 - make xpath parser features configurable
This commit is contained in:
parent
4fa10356f0
commit
b9696ac80b
|
@ -16,32 +16,33 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.activemq.filter;
|
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.BytesMessage;
|
||||||
import javax.jms.JMSException;
|
import javax.jms.JMSException;
|
||||||
import javax.jms.TextMessage;
|
import javax.jms.TextMessage;
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
import javax.xml.xpath.XPath;
|
import javax.xml.xpath.XPath;
|
||||||
import javax.xml.xpath.XPathConstants;
|
import javax.xml.xpath.XPathConstants;
|
||||||
import javax.xml.xpath.XPathExpressionException;
|
|
||||||
import javax.xml.xpath.XPathFactory;
|
import javax.xml.xpath.XPathFactory;
|
||||||
|
import java.io.StringReader;
|
||||||
import org.apache.activemq.command.Message;
|
|
||||||
import org.apache.activemq.util.ByteArrayInputStream;
|
|
||||||
import org.xml.sax.InputSource;
|
|
||||||
|
|
||||||
public class JAXPXPathEvaluator implements XPathExpression.XPathEvaluator {
|
public class JAXPXPathEvaluator implements XPathExpression.XPathEvaluator {
|
||||||
|
|
||||||
private static final XPathFactory FACTORY = XPathFactory.newInstance();
|
private static final XPathFactory FACTORY = XPathFactory.newInstance();
|
||||||
private final javax.xml.xpath.XPathExpression expression;
|
|
||||||
private final String xpathExpression;
|
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;
|
this.xpathExpression = xpathExpression;
|
||||||
try {
|
if (builder != null) {
|
||||||
XPath xpath = FACTORY.newXPath();
|
this.builder = builder;
|
||||||
expression = xpath.compile(xpathExpression);
|
} else {
|
||||||
} catch (XPathExpressionException e) {
|
throw new RuntimeException("No document builder available");
|
||||||
throw new RuntimeException("Invalid XPath expression: " + xpathExpression);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,8 +62,9 @@ public class JAXPXPathEvaluator implements XPathExpression.XPathEvaluator {
|
||||||
private boolean evaluate(byte[] data) {
|
private boolean evaluate(byte[] data) {
|
||||||
try {
|
try {
|
||||||
InputSource inputSource = new InputSource(new ByteArrayInputStream(data));
|
InputSource inputSource = new InputSource(new ByteArrayInputStream(data));
|
||||||
return ((Boolean)expression.evaluate(inputSource, XPathConstants.BOOLEAN)).booleanValue();
|
Document inputDocument = builder.parse(inputSource);
|
||||||
} catch (XPathExpressionException e) {
|
return ((Boolean)xpath.evaluate(xpathExpression, inputDocument, XPathConstants.BOOLEAN)).booleanValue();
|
||||||
|
} catch (Exception e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,8 +72,9 @@ public class JAXPXPathEvaluator implements XPathExpression.XPathEvaluator {
|
||||||
private boolean evaluate(String text) {
|
private boolean evaluate(String text) {
|
||||||
try {
|
try {
|
||||||
InputSource inputSource = new InputSource(new StringReader(text));
|
InputSource inputSource = new InputSource(new StringReader(text));
|
||||||
return ((Boolean)expression.evaluate(inputSource, XPathConstants.BOOLEAN)).booleanValue();
|
Document inputDocument = builder.parse(inputSource);
|
||||||
} catch (XPathExpressionException e) {
|
return ((Boolean)xpath.evaluate(xpathExpression, inputDocument, XPathConstants.BOOLEAN)).booleanValue();
|
||||||
|
} catch (Exception e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,34 +16,33 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.activemq.filter;
|
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.BytesMessage;
|
||||||
import javax.jms.JMSException;
|
import javax.jms.JMSException;
|
||||||
import javax.jms.TextMessage;
|
import javax.jms.TextMessage;
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
import javax.xml.xpath.XPath;
|
import javax.xml.xpath.XPath;
|
||||||
import javax.xml.xpath.XPathConstants;
|
import javax.xml.xpath.XPathConstants;
|
||||||
import javax.xml.xpath.XPathExpressionException;
|
|
||||||
import javax.xml.xpath.XPathFactory;
|
import javax.xml.xpath.XPathFactory;
|
||||||
|
import java.io.StringReader;
|
||||||
import org.apache.activemq.command.Message;
|
|
||||||
import org.apache.activemq.util.ByteArrayInputStream;
|
|
||||||
|
|
||||||
import org.xml.sax.InputSource;
|
|
||||||
|
|
||||||
public class XalanXPathEvaluator implements XPathExpression.XPathEvaluator {
|
public class XalanXPathEvaluator implements XPathExpression.XPathEvaluator {
|
||||||
|
|
||||||
private static final XPathFactory FACTORY = XPathFactory.newInstance();
|
private static final XPathFactory FACTORY = XPathFactory.newInstance();
|
||||||
private final javax.xml.xpath.XPathExpression expression;
|
|
||||||
private final String xpathExpression;
|
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;
|
this.xpathExpression = xpathExpression;
|
||||||
try {
|
if (builder != null) {
|
||||||
XPath xpath = FACTORY.newXPath();
|
this.builder = builder;
|
||||||
expression = xpath.compile(xpathExpression);
|
} else {
|
||||||
} catch (XPathExpressionException e) {
|
throw new RuntimeException("No document builder available");
|
||||||
throw new RuntimeException("Invalid XPath expression: " + xpathExpression);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,8 +62,9 @@ public class XalanXPathEvaluator implements XPathExpression.XPathEvaluator {
|
||||||
private boolean evaluate(byte[] data) {
|
private boolean evaluate(byte[] data) {
|
||||||
try {
|
try {
|
||||||
InputSource inputSource = new InputSource(new ByteArrayInputStream(data));
|
InputSource inputSource = new InputSource(new ByteArrayInputStream(data));
|
||||||
return ((Boolean)expression.evaluate(inputSource, XPathConstants.BOOLEAN)).booleanValue();
|
Document inputDocument = builder.parse(inputSource);
|
||||||
} catch (XPathExpressionException e) {
|
return ((Boolean) xpath.evaluate(xpathExpression, inputDocument, XPathConstants.BOOLEAN)).booleanValue();
|
||||||
|
} catch (Exception e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,8 +72,9 @@ public class XalanXPathEvaluator implements XPathExpression.XPathEvaluator {
|
||||||
private boolean evaluate(String text) {
|
private boolean evaluate(String text) {
|
||||||
try {
|
try {
|
||||||
InputSource inputSource = new InputSource(new StringReader(text));
|
InputSource inputSource = new InputSource(new StringReader(text));
|
||||||
return ((Boolean)expression.evaluate(inputSource, XPathConstants.BOOLEAN)).booleanValue();
|
Document inputDocument = builder.parse(inputSource);
|
||||||
} catch (XPathExpressionException e) {
|
return ((Boolean) xpath.evaluate(xpathExpression, inputDocument, XPathConstants.BOOLEAN)).booleanValue();
|
||||||
|
} catch (Exception e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,15 @@ package org.apache.activemq.filter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
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.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.command.Message;
|
||||||
import org.apache.activemq.util.JMSExceptionSupport;
|
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 Logger LOG = LoggerFactory.getLogger(XPathExpression.class);
|
||||||
private static final String EVALUATOR_SYSTEM_PROPERTY = "org.apache.activemq.XPathEvaluatorClassName";
|
private static final String EVALUATOR_SYSTEM_PROPERTY = "org.apache.activemq.XPathEvaluatorClassName";
|
||||||
private static final String DEFAULT_EVALUATOR_CLASS_NAME = "org.apache.activemq.filter.XalanXPathEvaluator";
|
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 final Constructor EVALUATOR_CONSTRUCTOR;
|
||||||
|
private static DocumentBuilder builder = null;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
String cn = System.getProperty(EVALUATOR_SYSTEM_PROPERTY, DEFAULT_EVALUATOR_CLASS_NAME);
|
String cn = System.getProperty(EVALUATOR_SYSTEM_PROPERTY, DEFAULT_EVALUATOR_CLASS_NAME);
|
||||||
|
@ -44,6 +53,21 @@ public final class XPathExpression implements BooleanExpression {
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
m = getXPathEvaluatorConstructor(cn);
|
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) {
|
} catch (Throwable e) {
|
||||||
LOG.warn("Invalid " + XPathEvaluator.class.getName() + " implementation: " + cn + ", reason: " + e, e);
|
LOG.warn("Invalid " + XPathEvaluator.class.getName() + " implementation: " + cn + ", reason: " + e, e);
|
||||||
cn = DEFAULT_EVALUATOR_CLASS_NAME;
|
cn = DEFAULT_EVALUATOR_CLASS_NAME;
|
||||||
|
@ -75,12 +99,41 @@ public final class XPathExpression implements BooleanExpression {
|
||||||
if (!XPathEvaluator.class.isAssignableFrom(c)) {
|
if (!XPathEvaluator.class.isAssignableFrom(c)) {
|
||||||
throw new ClassCastException("" + c + " is not an instance of " + XPathEvaluator.class);
|
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) {
|
private XPathEvaluator createEvaluator(String xpath2) {
|
||||||
try {
|
try {
|
||||||
return (XPathEvaluator)EVALUATOR_CONSTRUCTOR.newInstance(new Object[] {xpath});
|
return (XPathEvaluator)EVALUATOR_CONSTRUCTOR.newInstance(new Object[] {xpath, builder});
|
||||||
} catch (InvocationTargetException e) {
|
} catch (InvocationTargetException e) {
|
||||||
Throwable cause = e.getCause();
|
Throwable cause = e.getCause();
|
||||||
if (cause instanceof RuntimeException) {
|
if (cause instanceof RuntimeException) {
|
||||||
|
|
Loading…
Reference in New Issue