CAMEL-8952: Expression or predicates - allow to refer to external script on file/classpath
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/146a7de3 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/146a7de3 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/146a7de3 Branch: refs/heads/master Commit: 146a7de3c20cd795b003f1b44c74f51dd549c6e9 Parents: 2e1cb1b Author: Claus Ibsen <davscl...@apache.org> Authored: Sat Jul 11 11:19:24 2015 +0200 Committer: Claus Ibsen <davscl...@apache.org> Committed: Sat Jul 11 11:58:35 2015 +0200 ---------------------------------------------------------------------- .../org/apache/camel/builder/SimpleBuilder.java | 9 +++- .../model/language/ExpressionDefinition.java | 7 +++ .../model/language/XMLTokenizerExpression.java | 5 -- .../org/apache/camel/util/ResourceHelper.java | 42 +++++++++++++++ .../camel/processor/ScriptExternalTest.java | 54 ++++++++++++++++++++ .../processor/TransformExternalScriptTest.java | 34 ++++++++++++ .../apache/camel/processor/mysimplescript.txt | 1 + .../processor/SpringScriptExternalTest.java | 50 ++++++++++++++++++ .../camel/spring/processor/mysimplescript.txt | 1 + .../camel/spring/processor/script-external.xml | 37 ++++++++++++++ 10 files changed, 233 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/146a7de3/camel-core/src/main/java/org/apache/camel/builder/SimpleBuilder.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/builder/SimpleBuilder.java b/camel-core/src/main/java/org/apache/camel/builder/SimpleBuilder.java index c39ebe6..bdf2232 100644 --- a/camel-core/src/main/java/org/apache/camel/builder/SimpleBuilder.java +++ b/camel-core/src/main/java/org/apache/camel/builder/SimpleBuilder.java @@ -21,6 +21,7 @@ import org.apache.camel.Expression; import org.apache.camel.Predicate; import org.apache.camel.language.simple.SimpleLanguage; import org.apache.camel.util.ObjectHelper; +import org.apache.camel.util.ResourceHelper; /** * Creates an {@link org.apache.camel.language.Simple} language builder. @@ -85,9 +86,11 @@ public class SimpleBuilder implements Predicate, Expression { private Predicate createPredicate(Exchange exchange) { SimpleLanguage simple = (SimpleLanguage) exchange.getContext().resolveLanguage("simple"); - // resolve property placeholders try { + // resolve property placeholders String resolve = exchange.getContext().resolvePropertyPlaceholders(text); + // and optional it be refer to an external script on the file/classpath + resolve = ResourceHelper.resolveOptionalExternalScript(exchange.getContext(), resolve); return simple.createPredicate(resolve); } catch (Exception e) { throw ObjectHelper.wrapCamelExecutionException(exchange, e); @@ -96,9 +99,11 @@ public class SimpleBuilder implements Predicate, Expression { private Expression createExpression(Exchange exchange) { SimpleLanguage simple = (SimpleLanguage) exchange.getContext().resolveLanguage("simple"); - // resolve property placeholders try { + // resolve property placeholders String resolve = exchange.getContext().resolvePropertyPlaceholders(text); + // and optional it be refer to an external script on the file/classpath + resolve = ResourceHelper.resolveOptionalExternalScript(exchange.getContext(), resolve); return simple.createExpression(resolve, resultType); } catch (Exception e) { throw ObjectHelper.wrapCamelExecutionException(exchange, e); http://git-wip-us.apache.org/repos/asf/camel/blob/146a7de3/camel-core/src/main/java/org/apache/camel/model/language/ExpressionDefinition.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/language/ExpressionDefinition.java b/camel-core/src/main/java/org/apache/camel/model/language/ExpressionDefinition.java index c7917a5..c3b87ee 100644 --- a/camel-core/src/main/java/org/apache/camel/model/language/ExpressionDefinition.java +++ b/camel-core/src/main/java/org/apache/camel/model/language/ExpressionDefinition.java @@ -45,6 +45,7 @@ import org.apache.camel.util.CollectionStringBuffer; import org.apache.camel.util.ExpressionToPredicateAdapter; import org.apache.camel.util.IntrospectionSupport; import org.apache.camel.util.ObjectHelper; +import org.apache.camel.util.ResourceHelper; /** * A useful base class for an expression @@ -166,6 +167,9 @@ public class ExpressionDefinition implements Expression, Predicate, OtherAttribu if (exp != null && isTrim) { exp = exp.trim(); } + // resolve the expression as it may be an external script from the classpath/file etc + exp = ResourceHelper.resolveOptionalExternalScript(camelContext, exp); + predicate = language.createPredicate(exp); configurePredicate(camelContext, predicate); } @@ -191,6 +195,9 @@ public class ExpressionDefinition implements Expression, Predicate, OtherAttribu if (exp != null && isTrim) { exp = exp.trim(); } + // resolve the expression as it may be an external script from the classpath/file etc + exp = ResourceHelper.resolveOptionalExternalScript(camelContext, exp); + setExpressionValue(language.createExpression(exp)); configureExpression(camelContext, getExpressionValue()); } http://git-wip-us.apache.org/repos/asf/camel/blob/146a7de3/camel-core/src/main/java/org/apache/camel/model/language/XMLTokenizerExpression.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/language/XMLTokenizerExpression.java b/camel-core/src/main/java/org/apache/camel/model/language/XMLTokenizerExpression.java index 8d9c266..cf53bb3 100644 --- a/camel-core/src/main/java/org/apache/camel/model/language/XMLTokenizerExpression.java +++ b/camel-core/src/main/java/org/apache/camel/model/language/XMLTokenizerExpression.java @@ -122,9 +122,4 @@ public class XMLTokenizerExpression extends NamespaceAwareExpression { super.configurePredicate(camelContext, predicate); } - @Override - public Expression createExpression(CamelContext camelContext) { - Expression answer = super.createExpression(camelContext); - return answer; - } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/146a7de3/camel-core/src/main/java/org/apache/camel/util/ResourceHelper.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/util/ResourceHelper.java b/camel-core/src/main/java/org/apache/camel/util/ResourceHelper.java index 15ceefc..0cb50ef 100644 --- a/camel-core/src/main/java/org/apache/camel/util/ResourceHelper.java +++ b/camel-core/src/main/java/org/apache/camel/util/ResourceHelper.java @@ -30,6 +30,8 @@ import java.net.URLConnection; import java.net.URLDecoder; import java.util.Map; +import org.apache.camel.CamelContext; +import org.apache.camel.RuntimeCamelException; import org.apache.camel.spi.ClassResolver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,6 +48,46 @@ public final class ResourceHelper { } /** + * Resolves the expression/predicate whether it refers to an external script on the file/classpath etc. + * This requires to use the prefix <tt>resource:</tt> such as <tt>resource:classpath:com/foo/myscript.groovy</tt>, + * <tt>resource:file:/var/myscript.groovy</tt>. + * <p/> + * If not then the returned value is returned as-is. + */ + public static String resolveOptionalExternalScript(CamelContext camelContext, String expression) { + if (expression == null) { + return null; + } + String external = expression; + + // must be one line only + int newLines = StringHelper.countChar(expression, '\n'); + if (newLines > 1) { + // okay then just use as-is + return expression; + } + + // must start with resource: to denote an external resource + if (external.startsWith("resource:")) { + external = external.substring(9); + + if (hasScheme(external)) { + InputStream is = null; + try { + is = resolveMandatoryResourceAsInputStream(camelContext.getClassResolver(), external); + expression = camelContext.getTypeConverter().convertTo(String.class, is); + } catch (IOException e) { + throw new RuntimeCamelException("Cannot load resource " + external, e); + } finally { + IOHelper.close(is); + } + } + } + + return expression; + } + + /** * Determines whether the URI has a scheme (e.g. file:, classpath: or http:) * * @param uri the URI http://git-wip-us.apache.org/repos/asf/camel/blob/146a7de3/camel-core/src/test/java/org/apache/camel/processor/ScriptExternalTest.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/processor/ScriptExternalTest.java b/camel-core/src/test/java/org/apache/camel/processor/ScriptExternalTest.java new file mode 100644 index 0000000..db42dbd --- /dev/null +++ b/camel-core/src/test/java/org/apache/camel/processor/ScriptExternalTest.java @@ -0,0 +1,54 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.processor; + +import org.apache.camel.ContextTestSupport; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; + +/** + * @version + */ +public class ScriptExternalTest extends ContextTestSupport { + protected MockEndpoint resultEndpoint; + + public void testScript() throws Exception { + resultEndpoint.expectedBodiesReceived("Hello"); + + sendBody("direct:start", "Hello"); + + resultEndpoint.assertIsSatisfied(); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + + resultEndpoint = getMockEndpoint("mock:result"); + } + + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + public void configure() { + from("direct:start") + // should not affect the body + .script(simple("resource:classpath:org/apache/camel/processor/mysimplescript.txt")) + .to("mock:result"); + } + }; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/146a7de3/camel-core/src/test/java/org/apache/camel/processor/TransformExternalScriptTest.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/processor/TransformExternalScriptTest.java b/camel-core/src/test/java/org/apache/camel/processor/TransformExternalScriptTest.java new file mode 100644 index 0000000..7dcb5c4 --- /dev/null +++ b/camel-core/src/test/java/org/apache/camel/processor/TransformExternalScriptTest.java @@ -0,0 +1,34 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.processor; + +import org.apache.camel.builder.RouteBuilder; + +public class TransformExternalScriptTest extends TransformViaDSLTest { + + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + public void configure() { + // START SNIPPET: example + from("direct:start") + .transform().simple("resource:classpath:org/apache/camel/processor/mysimplescript.txt") + .to("mock:result"); + // END SNIPPET: example + } + }; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/146a7de3/camel-core/src/test/resources/org/apache/camel/processor/mysimplescript.txt ---------------------------------------------------------------------- diff --git a/camel-core/src/test/resources/org/apache/camel/processor/mysimplescript.txt b/camel-core/src/test/resources/org/apache/camel/processor/mysimplescript.txt new file mode 100644 index 0000000..97c955d --- /dev/null +++ b/camel-core/src/test/resources/org/apache/camel/processor/mysimplescript.txt @@ -0,0 +1 @@ +${body} World! \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/146a7de3/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringScriptExternalTest.java ---------------------------------------------------------------------- diff --git a/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringScriptExternalTest.java b/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringScriptExternalTest.java new file mode 100644 index 0000000..2e91f37 --- /dev/null +++ b/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringScriptExternalTest.java @@ -0,0 +1,50 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.spring.processor; + +import org.apache.camel.CamelContext; +import org.apache.camel.ContextTestSupport; +import org.apache.camel.component.mock.MockEndpoint; + +import static org.apache.camel.spring.processor.SpringTestHelper.createSpringCamelContext; + +/** + * @version + */ +public class SpringScriptExternalTest extends ContextTestSupport { + + protected MockEndpoint resultEndpoint; + + public void testScriptExternal() throws Exception { + resultEndpoint.expectedBodiesReceived("Hello"); + + sendBody("direct:start", "Hello"); + + resultEndpoint.assertIsSatisfied(); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + + resultEndpoint = getMockEndpoint("mock:result"); + } + + protected CamelContext createCamelContext() throws Exception { + return createSpringCamelContext(this, "org/apache/camel/spring/processor/script-external.xml"); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/146a7de3/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/mysimplescript.txt ---------------------------------------------------------------------- diff --git a/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/mysimplescript.txt b/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/mysimplescript.txt new file mode 100644 index 0000000..cddb5a8 --- /dev/null +++ b/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/mysimplescript.txt @@ -0,0 +1 @@ +Hello ${body} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/146a7de3/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/script-external.xml ---------------------------------------------------------------------- diff --git a/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/script-external.xml b/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/script-external.xml new file mode 100644 index 0000000..2a96db7 --- /dev/null +++ b/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/script-external.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd + "> + + <!-- START SNIPPET: example --> + <camelContext xmlns="http://camel.apache.org/schema/spring"> + <route> + <from uri="direct:start"/> + <script> + <simple>resource:classpath:org/apache/camel/spring/processor/mysimplescript.txt</simple> + </script> + <to uri="mock:result"/> + </route> + </camelContext> + <!-- END SNIPPET: example --> + +</beans>