Author: davsclaus Date: Sun Jan 15 16:47:34 2012 New Revision: 1231704 URL: http://svn.apache.org/viewvc?rev=1231704&view=rev Log: CAMEL-4894: Fixed ognl parser to take into account parameter bindings encloded in parenthesis pairs, in the method names.
Added: camel/trunk/camel-core/src/test/java/org/apache/camel/util/OgnlHelperTest.java Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/util/OgnlHelper.java camel/trunk/camel-core/src/test/java/org/apache/camel/processor/RecipientListBeanTest.java Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/util/OgnlHelper.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/util/OgnlHelper.java?rev=1231704&r1=1231703&r2=1231704&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/util/OgnlHelper.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/util/OgnlHelper.java Sun Jan 15 16:47:34 2012 @@ -164,14 +164,23 @@ public final class OgnlHelper { * Regular expression with repeating groups is a pain to get right * and then nobody understands the reg exp afterwards. * So we use a bit ugly/low-level Java code to split the OGNL into methods. + * + * @param ognl the ognl expression + * @return a list of methods, will return an empty list, if ognl expression has no methods */ public static List<String> splitOgnl(String ognl) { List<String> methods = new ArrayList<String>(); + // return an empty list if ognl is empty + if (ObjectHelper.isEmpty(ognl)) { + return methods; + } + StringBuilder sb = new StringBuilder(); int j = 0; // j is used as counter per method - boolean squareBracket = false; // special to keep track if we are inside a square bracket block - (eg [foo]) + boolean squareBracket = false; // special to keep track if we are inside a square bracket block, eg: [foo] + boolean parenthesisBracket = false; // special to keep track if we are inside a parenthesis block, eg: bar(${body}, ${header.foo}) for (int i = 0; i < ognl.length(); i++) { char ch = ognl.charAt(i); // special for starting a new method @@ -179,12 +188,16 @@ public final class OgnlHelper { || (ch != '.' && ch != '?' && ch != ']')) { sb.append(ch); // special if we are doing square bracket - if (ch == '[') { + if (ch == '[' && !parenthesisBracket) { squareBracket = true; + } else if (ch == '(') { + parenthesisBracket = true; + } else if (ch == ')') { + parenthesisBracket = false; } j++; // advance } else { - if (ch == '.' && !squareBracket) { + if (ch == '.' && !squareBracket && !parenthesisBracket) { // only treat dot as a method separator if not inside a square bracket block // as dots can be used in key names when accessing maps @@ -205,7 +218,7 @@ public final class OgnlHelper { // reset j to begin a new method j = 0; - } else if (ch == ']') { + } else if (ch == ']' && !parenthesisBracket) { // append ending ] to method name sb.append(ch); String s = sb.toString(); @@ -223,11 +236,16 @@ public final class OgnlHelper { squareBracket = false; } - // and dont lose the char if its not an ] end marker (as we already added that) - if (ch != ']') { + // and don't lose the char if its not an ] end marker (as we already added that) + if (ch != ']' || parenthesisBracket) { sb.append(ch); } + // check for end of parenthesis + if (ch == ')') { + parenthesisBracket = false; + } + // only advance if already begun on the new method if (j > 0) { j++; Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/processor/RecipientListBeanTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/RecipientListBeanTest.java?rev=1231704&r1=1231703&r2=1231704&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/processor/RecipientListBeanTest.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/processor/RecipientListBeanTest.java Sun Jan 15 16:47:34 2012 @@ -46,8 +46,7 @@ public class RecipientListBeanTest exten assertMockEndpointsSatisfied(); } - // @Ignore("CAMEL-4894") @Test - public void fixmeTestRecipientListWithParams() throws Exception { + public void testRecipientListWithParams() throws Exception { MockEndpoint mock = getMockEndpoint("mock:result"); mock.expectedBodiesReceived("Hello b"); @@ -65,7 +64,7 @@ public class RecipientListBeanTest exten return new RouteBuilder() { public void configure() { from("direct:start").recipientList(bean("myBean", "foo")).to("mock:result"); - from("direct:params").recipientList(bean("myBean", "bar(header.one, header.two)"), ",").to("mock:result"); + from("direct:params").recipientList(bean("myBean", "bar(${header.one}, ${header.two})"), ",").to("mock:result"); from("direct:a").transform(constant("Hello a")); from("direct:b").transform(constant("Hello b")); @@ -80,15 +79,10 @@ public class RecipientListBeanTest exten return body.split(","); } - public String foo(int one, String two) { - String [] recipients = two.split(","); - int count = Math.min(one, recipients.length); - StringBuilder answer = new StringBuilder(); - for (int i = 0; i < count; i++) { - answer.append(i > 0 ? "," : ""); - answer.append(recipients[i]); - } - return answer.toString(); + public String bar(int one, String two) { + assertEquals(21, one); + assertEquals("direct:a,direct:b,direct:c", two); + return "direct:c,direct:b"; } } Added: camel/trunk/camel-core/src/test/java/org/apache/camel/util/OgnlHelperTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/util/OgnlHelperTest.java?rev=1231704&view=auto ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/util/OgnlHelperTest.java (added) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/util/OgnlHelperTest.java Sun Jan 15 16:47:34 2012 @@ -0,0 +1,133 @@ +/** + * 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.util; + +import java.util.List; + +import junit.framework.TestCase; + +/** + * + */ +public class OgnlHelperTest extends TestCase { + + public void testSplitOgnlSimple() throws Exception { + List<String> methods = OgnlHelper.splitOgnl(null); + assertEquals(0, methods.size()); + methods = OgnlHelper.splitOgnl(""); + assertEquals(0, methods.size()); + methods = OgnlHelper.splitOgnl(" "); + assertEquals(0, methods.size()); + + methods = OgnlHelper.splitOgnl("foo"); + assertEquals(1, methods.size()); + assertEquals("foo", methods.get(0)); + + methods = OgnlHelper.splitOgnl("foo.bar"); + assertEquals(2, methods.size()); + assertEquals("foo", methods.get(0)); + assertEquals(".bar", methods.get(1)); + + methods = OgnlHelper.splitOgnl("foo.bar.baz"); + assertEquals(3, methods.size()); + assertEquals("foo", methods.get(0)); + assertEquals(".bar", methods.get(1)); + assertEquals(".baz", methods.get(2)); + } + + public void testSplitOgnlSquare() throws Exception { + List<String> methods = OgnlHelper.splitOgnl("foo"); + assertEquals(1, methods.size()); + assertEquals("foo", methods.get(0)); + + methods = OgnlHelper.splitOgnl("foo[0].bar"); + assertEquals(2, methods.size()); + assertEquals("foo[0]", methods.get(0)); + assertEquals(".bar", methods.get(1)); + + methods = OgnlHelper.splitOgnl("foo[0]?.bar"); + assertEquals(2, methods.size()); + assertEquals("foo[0]", methods.get(0)); + assertEquals("?.bar", methods.get(1)); + + methods = OgnlHelper.splitOgnl("foo['key'].bar"); + assertEquals(2, methods.size()); + assertEquals("foo['key']", methods.get(0)); + assertEquals(".bar", methods.get(1)); + + methods = OgnlHelper.splitOgnl("foo['key']?.bar"); + assertEquals(2, methods.size()); + assertEquals("foo['key']", methods.get(0)); + assertEquals("?.bar", methods.get(1)); + + methods = OgnlHelper.splitOgnl("foo['key'].bar[0]"); + assertEquals(2, methods.size()); + assertEquals("foo['key']", methods.get(0)); + assertEquals(".bar[0]", methods.get(1)); + + methods = OgnlHelper.splitOgnl("foo['key']?.bar[0]"); + assertEquals(2, methods.size()); + assertEquals("foo['key']", methods.get(0)); + assertEquals("?.bar[0]", methods.get(1)); + } + + public void testSplitOgnlParenthesis() throws Exception { + List<String> methods = OgnlHelper.splitOgnl("foo()"); + assertEquals(1, methods.size()); + assertEquals("foo()", methods.get(0)); + + methods = OgnlHelper.splitOgnl("foo(${body})"); + assertEquals(1, methods.size()); + assertEquals("foo(${body})", methods.get(0)); + + methods = OgnlHelper.splitOgnl("foo(${body}, ${header.foo})"); + assertEquals(1, methods.size()); + assertEquals("foo(${body}, ${header.foo})", methods.get(0)); + + methods = OgnlHelper.splitOgnl("foo(${body}, ${header.foo}).bar"); + assertEquals(2, methods.size()); + assertEquals("foo(${body}, ${header.foo})", methods.get(0)); + assertEquals(".bar", methods.get(1)); + + methods = OgnlHelper.splitOgnl("foo(${body}, ${header.foo}).bar(true, ${header.bar})"); + assertEquals(2, methods.size()); + assertEquals("foo(${body}, ${header.foo})", methods.get(0)); + assertEquals(".bar(true, ${header.bar})", methods.get(1)); + + methods = OgnlHelper.splitOgnl("foo(${body}, ${header.foo}).bar(true, ${header.bar}).baz['key']"); + assertEquals(3, methods.size()); + assertEquals("foo(${body}, ${header.foo})", methods.get(0)); + assertEquals(".bar(true, ${header.bar})", methods.get(1)); + assertEquals(".baz['key']", methods.get(2)); + } + + public void testSplitOgnlParenthesisAndBracket() throws Exception { + List<String> methods = OgnlHelper.splitOgnl("foo(${body['key']})"); + assertEquals(1, methods.size()); + assertEquals("foo(${body['key']})", methods.get(0)); + + methods = OgnlHelper.splitOgnl("foo(${body}, ${header.foo?['key']})"); + assertEquals(1, methods.size()); + assertEquals("foo(${body}, ${header.foo?['key']})", methods.get(0)); + + methods = OgnlHelper.splitOgnl("foo(${body}, ${header.foo}).bar(true, ${header.bar[0]?.code})"); + assertEquals(2, methods.size()); + assertEquals("foo(${body}, ${header.foo})", methods.get(0)); + assertEquals(".bar(true, ${header.bar[0]?.code})", methods.get(1)); + } + +}