You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2015/03/14 20:32:07 UTC

[1/4] camel git commit: CAMEL-8437: Bean language should support parenthesis in method parameters in the method signatures

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 <da...@apache.org>
Authored: Sat Mar 14 18:25:09 2015 +0100
Committer: Claus Ibsen <da...@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"));


[2/4] camel git commit: Fixed CS

Posted by da...@apache.org.
Fixed CS


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/f01ab051
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/f01ab051
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/f01ab051

Branch: refs/heads/master
Commit: f01ab0513b68ad4f9d57930ff1c4b14eabe7d6df
Parents: 45d9fdb
Author: Claus Ibsen <da...@apache.org>
Authored: Sat Mar 14 20:33:21 2015 +0100
Committer: Claus Ibsen <da...@apache.org>
Committed: Sat Mar 14 20:33:21 2015 +0100

----------------------------------------------------------------------
 .../src/main/java/org/apache/camel/util/ObjectHelper.java       | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/f01ab051/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 6776b57..4c1d22b 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,6 +44,9 @@ 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;
@@ -54,8 +57,6 @@ 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


[4/4] camel git commit: Fixed CS

Posted by da...@apache.org.
Fixed CS


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/caa1b441
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/caa1b441
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/caa1b441

Branch: refs/heads/camel-2.15.x
Commit: caa1b441c82007183dd62c299b0844fd4661fe52
Parents: 68a1306
Author: Claus Ibsen <da...@apache.org>
Authored: Sat Mar 14 20:33:21 2015 +0100
Committer: Claus Ibsen <da...@apache.org>
Committed: Sat Mar 14 20:33:41 2015 +0100

----------------------------------------------------------------------
 .../src/main/java/org/apache/camel/util/ObjectHelper.java       | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/caa1b441/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 6776b57..4c1d22b 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,6 +44,9 @@ 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;
@@ -54,8 +57,6 @@ 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


[3/4] camel git commit: CAMEL-8437: Bean language should support parenthesis in method parameters in the method signatures

Posted by da...@apache.org.
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/68a13068
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/68a13068
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/68a13068

Branch: refs/heads/camel-2.15.x
Commit: 68a130686a69468b2d86487ab343b10c64f5ebfd
Parents: 23a642f
Author: Claus Ibsen <da...@apache.org>
Authored: Sat Mar 14 18:25:09 2015 +0100
Committer: Claus Ibsen <da...@apache.org>
Committed: Sat Mar 14 20:33:36 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/68a13068/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/68a13068/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/68a13068/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/68a13068/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/68a13068/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"));