This is an automated email from the ASF dual-hosted git repository. gnodet pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel.git
commit 7afcecd94288e88df957f3a4f4d0facb1e747b8f Author: Guillaume Nodet <gno...@gmail.com> AuthorDate: Wed Mar 18 10:07:45 2020 +0100 Add an init method to Expression / Predicate --- .../apache/camel/language/bean/BeanExpression.java | 4 + .../camel/component/mock/MockExpressionClause.java | 34 +- .../camel/component/mock/MockValueBuilder.java | 6 + .../apache/camel/language/xpath/XPathBuilder.java | 4 + .../src/main/java/org/apache/camel/Expression.java | 7 + .../src/main/java/org/apache/camel/Predicate.java | 6 + .../apache/camel/processor/FilterProcessor.java | 11 +- .../org/apache/camel/builder/ExpressionClause.java | 34 +- .../org/apache/camel/builder/SimpleBuilder.java | 88 ++++-- .../camel/model/language/ExpressionDefinition.java | 10 + .../apache/camel/reifier/ExpressionReifier.java | 2 +- .../org/apache/camel/reifier/FilterReifier.java | 2 +- .../reifier/language/SimpleExpressionReifier.java | 37 ++- .../apache/camel/processor/TryProcessorTest.java | 5 + .../apache/camel/processor/ValidateSimpleTest.java | 4 +- .../apache/camel/support/ExpressionSupport.java | 5 + .../support/ExpressionToPredicateAdapter.java | 5 + .../org/apache/camel/support/ScriptHelper.java | 10 + .../support/builder/BinaryPredicateSupport.java | 7 + .../camel/support/builder/ExpressionBuilder.java | 342 +++++++++++++++++---- .../apache/camel/support/builder/ValueBuilder.java | 6 + 21 files changed, 512 insertions(+), 117 deletions(-) diff --git a/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanExpression.java b/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanExpression.java index 516c131..3d48bf0 100644 --- a/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanExpression.java +++ b/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanExpression.java @@ -110,6 +110,10 @@ public class BeanExpression implements Expression, Predicate, AfterPropertiesCon } @Override + public void init(CamelContext context) { + } + + @Override public String toString() { StringBuilder sb = new StringBuilder("BeanExpression["); if (bean != null) { diff --git a/components/camel-mock/src/main/java/org/apache/camel/component/mock/MockExpressionClause.java b/components/camel-mock/src/main/java/org/apache/camel/component/mock/MockExpressionClause.java index aa3c77d..ba74616b 100644 --- a/components/camel-mock/src/main/java/org/apache/camel/component/mock/MockExpressionClause.java +++ b/components/camel-mock/src/main/java/org/apache/camel/component/mock/MockExpressionClause.java @@ -21,6 +21,7 @@ import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Supplier; +import org.apache.camel.CamelContext; import org.apache.camel.Exchange; import org.apache.camel.Expression; import org.apache.camel.ExpressionFactory; @@ -425,23 +426,32 @@ public class MockExpressionClause<T> implements Expression, Predicate { return delegate.getExpressionType(); } + private volatile Expression expr; + @Override - public <T> T evaluate(Exchange exchange, Class<T> type) { - if (getExpressionValue() != null) { - return getExpressionValue().evaluate(exchange, type); - } else { - Expression exp = delegate.getExpressionType().createExpression(exchange.getContext()); - return exp.evaluate(exchange, type); + public void init(CamelContext context) { + if (expr == null) { + synchronized (this) { + if (expr == null) { + expr = getExpressionValue(); + if (expr == null) { + expr = getExpressionType().createExpression(context); + } + expr.init(context); + } + } } } @Override + public <T> T evaluate(Exchange exchange, Class<T> type) { + init(exchange.getContext()); + return expr.evaluate(exchange, type); + } + + @Override public boolean matches(Exchange exchange) { - if (getExpressionValue() != null) { - return new ExpressionToPredicateAdapter(getExpressionValue()).matches(exchange); - } else { - Expression exp = delegate.getExpressionType().createExpression(exchange.getContext()); - return new ExpressionToPredicateAdapter(exp).matches(exchange); - } + init(exchange.getContext()); + return new ExpressionToPredicateAdapter(expr).matches(exchange); } } diff --git a/components/camel-mock/src/main/java/org/apache/camel/component/mock/MockValueBuilder.java b/components/camel-mock/src/main/java/org/apache/camel/component/mock/MockValueBuilder.java index 551c524..4082a0e 100644 --- a/components/camel-mock/src/main/java/org/apache/camel/component/mock/MockValueBuilder.java +++ b/components/camel-mock/src/main/java/org/apache/camel/component/mock/MockValueBuilder.java @@ -21,6 +21,7 @@ import java.util.Comparator; import java.util.List; import java.util.concurrent.atomic.AtomicReference; +import org.apache.camel.CamelContext; import org.apache.camel.Exchange; import org.apache.camel.Expression; import org.apache.camel.Predicate; @@ -44,6 +45,11 @@ public class MockValueBuilder implements Expression, Predicate { } @Override + public void init(CamelContext context) { + expression.init(context); + } + + @Override public <T> T evaluate(Exchange exchange, Class<T> type) { return expression.evaluate(exchange, type); } 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 6ff9fef..7adb463 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 @@ -171,6 +171,10 @@ public class XPathBuilder extends ServiceSupport implements CamelContextAware, E } @Override + public void init(CamelContext context) { + } + + @Override public boolean configure(CamelContext camelContext, Object target, String name, Object value, boolean ignoreCase) { if (target != this) { throw new IllegalStateException("Can only configure our own instance !"); diff --git a/core/camel-api/src/main/java/org/apache/camel/Expression.java b/core/camel-api/src/main/java/org/apache/camel/Expression.java index 4995d0b..6fc0f64 100644 --- a/core/camel-api/src/main/java/org/apache/camel/Expression.java +++ b/core/camel-api/src/main/java/org/apache/camel/Expression.java @@ -30,4 +30,11 @@ public interface Expression { * @return the value of the expression */ <T> T evaluate(Exchange exchange, Class<T> type); + + /** + * Initialize the expression with the given camel context + */ + default void init(CamelContext context) { + } + } diff --git a/core/camel-api/src/main/java/org/apache/camel/Predicate.java b/core/camel-api/src/main/java/org/apache/camel/Predicate.java index d6a81c0..2f7f3dc 100644 --- a/core/camel-api/src/main/java/org/apache/camel/Predicate.java +++ b/core/camel-api/src/main/java/org/apache/camel/Predicate.java @@ -31,4 +31,10 @@ public interface Predicate { */ boolean matches(Exchange exchange); + /** + * Initialize the predicate with the given camel context + */ + default void init(CamelContext context) { + } + } diff --git a/core/camel-base/src/main/java/org/apache/camel/processor/FilterProcessor.java b/core/camel-base/src/main/java/org/apache/camel/processor/FilterProcessor.java index 637cc65..3c472df 100644 --- a/core/camel-base/src/main/java/org/apache/camel/processor/FilterProcessor.java +++ b/core/camel-base/src/main/java/org/apache/camel/processor/FilterProcessor.java @@ -17,6 +17,7 @@ package org.apache.camel.processor; import org.apache.camel.AsyncCallback; +import org.apache.camel.CamelContext; import org.apache.camel.Exchange; import org.apache.camel.Predicate; import org.apache.camel.Processor; @@ -36,17 +37,25 @@ public class FilterProcessor extends DelegateAsyncProcessor implements Traceable private static final Logger LOG = LoggerFactory.getLogger(FilterProcessor.class); + private final CamelContext context; private String id; private String routeId; private final Predicate predicate; private transient long filtered; - public FilterProcessor(Predicate predicate, Processor processor) { + public FilterProcessor(CamelContext context, Predicate predicate, Processor processor) { super(processor); + this.context = context; this.predicate = predicate; } @Override + protected void doInit() throws Exception { + super.doInit(); + predicate.init(context); + } + + @Override public boolean process(Exchange exchange, AsyncCallback callback) { boolean matches = false; diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/builder/ExpressionClause.java b/core/camel-core-engine/src/main/java/org/apache/camel/builder/ExpressionClause.java index ff2f968..9dd2f6f 100644 --- a/core/camel-core-engine/src/main/java/org/apache/camel/builder/ExpressionClause.java +++ b/core/camel-core-engine/src/main/java/org/apache/camel/builder/ExpressionClause.java @@ -20,6 +20,7 @@ import java.util.Map; import java.util.function.BiFunction; import java.util.function.Function; +import org.apache.camel.CamelContext; import org.apache.camel.Exchange; import org.apache.camel.Expression; import org.apache.camel.ExpressionFactory; @@ -939,23 +940,32 @@ public class ExpressionClause<T> implements Expression, Predicate { return delegate.getExpressionType(); } + private volatile Expression expr; + @Override - public <T> T evaluate(Exchange exchange, Class<T> type) { - if (getExpressionValue() != null) { - return getExpressionValue().evaluate(exchange, type); - } else { - Expression exp = delegate.getExpressionType().createExpression(exchange.getContext()); - return exp.evaluate(exchange, type); + public void init(CamelContext context) { + if (expr == null) { + synchronized (this) { + if (expr == null) { + expr = getExpressionValue(); + if (expr == null) { + expr = delegate.getExpressionType().createExpression(context); + } + expr.init(context); + } + } } } @Override + public <T> T evaluate(Exchange exchange, Class<T> type) { + init(exchange.getContext()); + return expr.evaluate(exchange, type); + } + + @Override public boolean matches(Exchange exchange) { - if (getExpressionValue() != null) { - return new ExpressionToPredicateAdapter(getExpressionValue()).matches(exchange); - } else { - Expression exp = delegate.getExpressionType().createExpression(exchange.getContext()); - return new ExpressionToPredicateAdapter(exp).matches(exchange); - } + init(exchange.getContext()); + return new ExpressionToPredicateAdapter(expr).matches(exchange); } } diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/builder/SimpleBuilder.java b/core/camel-core-engine/src/main/java/org/apache/camel/builder/SimpleBuilder.java index 894e5e6..d252920 100644 --- a/core/camel-core-engine/src/main/java/org/apache/camel/builder/SimpleBuilder.java +++ b/core/camel-core-engine/src/main/java/org/apache/camel/builder/SimpleBuilder.java @@ -103,60 +103,90 @@ public class SimpleBuilder implements Predicate, Expression, ExpressionResultTyp } @Override - public boolean matches(Exchange exchange) { + public void init(CamelContext context) { if (predicate == null) { - predicate = createPredicate(exchange); + predicate = createPredicate(context); } + predicate.init(context); + } + + @Override + public boolean matches(Exchange exchange) { + init(exchange.getContext()); return predicate.matches(exchange); } @Override public <T> T evaluate(Exchange exchange, Class<T> type) { if (expression == null) { - expression = createExpression(exchange); + expression = createExpression(exchange.getContext()); } return expression.evaluate(exchange, type); } - private Predicate createPredicate(Exchange exchange) { + public Predicate createPredicate(CamelContext context) { try { + Language simple = context.resolveLanguage("simple"); // resolve property placeholders - String resolve = exchange.getContext().resolvePropertyPlaceholders(text); - // and optional it be refer to an external script on the - // file/classpath - resolve = ScriptHelper.resolveOptionalExternalScript(exchange.getContext(), exchange, resolve); - Language simple = exchange.getContext().resolveLanguage("simple"); - return simple.createPredicate(resolve); - } catch (Exception e) { - throw CamelExecutionException.wrapCamelExecutionException(exchange, e); - } - } - - private Expression createExpression(Exchange exchange) { - try { - // resolve property placeholders - String resolve = exchange.getContext().resolvePropertyPlaceholders(text); - // and optional it be refer to an external script on the - // file/classpath - resolve = ScriptHelper.resolveOptionalExternalScript(exchange.getContext(), exchange, resolve); - Language simple = exchange.getContext().resolveLanguage("simple"); - return createSimpleExpression(simple, resolve, resultType); + String resolve = context.resolvePropertyPlaceholders(text); + // and optional it be refer to an external script on the file/classpath + if (ScriptHelper.hasExternalScript(resolve)) { + return new Predicate() { + @Override + public boolean matches(Exchange exchange) { + String r = ScriptHelper.resolveOptionalExternalScript(context, exchange, resolve); + return simple.createPredicate(r).matches(exchange); + } + @Override + public String toString() { + return text; + } + }; + } else { + Predicate pred = simple.createPredicate(resolve); + pred.init(context); + return pred; + } } catch (Exception e) { - throw CamelExecutionException.wrapCamelExecutionException(exchange, e); + throw CamelExecutionException.wrapCamelExecutionException(null, e); } } - private static Expression createSimpleExpression(Language simple, String expression, Class<?> resultType) { + public Expression createExpression(CamelContext context) { if (resultType == Boolean.class || resultType == boolean.class) { // if its a boolean as result then its a predicate - Predicate predicate = simple.createPredicate(expression); + Predicate predicate = createPredicate(context); return PredicateToExpressionAdapter.toExpression(predicate); - } else { - Expression exp = simple.createExpression(expression); + } + try { + // resolve property placeholders + Language simple = context.resolveLanguage("simple"); + String resolve = context.resolvePropertyPlaceholders(text); + Expression exp; + // and optional it be refer to an external script on the file/classpath + if (ScriptHelper.hasExternalScript(resolve)) { + exp = new Expression() { + @Override + public <T> T evaluate(Exchange exchange, Class<T> type) { + String r = ScriptHelper.resolveOptionalExternalScript(context, exchange, resolve); + Expression exp = simple.createExpression(r); + return exp.evaluate(exchange, type); + } + @Override + public String toString() { + return text; + } + }; + } else { + exp = simple.createExpression(resolve); + exp.init(context); + } if (resultType != null) { exp = ExpressionBuilder.convertToExpression(exp, resultType); } return exp; + } catch (Exception e) { + throw CamelExecutionException.wrapCamelExecutionException(null, e); } } diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/model/language/ExpressionDefinition.java b/core/camel-core-engine/src/main/java/org/apache/camel/model/language/ExpressionDefinition.java index d2326b7..0ea00ef 100644 --- a/core/camel-core-engine/src/main/java/org/apache/camel/model/language/ExpressionDefinition.java +++ b/core/camel-core-engine/src/main/java/org/apache/camel/model/language/ExpressionDefinition.java @@ -225,4 +225,14 @@ public class ExpressionDefinition implements Expression, Predicate, ExpressionFa return predicate.matches(exchange); } + @Override + public void init(CamelContext context) { + if (expressionValue == null) { + expressionValue = createExpression(context); + } + if (predicate == null) { + predicate = createPredicate(context); + } + } + } diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/reifier/ExpressionReifier.java b/core/camel-core-engine/src/main/java/org/apache/camel/reifier/ExpressionReifier.java index 77667eb..672a1b6 100644 --- a/core/camel-core-engine/src/main/java/org/apache/camel/reifier/ExpressionReifier.java +++ b/core/camel-core-engine/src/main/java/org/apache/camel/reifier/ExpressionReifier.java @@ -36,7 +36,7 @@ abstract class ExpressionReifier<T extends ExpressionNode> extends ProcessorReif */ protected FilterProcessor createFilterProcessor() throws Exception { Processor childProcessor = createOutputsProcessor(); - return new FilterProcessor(createPredicate(), childProcessor); + return new FilterProcessor(camelContext, createPredicate(), childProcessor); } /** diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/reifier/FilterReifier.java b/core/camel-core-engine/src/main/java/org/apache/camel/reifier/FilterReifier.java index 4d070ef..239a82b 100644 --- a/core/camel-core-engine/src/main/java/org/apache/camel/reifier/FilterReifier.java +++ b/core/camel-core-engine/src/main/java/org/apache/camel/reifier/FilterReifier.java @@ -37,7 +37,7 @@ public class FilterReifier extends ExpressionReifier<FilterDefinition> { protected FilterProcessor createFilterProcessor() throws Exception { // filter EIP should have child outputs Processor childProcessor = this.createChildProcessor(true); - return new FilterProcessor(createPredicate(), childProcessor); + return new FilterProcessor(camelContext, createPredicate(), childProcessor); } } diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/reifier/language/SimpleExpressionReifier.java b/core/camel-core-engine/src/main/java/org/apache/camel/reifier/language/SimpleExpressionReifier.java index c5f238d..0126cee 100644 --- a/core/camel-core-engine/src/main/java/org/apache/camel/reifier/language/SimpleExpressionReifier.java +++ b/core/camel-core-engine/src/main/java/org/apache/camel/reifier/language/SimpleExpressionReifier.java @@ -20,6 +20,7 @@ import java.util.HashMap; import java.util.Map; import org.apache.camel.CamelContext; +import org.apache.camel.Exchange; import org.apache.camel.Expression; import org.apache.camel.Predicate; import org.apache.camel.builder.SimpleBuilder; @@ -34,13 +35,41 @@ public class SimpleExpressionReifier extends ExpressionReifier<SimpleExpression> @Override public Expression createExpression() { + Expression expr = createBuilder().createExpression(camelContext); + return new Expression() { + @Override + public <T> T evaluate(Exchange exchange, Class<T> type) { + return expr.evaluate(exchange, type); + } + @Override + public String toString() { + return definition.getExpression(); + } + }; + } + + @Override + public Predicate createPredicate() { + Predicate pred = createBuilder().createPredicate(camelContext); + return new Predicate() { + @Override + public boolean matches(Exchange exchange) { + return pred.matches(exchange); + } + @Override + public String toString() { + return definition.getExpression(); + } + }; + } + + protected SimpleBuilder createBuilder() { String exp = parseString(definition.getExpression()); // should be true by default boolean isTrim = parseBoolean(definition.getTrim(), true); if (exp != null && isTrim) { exp = exp.trim(); } - SimpleBuilder answer = new SimpleBuilder(exp); Map<String, Object> props = new HashMap<>(); props.put("resultType", or(definition.getResultType(), definition.getResultTypeName())); @@ -48,10 +77,4 @@ public class SimpleExpressionReifier extends ExpressionReifier<SimpleExpression> return answer; } - @Override - public Predicate createPredicate() { - // SimpleBuilder is also a Predicate - return (Predicate) createExpression(); - } - } diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/TryProcessorTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/TryProcessorTest.java index 5d81d93..e978d7b 100644 --- a/core/camel-core/src/test/java/org/apache/camel/processor/TryProcessorTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/processor/TryProcessorTest.java @@ -16,6 +16,7 @@ */ package org.apache.camel.processor; +import org.apache.camel.CamelContext; import org.apache.camel.CamelException; import org.apache.camel.ContextTestSupport; import org.apache.camel.Exchange; @@ -95,6 +96,10 @@ public class TryProcessorTest extends ContextTestSupport { public boolean matches(Exchange exchange) { throw new RuntimeCamelException(new CamelException("Force to fail")); } + + @Override + public void init(CamelContext context) { + } } private class ProcessorHandle implements Processor { diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/ValidateSimpleTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/ValidateSimpleTest.java index b463006..0498090 100644 --- a/core/camel-core/src/test/java/org/apache/camel/processor/ValidateSimpleTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/processor/ValidateSimpleTest.java @@ -58,8 +58,8 @@ public class ValidateSimpleTest extends ContextTestSupport { } catch (CamelExecutionException e) { // expected assertIsInstanceOf(PredicateValidationException.class, e.getCause()); - String s = "Validation failed for Predicate[Simple: ${body} contains 'Camel']."; - assertTrue(e.getCause().getMessage().startsWith(s)); + String s = "Validation failed for Predicate[${body} contains 'Camel']."; + assertStringContains(e.getCause().getMessage(), s); } assertMockEndpointsSatisfied(); diff --git a/core/camel-support/src/main/java/org/apache/camel/support/ExpressionSupport.java b/core/camel-support/src/main/java/org/apache/camel/support/ExpressionSupport.java index 322a742..c90810e 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/ExpressionSupport.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/ExpressionSupport.java @@ -16,6 +16,7 @@ */ package org.apache.camel.support; +import org.apache.camel.CamelContext; import org.apache.camel.Exchange; import org.apache.camel.Expression; import org.apache.camel.Predicate; @@ -27,6 +28,10 @@ import org.apache.camel.util.ObjectHelper; public abstract class ExpressionSupport implements Expression, Predicate { @Override + public void init(CamelContext context) { + } + + @Override public boolean matches(Exchange exchange) { Object value = evaluate(exchange, Object.class); return ObjectHelper.evaluateValuePredicate(value); diff --git a/core/camel-support/src/main/java/org/apache/camel/support/ExpressionToPredicateAdapter.java b/core/camel-support/src/main/java/org/apache/camel/support/ExpressionToPredicateAdapter.java index 9c8fb6d3..51b4ab5 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/ExpressionToPredicateAdapter.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/ExpressionToPredicateAdapter.java @@ -58,6 +58,11 @@ public final class ExpressionToPredicateAdapter implements Predicate, CamelConte } @Override + public void init(CamelContext context) { + expression.init(context); + } + + @Override public void setCamelContext(CamelContext camelContext) { if (expression instanceof CamelContextAware) { ((CamelContextAware) expression).setCamelContext(camelContext); diff --git a/core/camel-support/src/main/java/org/apache/camel/support/ScriptHelper.java b/core/camel-support/src/main/java/org/apache/camel/support/ScriptHelper.java index 0550330..d66d02f 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/ScriptHelper.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/ScriptHelper.java @@ -89,4 +89,14 @@ public final class ScriptHelper { return expression; } + + public static boolean hasExternalScript(String external) { + if (external.startsWith("resource:")) { + external = external.substring(9); + if (ResourceHelper.hasScheme(external) && LanguageSupport.hasSimpleFunction(external)) { + return true; + } + } + return false; + } } diff --git a/core/camel-support/src/main/java/org/apache/camel/support/builder/BinaryPredicateSupport.java b/core/camel-support/src/main/java/org/apache/camel/support/builder/BinaryPredicateSupport.java index b7c49ec..65757c5 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/builder/BinaryPredicateSupport.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/builder/BinaryPredicateSupport.java @@ -17,6 +17,7 @@ package org.apache.camel.support.builder; import org.apache.camel.BinaryPredicate; +import org.apache.camel.CamelContext; import org.apache.camel.Exchange; import org.apache.camel.Expression; import org.apache.camel.Predicate; @@ -40,6 +41,12 @@ public abstract class BinaryPredicateSupport implements BinaryPredicate { } @Override + public void init(CamelContext context) { + left.init(context); + right.init(context); + } + + @Override public String toString() { return left + " " + getOperationText() + " " + right; } diff --git a/core/camel-support/src/main/java/org/apache/camel/support/builder/ExpressionBuilder.java b/core/camel-support/src/main/java/org/apache/camel/support/builder/ExpressionBuilder.java index 71f1d68..d9c0a3a 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/builder/ExpressionBuilder.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/builder/ExpressionBuilder.java @@ -35,6 +35,7 @@ import org.apache.camel.ExtendedCamelContext; import org.apache.camel.InvalidPayloadException; import org.apache.camel.Message; import org.apache.camel.NoSuchLanguageException; +import org.apache.camel.Predicate; import org.apache.camel.RuntimeCamelException; import org.apache.camel.RuntimeExchangeException; import org.apache.camel.spi.Language; @@ -65,9 +66,22 @@ public class ExpressionBuilder { * @return an expression object which will return the header value */ public static Expression headerExpression(final String headerName) { + return headerExpression(simpleExpression(headerName)); + } + + /** + * Returns an expression for the header value with the given name + * <p/> + * Will fallback and look in properties if not found in headers. + * + * @param headerName the name of the header the expression will return + * @return an expression object which will return the header value + */ + public static Expression headerExpression(final Expression headerName) { return new ExpressionAdapter() { + @Override public Object evaluate(Exchange exchange) { - String name = simpleExpression(headerName).evaluate(exchange, String.class); + String name = headerName.evaluate(exchange, String.class); Object header = exchange.getIn().getHeader(name); if (header == null) { // fall back on a property @@ -77,6 +91,11 @@ public class ExpressionBuilder { } @Override + public void init(CamelContext context) { + headerName.init(context); + } + + @Override public String toString() { return "header(" + headerName + ")"; } @@ -93,22 +112,7 @@ public class ExpressionBuilder { * @return an expression object which will return the header value */ public static <T> Expression headerExpression(final String headerName, final Class<T> type) { - return new ExpressionAdapter() { - public Object evaluate(Exchange exchange) { - String name = simpleExpression(headerName).evaluate(exchange, String.class); - T header = exchange.getIn().getHeader(name, type); - if (header == null) { - // fall back on a property - header = exchange.getProperty(name, type); - } - return header; - } - - @Override - public String toString() { - return "headerAs(" + headerName + ", " + type + ")"; - } - }; + return headerExpression(simpleExpression(headerName), constantExpression(type)); } /** @@ -121,17 +125,30 @@ public class ExpressionBuilder { * @return an expression object which will return the header value */ public static Expression headerExpression(final String headerName, final String typeName) { + return headerExpression(simpleExpression(headerName), simpleExpression(typeName)); + } + + /** + * Returns an expression for the header value with the given name converted to the given type + * <p/> + * Will fallback and look in properties if not found in headers. + * + * @param headerName the name of the header the expression will return + * @param typeName the type to convert to as a FQN class name + * @return an expression object which will return the header value + */ + public static Expression headerExpression(final Expression headerName, final Expression typeName) { return new ExpressionAdapter() { + @Override public Object evaluate(Exchange exchange) { Class<?> type; try { - String text = simpleExpression(typeName).evaluate(exchange, String.class); + String text = typeName.evaluate(exchange, String.class); type = exchange.getContext().getClassResolver().resolveMandatoryClass(text); } catch (ClassNotFoundException e) { throw CamelExecutionException.wrapCamelExecutionException(exchange, e); } - - String text = simpleExpression(headerName).evaluate(exchange, String.class); + String text = headerName.evaluate(exchange, String.class); Object header = exchange.getIn().getHeader(text, type); if (header == null) { // fall back on a property @@ -141,6 +158,12 @@ public class ExpressionBuilder { } @Override + public void init(CamelContext context) { + headerName.init(context); + typeName.init(context); + } + + @Override public String toString() { return "headerAs(" + headerName + ", " + typeName + ")"; } @@ -276,13 +299,28 @@ public class ExpressionBuilder { * @return an expression object which will return the bean */ public static Expression refExpression(final String ref) { + return refExpression(simpleExpression(ref)); + } + + /** + * Returns an expression for lookup a bean in the {@link org.apache.camel.spi.Registry} + * + * @return an expression object which will return the bean + */ + public static Expression refExpression(final Expression ref) { return new ExpressionAdapter() { + @Override public Object evaluate(Exchange exchange) { - String text = simpleExpression(ref).evaluate(exchange, String.class); + String text = ref.evaluate(exchange, String.class); return exchange.getContext().getRegistry().lookupByName(text); } @Override + public void init(CamelContext context) { + ref.init(context); + } + + @Override public String toString() { return "ref(" + ref + ")"; } @@ -384,13 +422,29 @@ public class ExpressionBuilder { * @return an expression object which will return the property value */ public static Expression exchangePropertyExpression(final String propertyName) { + return exchangePropertyExpression(simpleExpression(propertyName)); + } + + /** + * Returns an expression for the property value of exchange with the given name + * + * @param propertyName the name of the property the expression will return + * @return an expression object which will return the property value + */ + public static Expression exchangePropertyExpression(final Expression propertyName) { return new ExpressionAdapter() { + @Override public Object evaluate(Exchange exchange) { - String text = simpleExpression(propertyName).evaluate(exchange, String.class); + String text = propertyName.evaluate(exchange, String.class); return exchange.getProperty(text); } @Override + public void init(CamelContext context) { + propertyName.init(context); + } + + @Override public String toString() { return "exchangeProperty(" + propertyName + ")"; } @@ -440,13 +494,29 @@ public class ExpressionBuilder { * @return an expression object which will return the property value */ public static Expression camelContextPropertyExpression(final String propertyName) { + return camelContextPropertyExpression(simpleExpression(propertyName)); + } + + /** + * Returns an expression for the property value of the camel context with the given name + * + * @param propertyName the name of the property the expression will return + * @return an expression object which will return the property value + */ + public static Expression camelContextPropertyExpression(final Expression propertyName) { return new ExpressionAdapter() { + @Override public Object evaluate(Exchange exchange) { - String text = simpleExpression(propertyName).evaluate(exchange, String.class); + String text = propertyName.evaluate(exchange, String.class); return exchange.getContext().getGlobalOption(text); } @Override + public void init(CamelContext context) { + propertyName.init(context); + } + + @Override public String toString() { return "camelContextProperty(" + propertyName + ")"; } @@ -472,16 +542,37 @@ public class ExpressionBuilder { */ public static Expression systemPropertyExpression(final String propertyName, final String defaultValue) { + Expression exprName = simpleExpression(propertyName); + Expression exprDeflt = simpleExpression(defaultValue); + return systemPropertyExpression(exprName, exprDeflt); + } + + /** + * Returns an expression for a system property value with the given name + * + * @param exprName the name of the system property the expression will return + * @param defaultValue default value to return if no system property exists + * @return an expression object which will return the system property value + */ + public static Expression systemPropertyExpression(final Expression exprName, + final Expression defaultValue) { return new ExpressionAdapter() { + @Override public Object evaluate(Exchange exchange) { - String text = simpleExpression(propertyName).evaluate(exchange, String.class); - String text2 = simpleExpression(defaultValue).evaluate(exchange, String.class); + String text = exprName.evaluate(exchange, String.class); + String text2 = defaultValue.evaluate(exchange, String.class); return System.getProperty(text, text2); } @Override + public void init(CamelContext context) { + exprName.init(context); + defaultValue.init(context); + } + + @Override public String toString() { - return "systemProperty(" + propertyName + ")"; + return "systemProperty(" + exprName + ")"; } }; } @@ -505,9 +596,24 @@ public class ExpressionBuilder { */ public static Expression systemEnvironmentExpression(final String propertyName, final String defaultValue) { + Expression exprName = simpleExpression(propertyName); + Expression expDeflt = simpleExpression(defaultValue); + return systemEnvironmentExpression(exprName, expDeflt); + } + + /** + * Returns an expression for a system environment value with the given name + * + * @param propertyName the name of the system environment the expression will return + * @param defaultValue default value to return if no system environment exists + * @return an expression object which will return the system environment value + */ + public static Expression systemEnvironmentExpression(final Expression propertyName, + final Expression defaultValue) { return new ExpressionAdapter() { + @Override public Object evaluate(Exchange exchange) { - String text = simpleExpression(propertyName).evaluate(exchange, String.class); + String text = propertyName.evaluate(exchange, String.class); String answer = null; if (text != null) { // lookup OS env with upper case key @@ -521,12 +627,18 @@ public class ExpressionBuilder { } if (answer == null) { - answer = simpleExpression(defaultValue).evaluate(exchange, String.class); + answer = defaultValue.evaluate(exchange, String.class); } return answer; } @Override + public void init(CamelContext context) { + propertyName.init(context); + defaultValue.init(context); + } + + @Override public String toString() { return "systemEnvironment(" + propertyName + ")"; } @@ -560,22 +672,36 @@ public class ExpressionBuilder { */ public static Expression languageExpression(final String language, final String expression) { return new ExpressionAdapter() { + private volatile Expression expr; + private volatile Predicate pred; + public Object evaluate(Exchange exchange) { - Language lan = exchange.getContext().resolveLanguage(language); - if (lan != null) { - return lan.createExpression(expression).evaluate(exchange, Object.class); - } else { - throw new NoSuchLanguageException(language); - } + init(exchange.getContext()); + return expr.evaluate(exchange, Object.class); } @Override public boolean matches(Exchange exchange) { - Language lan = exchange.getContext().resolveLanguage(language); - if (lan != null) { - return lan.createPredicate(expression).matches(exchange); - } else { - throw new NoSuchLanguageException(language); + init(exchange.getContext()); + return pred.matches(exchange); + } + + @Override + public void init(CamelContext context) { + if (expr == null) { + synchronized (this) { + if (expr == null) { + Language lan = context.resolveLanguage(language); + if (lan != null) { + pred = lan.createPredicate(expression); + pred.init(context); + expr = lan.createExpression(expression); + expr.init(context); + } else { + throw new NoSuchLanguageException(language); + } + } + } } } @@ -698,11 +824,20 @@ public class ExpressionBuilder { * to the given type */ public static Expression bodyExpression(final String name) { + return bodyExpression(simpleExpression(name)); + } + + /** + * Returns the expression for the exchanges inbound message body converted + * to the given type + */ + public static Expression bodyExpression(final Expression name) { return new ExpressionAdapter() { + @Override public Object evaluate(Exchange exchange) { - String text = simpleExpression(name).evaluate(exchange, String.class); Class<?> type; try { + String text = name.evaluate(exchange, String.class); type = exchange.getContext().getClassResolver().resolveMandatoryClass(text); } catch (ClassNotFoundException e) { throw CamelExecutionException.wrapCamelExecutionException(exchange, e); @@ -711,6 +846,11 @@ public class ExpressionBuilder { } @Override + public void init(CamelContext context) { + name.init(context); + } + + @Override public String toString() { return "bodyAs[" + name + "]"; } @@ -722,6 +862,7 @@ public class ExpressionBuilder { */ public static Expression threadNameExpression() { return new ExpressionAdapter() { + @Override public Object evaluate(Exchange exchange) { return Thread.currentThread().getName(); } @@ -738,6 +879,7 @@ public class ExpressionBuilder { */ public static Expression hostnameExpression() { return new ExpressionAdapter() { + @Override public Object evaluate(Exchange exchange) { return InetAddressUtil.getLocalHostNameSafe(); } @@ -754,6 +896,7 @@ public class ExpressionBuilder { */ public static Expression stepIdExpression() { return new ExpressionAdapter() { + @Override public Object evaluate(Exchange exchange) { return exchange.getProperty(Exchange.STEP_ID); } @@ -785,6 +928,7 @@ public class ExpressionBuilder { */ public static <T> Expression mandatoryBodyExpression(final Class<T> type, final boolean nullBodyAllowed) { return new ExpressionAdapter() { + @Override public Object evaluate(Exchange exchange) { if (nullBodyAllowed) { if (exchange.getIn().getBody() == null) { @@ -811,6 +955,7 @@ public class ExpressionBuilder { */ public static Expression bodyTypeExpression() { return new ExpressionAdapter() { + @Override public Object evaluate(Exchange exchange) { return exchange.getIn().getBody().getClass(); } @@ -827,6 +972,7 @@ public class ExpressionBuilder { */ public static Expression exchangeExpression() { return new ExpressionAdapter() { + @Override public Object evaluate(Exchange exchange) { return exchange; } @@ -843,6 +989,7 @@ public class ExpressionBuilder { */ public static Expression exchangeExpression(final Function<Exchange, Object> function) { return new ExpressionAdapter() { + @Override public Object evaluate(Exchange exchange) { return function.apply(exchange); } @@ -873,6 +1020,7 @@ public class ExpressionBuilder { */ public static Expression inMessageExpression() { return new ExpressionAdapter() { + @Override public Object evaluate(Exchange exchange) { return exchange.getIn(); } @@ -889,6 +1037,7 @@ public class ExpressionBuilder { */ public static Expression inMessageExpression(final Function<Message, Object> function) { return new ExpressionAdapter() { + @Override public Object evaluate(Exchange exchange) { return function.apply(exchange.getIn()); } @@ -905,6 +1054,7 @@ public class ExpressionBuilder { */ public static Expression convertToExpression(final Expression expression, final Class<?> type) { return new ExpressionAdapter() { + @Override public Object evaluate(Exchange exchange) { if (type != null) { return expression.evaluate(exchange, type); @@ -914,6 +1064,11 @@ public class ExpressionBuilder { } @Override + public void init(CamelContext context) { + expression.init(context); + } + + @Override public String toString() { return "" + expression; } @@ -926,6 +1081,7 @@ public class ExpressionBuilder { */ public static Expression convertToExpression(final Expression expression, final Expression type) { return new ExpressionAdapter() { + @Override public Object evaluate(Exchange exchange) { Object result = type.evaluate(exchange, Object.class); if (result != null) { @@ -936,6 +1092,12 @@ public class ExpressionBuilder { } @Override + public void init(CamelContext context) { + expression.init(context); + type.init(context); + } + + @Override public String toString() { return "" + expression; } @@ -948,15 +1110,31 @@ public class ExpressionBuilder { */ public static Expression tokenizeExpression(final Expression expression, final String token) { + return tokenizeExpression(expression, simpleExpression(token)); + } + + /** + * Returns a tokenize expression which will tokenize the string with the + * given token + */ + public static Expression tokenizeExpression(final Expression expression, + final Expression token) { return new ExpressionAdapter() { + @Override public Object evaluate(Exchange exchange) { - String text = simpleExpression(token).evaluate(exchange, String.class); + String text = token.evaluate(exchange, String.class); Object value = expression.evaluate(exchange, Object.class); Scanner scanner = ExchangeHelper.getScanner(exchange, value, text); return scanner; } @Override + public void init(CamelContext context) { + expression.init(context); + token.init(context); + } + + @Override public String toString() { return "tokenize(" + expression + ", " + token + ")"; } @@ -968,6 +1146,7 @@ public class ExpressionBuilder { */ public static Expression skipFirstExpression(final Expression expression) { return new ExpressionAdapter() { + @Override public Object evaluate(Exchange exchange) { Object value = expression.evaluate(exchange, Object.class); Iterator it = exchange.getContext().getTypeConverter().tryConvertTo(Iterator.class, exchange, value); @@ -981,6 +1160,11 @@ public class ExpressionBuilder { } @Override + public void init(CamelContext context) { + expression.init(context); + } + + @Override public String toString() { return "skipFirst(" + expression + ")"; } @@ -994,6 +1178,7 @@ public class ExpressionBuilder { public static Expression regexTokenizeExpression(final Expression expression, final String regexTokenizer) { return new ExpressionAdapter() { + @Override public Object evaluate(Exchange exchange) { Object value = expression.evaluate(exchange, Object.class); Scanner scanner = ExchangeHelper.getScanner(exchange, value, regexTokenizer); @@ -1001,6 +1186,11 @@ public class ExpressionBuilder { } @Override + public void init(CamelContext context) { + expression.init(context); + } + + @Override public String toString() { return "regexTokenize(" + expression + ", " + regexTokenizer + ")"; } @@ -1009,6 +1199,7 @@ public class ExpressionBuilder { public static Expression groupXmlIteratorExpression(final Expression expression, final String group) { return new ExpressionAdapter() { + @Override public Object evaluate(Exchange exchange) { // evaluate expression as iterator Iterator<?> it = expression.evaluate(exchange, Iterator.class); @@ -1025,6 +1216,11 @@ public class ExpressionBuilder { } @Override + public void init(CamelContext context) { + expression.init(context); + } + + @Override public String toString() { return "group " + expression + " " + group + " times"; } @@ -1052,6 +1248,11 @@ public class ExpressionBuilder { } @Override + public void init(CamelContext context) { + expression.init(context); + } + + @Override public String toString() { return "group " + expression + " " + group + " times"; } @@ -1073,6 +1274,11 @@ public class ExpressionBuilder { } @Override + public void init(CamelContext context) { + expression.init(context); + } + + @Override public String toString() { return "sort(" + expression + " by: " + comparator + ")"; } @@ -1096,6 +1302,11 @@ public class ExpressionBuilder { } @Override + public void init(CamelContext context) { + expression.init(context); + } + + @Override public String toString() { return "regexReplaceAll(" + expression + ", " + pattern.pattern() + ")"; } @@ -1111,6 +1322,7 @@ public class ExpressionBuilder { final Pattern pattern = Pattern.compile(regex); return new ExpressionAdapter() { + @Override public Object evaluate(Exchange exchange) { String text = expression.evaluate(exchange, String.class); String replacement = replacementExpression.evaluate(exchange, String.class); @@ -1121,6 +1333,12 @@ public class ExpressionBuilder { } @Override + public void init(CamelContext context) { + expression.init(context); + replacementExpression.init(context); + } + + @Override public String toString() { return "regexReplaceAll(" + expression + ", " + pattern.pattern() + ")"; } @@ -1137,6 +1355,12 @@ public class ExpressionBuilder { } @Override + public void init(CamelContext context) { + left.init(context); + right.init(context); + } + + @Override public String toString() { return "append(" + left + ", " + right + ")"; } @@ -1153,6 +1377,12 @@ public class ExpressionBuilder { } @Override + public void init(CamelContext context) { + left.init(context); + right.init(context); + } + + @Override public String toString() { return "prepend(" + left + ", " + right + ")"; } @@ -1192,6 +1422,13 @@ public class ExpressionBuilder { } @Override + public void init(CamelContext context) { + for (Expression expression : expressions) { + expression.init(context); + } + } + + @Override public String toString() { if (description != null) { return description; @@ -1252,24 +1489,24 @@ public class ExpressionBuilder { } public static Expression simpleExpression(final String expression) { - return new ExpressionAdapter() { - public Object evaluate(Exchange exchange) { - if (LanguageSupport.hasSimpleFunction(expression)) { + if (LanguageSupport.hasSimpleFunction(expression)) { + return new ExpressionAdapter() { + public Object evaluate(Exchange exchange) { // resolve language using context to have a clear separation of packages // must call evaluate to return the nested language evaluate when evaluating // stacked expressions Language language = exchange.getContext().resolveLanguage("simple"); return language.createExpression(expression).evaluate(exchange, Object.class); - } else { - return expression; } - } - @Override - public String toString() { - return "simple(" + expression + ")"; - } - }; + @Override + public String toString() { + return "simple(" + expression + ")"; + } + }; + } else { + return constantExpression(expression); + } } public static Expression beanExpression(final String expression) { @@ -1423,4 +1660,5 @@ public class ExpressionBuilder { throw new IllegalArgumentException("Failed to set property " + name + " on " + bean + ". Reason: " + e, e); } } + } diff --git a/core/camel-support/src/main/java/org/apache/camel/support/builder/ValueBuilder.java b/core/camel-support/src/main/java/org/apache/camel/support/builder/ValueBuilder.java index 833de82..915a2fa 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/builder/ValueBuilder.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/builder/ValueBuilder.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.Comparator; import java.util.List; +import org.apache.camel.CamelContext; import org.apache.camel.Exchange; import org.apache.camel.Expression; import org.apache.camel.Predicate; @@ -36,6 +37,11 @@ public class ValueBuilder implements Expression, Predicate { } @Override + public void init(CamelContext context) { + expression.init(context); + } + + @Override public <T> T evaluate(Exchange exchange, Class<T> type) { return expression.evaluate(exchange, type); }