This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/master by this push:
     new e6a5226  CAMEL-15643: camel-xpath - Add option to pre-compile xpath 
expression
e6a5226 is described below

commit e6a5226f5428dfd0f7b8fc28ef5855e5b081c343
Author: Claus Ibsen <[email protected]>
AuthorDate: Tue Oct 6 17:15:53 2020 +0200

    CAMEL-15643: camel-xpath - Add option to pre-compile xpath expression
---
 .../apache/camel/catalog/docs/xpath-language.adoc  |  3 +-
 .../org/apache/camel/language/xpath/xpath.json     |  1 +
 .../camel-xpath/src/main/docs/xpath-language.adoc  |  3 +-
 .../apache/camel/language/xpath/XPathBuilder.java  | 43 ++++++++++++++++++----
 .../apache/camel/language/xpath/XPathLanguage.java | 17 +++++++++
 .../org/apache/camel/model/language/xpath.json     |  1 +
 .../camel/model/language/XPathExpression.java      | 19 ++++++++++
 .../reifier/language/XPathExpressionReifier.java   |  3 +-
 .../org/apache/camel/builder/xml/XPathTest.java    |  4 +-
 .../java/org/apache/camel/xml/in/ModelParser.java  |  1 +
 .../modules/languages/pages/xpath-language.adoc    |  3 +-
 11 files changed, 84 insertions(+), 14 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/xpath-language.adoc
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/xpath-language.adoc
index 3404897..049480c 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/xpath-language.adoc
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/xpath-language.adoc
@@ -45,7 +45,7 @@ from("queue:foo").
 == XPath Language options
 
 // language options: START
-The XPath language supports 9 options, which are listed below.
+The XPath language supports 10 options, which are listed below.
 
 
 
@@ -60,6 +60,7 @@ The XPath language supports 9 options, which are listed below.
 | logNamespaces | false | Boolean | Whether to log namespaces which can assist 
during trouble shooting
 | headerName |  | String | Name of header to use as input, instead of the 
message body
 | threadSafety | false | Boolean | Whether to enable thread-safety for the 
returned result of the xpath expression. This applies to when using NODESET as 
the result type, and the returned set has multiple elements. In this situation 
there can be thread-safety issues if you process the NODESET concurrently such 
as from a Camel Splitter EIP in parallel processing mode. This option prevents 
concurrency issues by doing defensive copies of the nodes. It is recommended to 
turn this option on i [...]
+| preCompile | true | Boolean | Whether to enable pre-compiling the xpath 
expression during initialization phase. pre-compile is enabled by default. This 
can be used to turn off, for example in cases the compilation phase is desired 
at the starting phase, such as if the application is pre-built with graalvm 
which would then load the xpath factory of the built operating system, and not 
a JVM runtime.
 | trim | true | Boolean | Whether to trim the value to remove leading and 
trailing whitespaces and line breaks
 |===
 // language options: END
diff --git 
a/components/camel-xpath/src/generated/resources/org/apache/camel/language/xpath/xpath.json
 
b/components/camel-xpath/src/generated/resources/org/apache/camel/language/xpath/xpath.json
index 57287f4..e5b94c1 100644
--- 
a/components/camel-xpath/src/generated/resources/org/apache/camel/language/xpath/xpath.json
+++ 
b/components/camel-xpath/src/generated/resources/org/apache/camel/language/xpath/xpath.json
@@ -25,6 +25,7 @@
     "logNamespaces": { "kind": "attribute", "displayName": "Log Namespaces", 
"required": false, "type": "boolean", "javaType": "java.lang.Boolean", 
"deprecated": false, "secret": false, "defaultValue": false, "description": 
"Whether to log namespaces which can assist during trouble shooting" },
     "headerName": { "kind": "attribute", "displayName": "Header Name", 
"required": false, "type": "string", "javaType": "java.lang.String", 
"deprecated": false, "secret": false, "description": "Name of header to use as 
input, instead of the message body" },
     "threadSafety": { "kind": "attribute", "displayName": "Thread Safety", 
"required": false, "type": "boolean", "javaType": "java.lang.Boolean", 
"deprecated": false, "secret": false, "defaultValue": false, "description": 
"Whether to enable thread-safety for the returned result of the xpath 
expression. This applies to when using NODESET as the result type, and the 
returned set has multiple elements. In this situation there can be 
thread-safety issues if you process the NODESET concurrent [...]
+    "preCompile": { "kind": "attribute", "displayName": "Pre Compile", 
"required": false, "type": "boolean", "javaType": "java.lang.Boolean", 
"deprecated": false, "secret": false, "defaultValue": true, "description": 
"Whether to enable pre-compiling the xpath expression during initialization 
phase. pre-compile is enabled by default. This can be used to turn off, for 
example in cases the compilation phase is desired at the starting phase, such 
as if the application is pre-built with graal [...]
     "trim": { "kind": "attribute", "displayName": "Trim", "required": false, 
"type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, 
"secret": false, "defaultValue": true, "description": "Whether to trim the 
value to remove leading and trailing whitespaces and line breaks" },
     "id": { "kind": "attribute", "displayName": "Id", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"secret": false, "description": "Sets the id of this node" }
   }
diff --git a/components/camel-xpath/src/main/docs/xpath-language.adoc 
b/components/camel-xpath/src/main/docs/xpath-language.adoc
index 3404897..049480c 100644
--- a/components/camel-xpath/src/main/docs/xpath-language.adoc
+++ b/components/camel-xpath/src/main/docs/xpath-language.adoc
@@ -45,7 +45,7 @@ from("queue:foo").
 == XPath Language options
 
 // language options: START
-The XPath language supports 9 options, which are listed below.
+The XPath language supports 10 options, which are listed below.
 
 
 
@@ -60,6 +60,7 @@ The XPath language supports 9 options, which are listed below.
 | logNamespaces | false | Boolean | Whether to log namespaces which can assist 
during trouble shooting
 | headerName |  | String | Name of header to use as input, instead of the 
message body
 | threadSafety | false | Boolean | Whether to enable thread-safety for the 
returned result of the xpath expression. This applies to when using NODESET as 
the result type, and the returned set has multiple elements. In this situation 
there can be thread-safety issues if you process the NODESET concurrently such 
as from a Camel Splitter EIP in parallel processing mode. This option prevents 
concurrency issues by doing defensive copies of the nodes. It is recommended to 
turn this option on i [...]
+| preCompile | true | Boolean | Whether to enable pre-compiling the xpath 
expression during initialization phase. pre-compile is enabled by default. This 
can be used to turn off, for example in cases the compilation phase is desired 
at the starting phase, such as if the application is pre-built with graalvm 
which would then load the xpath factory of the built operating system, and not 
a JVM runtime.
 | trim | true | Boolean | Whether to trim the value to remove leading and 
trailing whitespaces and line breaks
 |===
 // language options: END
diff --git 
a/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathBuilder.java
 
b/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathBuilder.java
index 42e2ee3..66d7985 100644
--- 
a/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathBuilder.java
+++ 
b/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathBuilder.java
@@ -71,11 +71,7 @@ import org.apache.camel.util.StringHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import static org.apache.camel.support.builder.Namespaces.DEFAULT_NAMESPACE;
-import static org.apache.camel.support.builder.Namespaces.FUNCTION_NAMESPACE;
-import static org.apache.camel.support.builder.Namespaces.IN_NAMESPACE;
-import static org.apache.camel.support.builder.Namespaces.OUT_NAMESPACE;
-import static 
org.apache.camel.support.builder.Namespaces.isMatchingNamespaceOrEmptyNamespace;
+import static org.apache.camel.support.builder.Namespaces.*;
 
 /**
  * Creates an XPath expression builder which creates a nodeset result by 
default. If you want to evaluate a String
@@ -109,6 +105,7 @@ public class XPathBuilder extends ServiceSupport
     private final ThreadLocal<Exchange> exchange = new ThreadLocal<>();
     private final MessageVariableResolver variableResolver = new 
MessageVariableResolver(exchange);
     private final Map<String, String> namespaces = new ConcurrentHashMap<>();
+    private boolean preCompile = true;
     private boolean threadSafety;
     private volatile XPathFactory xpathFactory;
     private volatile Class<?> documentType = Document.class;
@@ -166,6 +163,15 @@ public class XPathBuilder extends ServiceSupport
 
     @Override
     public void init(CamelContext context) {
+        if (preCompile) {
+            LOG.trace("PreCompiling new XPathExpression and adding to pool 
during initialization");
+            try {
+                XPathExpression xpathExpression = createXPathExpression();
+                pool.add(xpathExpression);
+            } catch (XPathExpressionException e) {
+                throw RuntimeCamelException.wrapRuntimeException(e);
+            }
+        }
     }
 
     @Override
@@ -496,6 +502,21 @@ public class XPathBuilder extends ServiceSupport
         return this;
     }
 
+    /**
+     * Whether to enable pre-compiling the xpath expression during 
initialization phase. pre-compile is enabled by
+     * default.
+     *
+     * This can be used to turn off, for example in cases the compilation 
phase is desired at the starting phase, such
+     * as if the application is pre-built with graalvm which would then load 
the xpath factory of the built operating
+     * system, and not a JVM runtime.
+     *
+     * @return the current builder.
+     */
+    public XPathBuilder preCompile(boolean preCompile) {
+        setPreCompile(preCompile);
+        return this;
+    }
+
     // Properties
     // 
-------------------------------------------------------------------------
 
@@ -551,6 +572,14 @@ public class XPathBuilder extends ServiceSupport
         this.threadSafety = threadSafety;
     }
 
+    public boolean isPreCompile() {
+        return preCompile;
+    }
+
+    public void setPreCompile(boolean preCompile) {
+        this.preCompile = preCompile;
+    }
+
     /**
      * Gets the namespace context, can be <tt>null</tt> if no custom context 
has been assigned.
      * <p/>
@@ -1078,7 +1107,7 @@ public class XPathBuilder extends ServiceSupport
      * started prior to being used.
      */
     protected synchronized XPathExpression createXPathExpression()
-            throws XPathExpressionException, 
XPathFactoryConfigurationException {
+            throws XPathExpressionException {
         // ensure we are started
         try {
             start();
@@ -1106,7 +1135,7 @@ public class XPathBuilder extends ServiceSupport
     }
 
     protected synchronized XPathExpression createTraceNamespaceExpression()
-            throws XPathFactoryConfigurationException, 
XPathExpressionException {
+            throws XPathExpressionException {
         // XPathFactory is not thread safe
         XPath xPath = getXPathFactory().newXPath();
         return xPath.compile(OBTAIN_ALL_NS_XPATH);
diff --git 
a/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathLanguage.java
 
b/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathLanguage.java
index 315a9bf..f896b63 100644
--- 
a/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathLanguage.java
+++ 
b/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathLanguage.java
@@ -40,6 +40,7 @@ public class XPathLanguage extends LanguageSupport {
     private Boolean threadSafety;
     private Boolean logNamespaces;
     private String headerName;
+    private Boolean preCompile;
 
     @Override
     public Predicate createPredicate(String expression) {
@@ -81,6 +82,7 @@ public class XPathLanguage extends LanguageSupport {
             setResultQName(qname);
         }
         setUseSaxon(property(Boolean.class, properties, "useSaxon", useSaxon));
+        setPreCompile(property(Boolean.class, properties, "preCompile", 
preCompile));
         setObjectModelUri(property(String.class, properties, "objectModelUri", 
objectModelUri));
         setThreadSafety(property(Boolean.class, properties, "threadSafety", 
threadSafety));
         setLogNamespaces(property(Boolean.class, properties, "logNamespaces", 
logNamespaces));
@@ -168,7 +170,22 @@ public class XPathLanguage extends LanguageSupport {
         return useSaxon != null && useSaxon;
     }
 
+    public Boolean getPreCompile() {
+        return preCompile;
+    }
+
+    public void setPreCompile(Boolean preCompile) {
+        this.preCompile = preCompile;
+    }
+
+    private boolean isPreCompile() {
+        return preCompile != null && preCompile;
+    }
+
     protected void configureBuilder(XPathBuilder builder) {
+        if (preCompile != null) {
+            builder.setPreCompile(preCompile);
+        }
         if (threadSafety != null) {
             builder.setThreadSafety(threadSafety);
         }
diff --git 
a/core/camel-core-engine/src/generated/resources/org/apache/camel/model/language/xpath.json
 
b/core/camel-core-engine/src/generated/resources/org/apache/camel/model/language/xpath.json
index 314a15d..0f740d5 100644
--- 
a/core/camel-core-engine/src/generated/resources/org/apache/camel/model/language/xpath.json
+++ 
b/core/camel-core-engine/src/generated/resources/org/apache/camel/model/language/xpath.json
@@ -21,6 +21,7 @@
     "logNamespaces": { "kind": "attribute", "displayName": "Log Namespaces", 
"required": false, "type": "boolean", "javaType": "java.lang.Boolean", 
"deprecated": false, "secret": false, "defaultValue": false, "description": 
"Whether to log namespaces which can assist during trouble shooting" },
     "headerName": { "kind": "attribute", "displayName": "Header Name", 
"required": false, "type": "string", "javaType": "java.lang.String", 
"deprecated": false, "secret": false, "description": "Name of header to use as 
input, instead of the message body" },
     "threadSafety": { "kind": "attribute", "displayName": "Thread Safety", 
"required": false, "type": "boolean", "javaType": "java.lang.Boolean", 
"deprecated": false, "secret": false, "defaultValue": false, "description": 
"Whether to enable thread-safety for the returned result of the xpath 
expression. This applies to when using NODESET as the result type, and the 
returned set has multiple elements. In this situation there can be 
thread-safety issues if you process the NODESET concurrent [...]
+    "preCompile": { "kind": "attribute", "displayName": "Pre Compile", 
"required": false, "type": "boolean", "javaType": "java.lang.Boolean", 
"deprecated": false, "secret": false, "defaultValue": true, "description": 
"Whether to enable pre-compiling the xpath expression during initialization 
phase. pre-compile is enabled by default. This can be used to turn off, for 
example in cases the compilation phase is desired at the starting phase, such 
as if the application is pre-built with graal [...]
     "trim": { "kind": "attribute", "displayName": "Trim", "required": false, 
"type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, 
"secret": false, "defaultValue": true, "description": "Whether to trim the 
value to remove leading and trailing whitespaces and line breaks" },
     "id": { "kind": "attribute", "displayName": "Id", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"secret": false, "description": "Sets the id of this node" }
   }
diff --git 
a/core/camel-core-engine/src/main/java/org/apache/camel/model/language/XPathExpression.java
 
b/core/camel-core-engine/src/main/java/org/apache/camel/model/language/XPathExpression.java
index d2c8ef4..b7618bb 100644
--- 
a/core/camel-core-engine/src/main/java/org/apache/camel/model/language/XPathExpression.java
+++ 
b/core/camel-core-engine/src/main/java/org/apache/camel/model/language/XPathExpression.java
@@ -64,6 +64,9 @@ public class XPathExpression extends NamespaceAwareExpression 
{
     @XmlAttribute
     @Metadata(label = "advanced", javaType = "java.lang.Boolean")
     private String threadSafety;
+    @XmlAttribute
+    @Metadata(label = "advanced", javaType = "java.lang.Boolean", defaultValue 
= "true")
+    private String preCompile;
 
     public XPathExpression() {
     }
@@ -213,6 +216,22 @@ public class XPathExpression extends 
NamespaceAwareExpression {
         this.threadSafety = threadSafety;
     }
 
+    public String getPreCompile() {
+        return preCompile;
+    }
+
+    /**
+     * Whether to enable pre-compiling the xpath expression during 
initialization phase. pre-compile is enabled by
+     * default.
+     *
+     * This can be used to turn off, for example in cases the compilation 
phase is desired at the starting phase, such
+     * as if the application is pre-built with graalvm which would then load 
the xpath factory of the built operating
+     * system, and not a JVM runtime.
+     */
+    public void setPreCompile(String preCompile) {
+        this.preCompile = preCompile;
+    }
+
     private void resolveXPathFactory(CamelContext camelContext) {
         // Factory and Object Model can be set simultaneously. The underlying
         // XPathBuilder allows for setting Saxon too, as it is simply a 
shortcut
diff --git 
a/core/camel-core-engine/src/main/java/org/apache/camel/reifier/language/XPathExpressionReifier.java
 
b/core/camel-core-engine/src/main/java/org/apache/camel/reifier/language/XPathExpressionReifier.java
index 6292a83..ead649e 100644
--- 
a/core/camel-core-engine/src/main/java/org/apache/camel/reifier/language/XPathExpressionReifier.java
+++ 
b/core/camel-core-engine/src/main/java/org/apache/camel/reifier/language/XPathExpressionReifier.java
@@ -66,7 +66,7 @@ public class XPathExpressionReifier extends 
ExpressionReifier<XPathExpression> {
     }
 
     protected Map<String, Object> createProperties() {
-        Map<String, Object> properties = new HashMap<>(9);
+        Map<String, Object> properties = new HashMap<>(10);
         properties.put("documentType", definition.getDocumentType());
         // resultType can either point to a QName or it can be a regular class 
that influence the qname
         // so we need this special logic to set resultQName and resultType 
accordingly
@@ -81,6 +81,7 @@ public class XPathExpressionReifier extends 
ExpressionReifier<XPathExpression> {
         properties.put("xpathFactory", definition.getXPathFactory());
         properties.put("objectModelUri", 
parseString(definition.getObjectModel()));
         properties.put("threadSafety", 
parseBoolean(definition.getThreadSafety()));
+        properties.put("preCompile", parseBoolean(definition.getPreCompile()));
         properties.put("logNamespaces", 
parseBoolean(definition.getLogNamespaces()));
         properties.put("headerName", parseString(definition.getHeaderName()));
         return properties;
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/builder/xml/XPathTest.java 
b/core/camel-core/src/test/java/org/apache/camel/builder/xml/XPathTest.java
index 2e4a077..88c52fc 100644
--- a/core/camel-core/src/test/java/org/apache/camel/builder/xml/XPathTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/builder/xml/XPathTest.java
@@ -41,7 +41,6 @@ import org.apache.camel.ContextTestSupport;
 import org.apache.camel.Exchange;
 import org.apache.camel.Expression;
 import org.apache.camel.Predicate;
-import org.apache.camel.language.xpath.InvalidXPathException;
 import org.apache.camel.language.xpath.XPathBuilder;
 import org.apache.camel.support.builder.Namespaces;
 import org.apache.camel.util.StringHelper;
@@ -86,8 +85,7 @@ public class XPathTest extends ContextTestSupport {
         try {
             assertPredicate("/foo/", "<foo><bar xyz='cheese'/></foo>", true);
             fail("Should have thrown exception");
-        } catch (InvalidXPathException e) {
-            assertEquals("/foo/", e.getXpath());
+        } catch (Exception e) {
             assertIsInstanceOf(XPathExpressionException.class, e.getCause());
         }
     }
diff --git 
a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java 
b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
index 394b9a3..7e99db4 100644
--- 
a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
+++ 
b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
@@ -2443,6 +2443,7 @@ public class ModelParser extends BaseParser {
                 case "headerName": def.setHeaderName(val); break;
                 case "logNamespaces": def.setLogNamespaces(val); break;
                 case "objectModel": def.setObjectModel(val); break;
+                case "preCompile": def.setPreCompile(val); break;
                 case "resultType": def.setResultTypeName(val); break;
                 case "saxon": def.setSaxon(val); break;
                 case "threadSafety": def.setThreadSafety(val); break;
diff --git a/docs/components/modules/languages/pages/xpath-language.adoc 
b/docs/components/modules/languages/pages/xpath-language.adoc
index 60dbea7..11b3a9b 100644
--- a/docs/components/modules/languages/pages/xpath-language.adoc
+++ b/docs/components/modules/languages/pages/xpath-language.adoc
@@ -47,7 +47,7 @@ from("queue:foo").
 == XPath Language options
 
 // language options: START
-The XPath language supports 9 options, which are listed below.
+The XPath language supports 10 options, which are listed below.
 
 
 
@@ -62,6 +62,7 @@ The XPath language supports 9 options, which are listed below.
 | logNamespaces | false | Boolean | Whether to log namespaces which can assist 
during trouble shooting
 | headerName |  | String | Name of header to use as input, instead of the 
message body
 | threadSafety | false | Boolean | Whether to enable thread-safety for the 
returned result of the xpath expression. This applies to when using NODESET as 
the result type, and the returned set has multiple elements. In this situation 
there can be thread-safety issues if you process the NODESET concurrently such 
as from a Camel Splitter EIP in parallel processing mode. This option prevents 
concurrency issues by doing defensive copies of the nodes. It is recommended to 
turn this option on i [...]
+| preCompile | true | Boolean | Whether to enable pre-compiling the xpath 
expression during initialization phase. pre-compile is enabled by default. This 
can be used to turn off, for example in cases the compilation phase is desired 
at the starting phase, such as if the application is pre-built with graalvm 
which would then load the xpath factory of the built operating system, and not 
a JVM runtime.
 | trim | true | Boolean | Whether to trim the value to remove leading and 
trailing whitespaces and line breaks
 |===
 // language options: END

Reply via email to