Repository: camel Updated Branches: refs/heads/camel-2.15.x 23a642f6a -> caa1b441c refs/heads/master 37c3572df -> f01ab0513
CAMEL-8437: Bean language should support parenthesis in method parameters in the method signatures Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/45d9fdb2 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/45d9fdb2 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/45d9fdb2 Branch: refs/heads/master Commit: 45d9fdb28734aebcbbabf2c864d9381e780b29e1 Parents: 37c3572 Author: Claus Ibsen <davscl...@apache.org> Authored: Sat Mar 14 18:25:09 2015 +0100 Committer: Claus Ibsen <davscl...@apache.org> Committed: Sat Mar 14 18:57:22 2015 +0100 ---------------------------------------------------------------------- .../apache/camel/component/bean/MethodInfo.java | 2 +- .../org/apache/camel/util/ObjectHelper.java | 68 +++++++++- .../SimpleLanguageBeanBodyParenthesisTest.java | 61 +++++++++ ...nFunctionMethodValueWithParenthesisTest.java | 134 +++++++++++++++++++ .../org/apache/camel/util/ObjectHelperTest.java | 10 +- 5 files changed, 270 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/45d9fdb2/camel-core/src/main/java/org/apache/camel/component/bean/MethodInfo.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/component/bean/MethodInfo.java b/camel-core/src/main/java/org/apache/camel/component/bean/MethodInfo.java index 61f0882..d7ca0fe 100644 --- a/camel-core/src/main/java/org/apache/camel/component/bean/MethodInfo.java +++ b/camel-core/src/main/java/org/apache/camel/component/bean/MethodInfo.java @@ -443,7 +443,7 @@ public class MethodInfo { // any provided parameter values in the method name String methodName = exchange.getIn().getHeader(Exchange.BEAN_METHOD_NAME, "", String.class); // the parameter values is between the parenthesis - String methodParameters = ObjectHelper.between(methodName, "(", ")"); + String methodParameters = ObjectHelper.betweenOuterPair(methodName, '(', ')'); // use an iterator to walk the parameter values Iterator<?> it = null; if (methodParameters != null) { http://git-wip-us.apache.org/repos/asf/camel/blob/45d9fdb2/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java b/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java index 6d03134..6776b57 100644 --- a/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java +++ b/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java @@ -44,9 +44,6 @@ import java.util.NoSuchElementException; import java.util.Properties; import java.util.Scanner; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - import org.apache.camel.CamelContext; import org.apache.camel.CamelExecutionException; import org.apache.camel.Exchange; @@ -57,6 +54,8 @@ import org.apache.camel.TypeConverter; import org.apache.camel.WrappedFile; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; /** * A number of useful helper methods for working with Objects @@ -471,6 +470,69 @@ public final class ObjectHelper { } /** + * Returns the string between the most outer pair of tokens + * <p/> + * The number of token pairs must be evenly, eg there must be same number of before and after tokens, otherwise <tt>null</tt> is returned + * <p/> + * This implementation skips matching when the text is either single or double quoted. + * For example: + * <tt>${body.matches("foo('bar')")</tt> + * Will not match the parenthesis from the quoted text. + * + * @param text the text + * @param after the before token + * @param before the after token + * @return the text between the outer most tokens, or <tt>null</tt> if text does not contain the tokens + */ + public static String betweenOuterPair(String text, char before, char after) { + if (text == null) { + return null; + } + + int pos = -1; + int pos2 = -1; + int count = 0; + int count2 = 0; + + boolean singleQuoted = false; + boolean doubleQuoted = false; + for (int i = 0; i < text.length(); i++) { + char ch = text.charAt(i); + if (!doubleQuoted && ch == '\'') { + singleQuoted = !singleQuoted; + } else if (!singleQuoted && ch == '\"') { + doubleQuoted = !doubleQuoted; + } + if (singleQuoted || doubleQuoted) { + continue; + } + + if (ch == before) { + count++; + } else if (ch == after) { + count2++; + } + + if (ch == before && pos == -1) { + pos = i; + } else if (ch == after) { + pos2 = i; + } + } + + if (pos == -1 || pos2 == -1) { + return null; + } + + // must be even paris + if (count != count2) { + return null; + } + + return text.substring(pos + 1, pos2); + } + + /** * Returns true if the collection contains the specified value */ public static boolean contains(Object collectionOrArray, Object value) { http://git-wip-us.apache.org/repos/asf/camel/blob/45d9fdb2/camel-core/src/test/java/org/apache/camel/component/bean/SimpleLanguageBeanBodyParenthesisTest.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/component/bean/SimpleLanguageBeanBodyParenthesisTest.java b/camel-core/src/test/java/org/apache/camel/component/bean/SimpleLanguageBeanBodyParenthesisTest.java new file mode 100644 index 0000000..8a3a632 --- /dev/null +++ b/camel-core/src/test/java/org/apache/camel/component/bean/SimpleLanguageBeanBodyParenthesisTest.java @@ -0,0 +1,61 @@ +/** + * 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.component.bean; + +import org.apache.camel.ContextTestSupport; +import org.apache.camel.builder.RouteBuilder; + +/** + * + */ +public class SimpleLanguageBeanBodyParenthesisTest extends ContextTestSupport { + + public void testNo() throws Exception { + getMockEndpoint("mock:result").expectedMessageCount(0); + getMockEndpoint("mock:other").expectedMessageCount(1); + + template.sendBody("direct:single", "Camel"); + + assertMockEndpointsSatisfied(); + } + + public void testYes() throws Exception { + getMockEndpoint("mock:result").expectedMessageCount(1); + getMockEndpoint("mock:other").expectedMessageCount(0); + + template.sendBody("direct:single", "Hello(World) how are you"); + + assertMockEndpointsSatisfied(); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:single") + .choice() + .when().simple("${body.contains(\")\")}") + .to("mock:result") + .otherwise() + .to("mock:other"); + + } + }; + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/45d9fdb2/camel-core/src/test/java/org/apache/camel/component/bean/SimpleLanguageBeanFunctionMethodValueWithParenthesisTest.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/component/bean/SimpleLanguageBeanFunctionMethodValueWithParenthesisTest.java b/camel-core/src/test/java/org/apache/camel/component/bean/SimpleLanguageBeanFunctionMethodValueWithParenthesisTest.java new file mode 100644 index 0000000..f976990 --- /dev/null +++ b/camel-core/src/test/java/org/apache/camel/component/bean/SimpleLanguageBeanFunctionMethodValueWithParenthesisTest.java @@ -0,0 +1,134 @@ +/** + * 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.component.bean; + +import org.apache.camel.ContextTestSupport; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.impl.JndiRegistry; + +/** + * + */ +public class SimpleLanguageBeanFunctionMethodValueWithParenthesisTest extends ContextTestSupport { + + public void testSingle() throws Exception { + getMockEndpoint("mock:result").expectedMessageCount(1); + getMockEndpoint("mock:other").expectedMessageCount(0); + + template.sendBody("direct:single", "Camel"); + + assertMockEndpointsSatisfied(); + } + + public void testDouble() throws Exception { + getMockEndpoint("mock:result").expectedMessageCount(1); + getMockEndpoint("mock:other").expectedMessageCount(0); + + template.sendBody("direct:double", "Camel"); + + assertMockEndpointsSatisfied(); + } + + public void testHeader() throws Exception { + getMockEndpoint("mock:result").expectedMessageCount(1); + getMockEndpoint("mock:other").expectedMessageCount(0); + + template.sendBodyAndHeader("direct:header", "Camel", "myHeader", "e()f"); + + assertMockEndpointsSatisfied(); + } + + public void testCron() throws Exception { + getMockEndpoint("mock:result").expectedMessageCount(1); + getMockEndpoint("mock:other").expectedMessageCount(0); + + template.sendBody("direct:cron", new MyCronBody("SomeID", "(0 0 10,11,12 * * ?)")); + + assertMockEndpointsSatisfied(); + } + + @Override + protected JndiRegistry createRegistry() throws Exception { + JndiRegistry jndi = super.createRegistry(); + jndi.bind("foo", new MyBean()); + return jndi; + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:single") + .choice() + .when().simple("${bean:foo?method=bar(${body}, 'a()b')}") + .to("mock:result") + .otherwise() + .to("mock:other"); + + from("direct:double") + .choice() + .when().simple("${bean:foo?method=bar(${body}, \"a()b\")}") + .to("mock:result") + .otherwise() + .to("mock:other"); + + from("direct:header") + .choice() + .when().simple("${bean:foo?method=bar(${body}, ${header.myHeader})}") + .to("mock:result") + .otherwise() + .to("mock:other"); + + from("direct:cron") + .choice() + .when().simple("${bean:foo?method=bar(${body.id}, ${body.cron})}") + .to("mock:result") + .otherwise() + .to("mock:other"); + } + }; + } + + public static class MyBean { + + public boolean bar(String body, String extra) { + // we are testing that we can pass in () as value for a parameter + return extra.contains("(") && extra.contains(")"); + } + } + + public static class MyCronBody { + + private String id; + private String cron; + + public MyCronBody(String id, String cron) { + this.id = id; + this.cron = cron; + } + + public String getId() { + return id; + } + + public String getCron() { + return cron; + } + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/45d9fdb2/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.java b/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.java index 745485d..cf53088 100644 --- a/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.java +++ b/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.java @@ -41,7 +41,6 @@ import org.apache.camel.component.bean.MyStaticClass; import org.apache.camel.impl.DefaultCamelContext; import org.apache.camel.impl.DefaultMessage; - /** * @version */ @@ -688,6 +687,15 @@ public class ObjectHelperTest extends TestCase { assertEquals(null, ObjectHelper.between("Hello ${foo bar} how are you", "'", "'")); } + public void testBetweenOuterPair() { + assertEquals("bar(baz)123", ObjectHelper.betweenOuterPair("foo(bar(baz)123)", '(', ')')); + assertEquals(null, ObjectHelper.betweenOuterPair("foo(bar(baz)123))", '(', ')')); + assertEquals(null, ObjectHelper.betweenOuterPair("foo(bar(baz123", '(', ')')); + assertEquals(null, ObjectHelper.betweenOuterPair("foo)bar)baz123", '(', ')')); + assertEquals("bar", ObjectHelper.betweenOuterPair("foo(bar)baz123", '(', ')')); + assertEquals("'bar', 'baz()123', 123", ObjectHelper.betweenOuterPair("foo('bar', 'baz()123', 123)", '(', ')')); + } + public void testIsJavaIdentifier() { assertEquals(true, ObjectHelper.isJavaIdentifier("foo")); assertEquals(false, ObjectHelper.isJavaIdentifier("foo.bar"));