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
commit df0b29c1fc781409823bc84faeb58d44c4325e23 Author: Claus Ibsen <[email protected]> AuthorDate: Fri Oct 16 21:25:24 2020 +0200 CAMEL-15697: camel-joor - Camel expression langauge using jOOR runtime java compiled. --- .../apache/camel/catalog/docs/joor-language.adoc | 6 +- .../camel-joor/src/main/docs/joor-language.adoc | 6 +- .../java/org/apache/camel/language/joor/Joor.java | 6 ++ .../joor/JoorAnnotationExpressionFactory.java | 3 +- .../apache/camel/language/joor/JoorExpression.java | 72 ++++++++++------------ .../apache/camel/language/joor/JoorLanguage.java | 15 ++--- ...ourceTest.java => JoorPreCompileFalseTest.java} | 34 +++++++--- .../language/joor/JoorTransformResourceTest.java | 2 +- .../camel/reifier/language/ExpressionReifier.java | 8 ++- .../reifier/language/JoorExpressionReifier.java | 6 ++ .../modules/languages/pages/joor-language.adoc | 6 +- 11 files changed, 93 insertions(+), 71 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/joor-language.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/joor-language.adoc index b3485ea..3703f2c 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/joor-language.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/joor-language.adoc @@ -15,7 +15,7 @@ The jOOR library integrates with the Java compiler and performs runtime compilat NOTE: Java 8 is not supported. This requires Java 11 or 14. -== JOOR Options +== jOOR Options @@ -36,7 +36,7 @@ The jOOR language supports 4 options, which are listed below. === Variables -The JOOR language allows the following variables to be used in the script +The jOOR language allows the following variables to be used in the script [width="100%",cols="2,1m,7",options="header"] |=== @@ -49,7 +49,7 @@ The JOOR language allows the following variables to be used in the script === Sample -For example to transform the message using joor language to upper case +For example to transform the message using jOOR language to upper case [source,java] ---- diff --git a/components/camel-joor/src/main/docs/joor-language.adoc b/components/camel-joor/src/main/docs/joor-language.adoc index b3485ea..3703f2c 100644 --- a/components/camel-joor/src/main/docs/joor-language.adoc +++ b/components/camel-joor/src/main/docs/joor-language.adoc @@ -15,7 +15,7 @@ The jOOR library integrates with the Java compiler and performs runtime compilat NOTE: Java 8 is not supported. This requires Java 11 or 14. -== JOOR Options +== jOOR Options @@ -36,7 +36,7 @@ The jOOR language supports 4 options, which are listed below. === Variables -The JOOR language allows the following variables to be used in the script +The jOOR language allows the following variables to be used in the script [width="100%",cols="2,1m,7",options="header"] |=== @@ -49,7 +49,7 @@ The JOOR language allows the following variables to be used in the script === Sample -For example to transform the message using joor language to upper case +For example to transform the message using jOOR language to upper case [source,java] ---- diff --git a/components/camel-joor/src/main/java/org/apache/camel/language/joor/Joor.java b/components/camel-joor/src/main/java/org/apache/camel/language/joor/Joor.java index a781c23..e8533f5 100644 --- a/components/camel-joor/src/main/java/org/apache/camel/language/joor/Joor.java +++ b/components/camel-joor/src/main/java/org/apache/camel/language/joor/Joor.java @@ -36,6 +36,12 @@ public @interface Joor { String value(); /** + * Whether the expression should be pre compiled once during initialization phase. If this is turned off, then the + * expression is reloaded and compiled on each evaluation. + */ + boolean preCompile() default true; + + /** * Whether single quotes can be used as replacement for double quotes. This is convenient when you need to work with * strings inside strings. */ diff --git a/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorAnnotationExpressionFactory.java b/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorAnnotationExpressionFactory.java index 9691fbc..6039c01 100644 --- a/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorAnnotationExpressionFactory.java +++ b/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorAnnotationExpressionFactory.java @@ -31,7 +31,7 @@ public class JoorAnnotationExpressionFactory extends DefaultAnnotationExpression LanguageAnnotation languageAnnotation, Class<?> expressionReturnType) { String expression = getExpressionFromAnnotation(annotation); - JoorExpression answer = new JoorExpression(JoorLanguage.nextFQN(), expression); + JoorExpression answer = new JoorExpression(expression); if (expressionReturnType != null) { answer.setResultType(expressionReturnType); @@ -39,6 +39,7 @@ public class JoorAnnotationExpressionFactory extends DefaultAnnotationExpression if (annotation instanceof Joor) { Joor joorAnnotation = (Joor) annotation; + answer.setPreCompile(joorAnnotation.preCompile()); answer.setSingleQuotes(joorAnnotation.singleQuotes()); } diff --git a/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorExpression.java b/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorExpression.java index d01ce92..0f0e941 100644 --- a/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorExpression.java +++ b/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorExpression.java @@ -16,26 +16,23 @@ */ package org.apache.camel.language.joor; -import java.io.IOException; -import java.io.InputStream; +import java.util.concurrent.atomic.AtomicInteger; import org.apache.camel.CamelContext; import org.apache.camel.Exchange; import org.apache.camel.ExpressionEvaluationException; -import org.apache.camel.RuntimeCamelException; import org.apache.camel.support.ExpressionAdapter; -import org.apache.camel.support.ResourceHelper; -import org.apache.camel.util.IOHelper; +import org.apache.camel.support.ScriptHelper; import org.joor.Reflect; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class JoorExpression extends ExpressionAdapter { + private static final AtomicInteger COUNTER = new AtomicInteger(); private static final Logger LOG = LoggerFactory.getLogger(JoorExpression.class); private static Boolean JAVA8; - private final String fqn; private final String text; private String code; private Reflect compiled; @@ -44,8 +41,7 @@ public class JoorExpression extends ExpressionAdapter { private boolean preCompile = true; private boolean singleQuotes = true; - public JoorExpression(String fqn, String text) { - this.fqn = fqn; + public JoorExpression(String text) { this.text = text; } @@ -79,6 +75,27 @@ public class JoorExpression extends ExpressionAdapter { } @Override + public Object evaluate(Exchange exchange) { + try { + Reflect ref = compiled; + if (ref == null) { + String fqn = nextFQN(); + String eval = evalCode(exchange.getContext(), fqn, text); + ref = compile(fqn, eval); + } + Object out = ref + .call("evaluate", exchange.getContext(), exchange, exchange.getIn(), exchange.getIn().getBody()).get(); + if (out != null && resultType != null) { + return exchange.getContext().getTypeConverter().convertTo(resultType, exchange, out); + } else { + return out; + } + } catch (Exception e) { + throw new ExpressionEvaluationException(this, exchange, e); + } + } + + @Override public void init(CamelContext context) { super.init(context); @@ -90,7 +107,8 @@ public class JoorExpression extends ExpressionAdapter { } if (preCompile) { - this.code = evalCode(context, text); + String fqn = nextFQN(); + this.code = evalCode(context, fqn, text); LOG.debug(code); this.compiled = compile(fqn, code); } @@ -104,18 +122,12 @@ public class JoorExpression extends ExpressionAdapter { } } - private String evalCode(CamelContext camelContext, String text) { + private String evalCode(CamelContext camelContext, String fqn, String text) { String qn = fqn.substring(0, fqn.lastIndexOf('.')); String name = fqn.substring(fqn.lastIndexOf('.') + 1); - if (text.startsWith("resource:")) { - String url = text.substring(9); - try (InputStream is = ResourceHelper.resolveMandatoryResourceAsInputStream(camelContext, url)) { - text = IOHelper.loadText(is); - } catch (IOException e) { - throw RuntimeCamelException.wrapRuntimeException(e); - } - } + // reload script + text = ScriptHelper.resolveOptionalExternalScript(camelContext, text); // trim text text = text.trim(); @@ -154,30 +166,14 @@ public class JoorExpression extends ExpressionAdapter { return sb.toString(); } - @Override - public Object evaluate(Exchange exchange) { - try { - Reflect ref = compiled; - if (ref == null) { - String eval = evalCode(exchange.getContext(), text); - ref = compile(fqn, eval); - } - Object out = ref - .call("evaluate", exchange.getContext(), exchange, exchange.getIn(), exchange.getIn().getBody()).get(); - if (out != null && resultType != null) { - return exchange.getContext().getTypeConverter().convertTo(resultType, exchange, out); - } else { - return out; - } - } catch (Exception e) { - throw new ExpressionEvaluationException(this, exchange, e); - } - } - private static int getJavaMajorVersion() { String javaSpecVersion = System.getProperty("java.specification.version"); return javaSpecVersion.contains(".") ? Integer.parseInt(javaSpecVersion.split("\\.")[1]) : Integer.parseInt(javaSpecVersion); } + private static String nextFQN() { + return "org.apache.camel.language.joor.compiled.JoorLanguage" + COUNTER.incrementAndGet(); + } + } diff --git a/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorLanguage.java b/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorLanguage.java index 3fdb508..3b8c703 100644 --- a/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorLanguage.java +++ b/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorLanguage.java @@ -16,8 +16,6 @@ */ package org.apache.camel.language.joor; -import java.util.concurrent.atomic.AtomicInteger; - import org.apache.camel.Expression; import org.apache.camel.Predicate; import org.apache.camel.StaticService; @@ -33,7 +31,6 @@ public class JoorLanguage extends LanguageSupport implements StaticService { private static final Logger LOG = LoggerFactory.getLogger(JoorLanguage.class); private long taken; - private static final AtomicInteger COUNTER = new AtomicInteger(); private boolean preCompile = true; private Class<?> resultType; @@ -70,7 +67,7 @@ public class JoorLanguage extends LanguageSupport implements StaticService { @Override public Expression createExpression(String expression) { - JoorExpression exp = new JoorExpression(nextFQN(), expression); + JoorExpression exp = new JoorExpression(expression); exp.setResultType(resultType); exp.setSingleQuotes(singleQuotes); @@ -88,7 +85,7 @@ public class JoorLanguage extends LanguageSupport implements StaticService { @Override public Expression createExpression(String expression, Object[] properties) { - JoorExpression exp = new JoorExpression(nextFQN(), expression); + JoorExpression exp = new JoorExpression(expression); exp.setPreCompile(property(boolean.class, properties, 0, preCompile)); exp.setResultType(property(Class.class, properties, 1, resultType)); exp.setSingleQuotes(property(boolean.class, properties, 2, singleQuotes)); @@ -96,10 +93,6 @@ public class JoorLanguage extends LanguageSupport implements StaticService { return exp; } - static String nextFQN() { - return "org.apache.camel.language.joor.compiled.JoorLanguage" + COUNTER.incrementAndGet(); - } - @Override public void start() { // noop @@ -107,8 +100,8 @@ public class JoorLanguage extends LanguageSupport implements StaticService { @Override public void stop() { - if (COUNTER.get() > 0) { - LOG.info("jOOR language compiled {} expressions in total {} millis", COUNTER, taken); + if (taken > 0) { + LOG.info("jOOR language compilations took {} millis", taken); } } } diff --git a/components/camel-joor/src/test/java/org/apache/camel/language/joor/JoorTransformResourceTest.java b/components/camel-joor/src/test/java/org/apache/camel/language/joor/JoorPreCompileFalseTest.java similarity index 55% copy from components/camel-joor/src/test/java/org/apache/camel/language/joor/JoorTransformResourceTest.java copy to components/camel-joor/src/test/java/org/apache/camel/language/joor/JoorPreCompileFalseTest.java index 38317c9..303f23f 100644 --- a/components/camel-joor/src/test/java/org/apache/camel/language/joor/JoorTransformResourceTest.java +++ b/components/camel-joor/src/test/java/org/apache/camel/language/joor/JoorPreCompileFalseTest.java @@ -16,33 +16,47 @@ */ package org.apache.camel.language.joor; +import org.apache.camel.Exchange; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.test.junit5.CamelTestSupport; import org.junit.jupiter.api.Test; -public class JoorTransformResourceTest extends CamelTestSupport { +public class JoorPreCompileFalseTest extends CamelTestSupport { @Override protected RouteBuilder createRouteBuilder() throws Exception { return new RouteBuilder() { @Override public void configure() throws Exception { + JoorLanguage joor = (JoorLanguage) context.resolveLanguage("joor"); + joor.setPreCompile(false); + from("direct:start") - .transform().joor("resource:myjoor.joor") + .transform().joor("resource:file:target/update.joor") .to("mock:result"); } }; } @Test - public void testTransform() throws Exception { - getMockEndpoint("mock:result").expectedBodiesReceived("A great number", "Happy riding", "An old Camel rider", - "A great number"); - - template.sendBody("direct:start", 20); - template.sendBody("direct:start", 44); - template.sendBody("direct:start", 101); - template.sendBody("direct:start", 50); + public void testPreCompileFalse() throws Exception { + template.sendBodyAndHeader("file:target?fileExist=Override", "'Hello ' + body", Exchange.FILE_NAME, "update.joor"); + + getMockEndpoint("mock:result").expectedBodiesReceived("Hello World", "Hello Camel"); + template.sendBody("direct:start", "World"); + template.sendBody("direct:start", "Camel"); + + assertMockEndpointsSatisfied(); + + // update file + resetMocks(); + + template.sendBodyAndHeader("file:target?fileExist=Override", "'Bye ' + body", Exchange.FILE_NAME, "update.joor"); + + getMockEndpoint("mock:result").expectedBodiesReceived("Bye World", "Bye Camel"); + + template.sendBody("direct:start", "World"); + template.sendBody("direct:start", "Camel"); assertMockEndpointsSatisfied(); } diff --git a/components/camel-joor/src/test/java/org/apache/camel/language/joor/JoorTransformResourceTest.java b/components/camel-joor/src/test/java/org/apache/camel/language/joor/JoorTransformResourceTest.java index 38317c9..b159268 100644 --- a/components/camel-joor/src/test/java/org/apache/camel/language/joor/JoorTransformResourceTest.java +++ b/components/camel-joor/src/test/java/org/apache/camel/language/joor/JoorTransformResourceTest.java @@ -28,7 +28,7 @@ public class JoorTransformResourceTest extends CamelTestSupport { @Override public void configure() throws Exception { from("direct:start") - .transform().joor("resource:myjoor.joor") + .transform().joor("resource:classpath:myjoor.joor") .to("mock:result"); } }; diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/reifier/language/ExpressionReifier.java b/core/camel-core-engine/src/main/java/org/apache/camel/reifier/language/ExpressionReifier.java index e23f3c5..38d08f6 100644 --- a/core/camel-core-engine/src/main/java/org/apache/camel/reifier/language/ExpressionReifier.java +++ b/core/camel-core-engine/src/main/java/org/apache/camel/reifier/language/ExpressionReifier.java @@ -112,6 +112,10 @@ public class ExpressionReifier<T extends ExpressionDefinition> extends AbstractR EXPRESSIONS.clear(); } + public boolean isResolveOptionalExternalScriptEnabled() { + return true; + } + public Expression createExpression() { Expression expression = definition.getExpressionValue(); if (expression == null) { @@ -132,7 +136,9 @@ public class ExpressionReifier<T extends ExpressionDefinition> extends AbstractR } // resolve the expression as it may be an external script from // the classpath/file etc - exp = ScriptHelper.resolveOptionalExternalScript(camelContext, exp); + if (isResolveOptionalExternalScriptEnabled()) { + exp = ScriptHelper.resolveOptionalExternalScript(camelContext, exp); + } configureLanguage(language); expression = createExpression(language, exp); configureExpression(expression); diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/reifier/language/JoorExpressionReifier.java b/core/camel-core-engine/src/main/java/org/apache/camel/reifier/language/JoorExpressionReifier.java index 491ae9e..1a4da7c 100644 --- a/core/camel-core-engine/src/main/java/org/apache/camel/reifier/language/JoorExpressionReifier.java +++ b/core/camel-core-engine/src/main/java/org/apache/camel/reifier/language/JoorExpressionReifier.java @@ -51,6 +51,12 @@ public class JoorExpressionReifier extends ExpressionReifier<JoorExpression> { } @Override + public boolean isResolveOptionalExternalScriptEnabled() { + // we handle this in camel-joor + return false; + } + + @Override protected Expression createExpression(Language language, String exp) { return language.createExpression(exp, createProperties()); } diff --git a/docs/components/modules/languages/pages/joor-language.adoc b/docs/components/modules/languages/pages/joor-language.adoc index 403848e..6d69884 100644 --- a/docs/components/modules/languages/pages/joor-language.adoc +++ b/docs/components/modules/languages/pages/joor-language.adoc @@ -17,7 +17,7 @@ The jOOR library integrates with the Java compiler and performs runtime compilat NOTE: Java 8 is not supported. This requires Java 11 or 14. -== JOOR Options +== jOOR Options @@ -38,7 +38,7 @@ The jOOR language supports 4 options, which are listed below. === Variables -The JOOR language allows the following variables to be used in the script +The jOOR language allows the following variables to be used in the script [width="100%",cols="2,1m,7",options="header"] |=== @@ -51,7 +51,7 @@ The JOOR language allows the following variables to be used in the script === Sample -For example to transform the message using joor language to upper case +For example to transform the message using jOOR language to upper case [source,java] ----
