This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch camel-3.18.x in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/camel-3.18.x by this push: new 9691878dbac CAMEL-19098: camel-bean - Performance overhead when invoking methods with string parameters. 9691878dbac is described below commit 9691878dbac33269c7da643096d43f302a619ef4 Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Wed Mar 1 12:50:02 2023 +0100 CAMEL-19098: camel-bean - Performance overhead when invoking methods with string parameters. --- .../apache/camel/component/bean/MethodInfo.java | 4 +- .../BeanParameterMatchPerformanceIssueTest.java | 69 ++++++++++++++++++++++ .../apache/camel/util/StingQuoteHelperTest.java | 23 ++++++++ .../org/apache/camel/util/StringQuoteHelper.java | 69 +++++++++++++++++++--- 4 files changed, 154 insertions(+), 11 deletions(-) diff --git a/components/camel-bean/src/main/java/org/apache/camel/component/bean/MethodInfo.java b/components/camel-bean/src/main/java/org/apache/camel/component/bean/MethodInfo.java index a3fb6c5f17d..7493e9a6a5d 100644 --- a/components/camel-bean/src/main/java/org/apache/camel/component/bean/MethodInfo.java +++ b/components/camel-bean/src/main/java/org/apache/camel/component/bean/MethodInfo.java @@ -576,8 +576,8 @@ public class MethodInfo { Iterator<?> it = null; if (methodParameters != null) { // split the parameters safely separated by comma, but beware that we can have - // quoted parameters which contains comma as well, so do a safe quote split - String[] parameters = StringQuoteHelper.splitSafeQuote(methodParameters, ',', true); + // quoted parameters which contains comma as well, so do a safe quote split (keep quotes) + String[] parameters = StringQuoteHelper.splitSafeQuote(methodParameters, ',', true, true); it = ObjectHelper.createIterator(parameters, ",", true); } diff --git a/core/camel-core/src/test/java/org/apache/camel/component/bean/issues/BeanParameterMatchPerformanceIssueTest.java b/core/camel-core/src/test/java/org/apache/camel/component/bean/issues/BeanParameterMatchPerformanceIssueTest.java new file mode 100644 index 00000000000..330aa16295c --- /dev/null +++ b/core/camel-core/src/test/java/org/apache/camel/component/bean/issues/BeanParameterMatchPerformanceIssueTest.java @@ -0,0 +1,69 @@ +/* + * 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.issues; + +import org.apache.camel.ContextTestSupport; +import org.apache.camel.builder.RouteBuilder; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class BeanParameterMatchPerformanceIssueTest extends ContextTestSupport { + + @Test + public void testPerformance() throws Exception { + String s = template.requestBody("direct:a", "a", String.class); + Assertions.assertEquals("Hello slow", s); + + s = template.requestBody("direct:b", "b", String.class); + Assertions.assertEquals("Hello fast", s); + + s = template.requestBody("direct:c", "c", String.class); + Assertions.assertEquals("Hello fast", s); + + s = template.requestBody("direct:d", "d", String.class); + Assertions.assertEquals("Hello 'fast'", s); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + context.getRegistry().bind("myBean", new MyBean()); + + from("direct:a") + .to("bean:myBean?method=myMethod(slow)"); + + from("direct:b") + .to("bean:myBean?method=myMethod('fast')"); + + from("direct:c") + .to("bean:myBean?method=myMethod(\"fast\")"); + + from("direct:d") + .to("bean:myBean?method=myMethod(\"'fast'\")"); + } + }; + } + + private static class MyBean { + + public String myMethod(String str) { + return "Hello " + str; + } + } +} diff --git a/core/camel-core/src/test/java/org/apache/camel/util/StingQuoteHelperTest.java b/core/camel-core/src/test/java/org/apache/camel/util/StingQuoteHelperTest.java index 0dd066b7f03..94fcde44563 100644 --- a/core/camel-core/src/test/java/org/apache/camel/util/StingQuoteHelperTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/util/StingQuoteHelperTest.java @@ -190,4 +190,27 @@ public class StingQuoteHelperTest { assertEquals("dependency=mvn:com.foo:myapp:2.1", out[2]); } + @Test + public void testKeepQuotes() throws Exception { + String[] out = StringQuoteHelper.splitSafeQuote("'body'", ',', false, true); + assertEquals(1, out.length); + assertEquals("'body'", out[0]); + + out = StringQuoteHelper.splitSafeQuote("'body', 123", ',', false, true); + assertEquals(2, out.length); + assertEquals("'body'", out[0]); + assertEquals("123", out[1]); + + out = StringQuoteHelper.splitSafeQuote("'body', \"world\"", ',', false, true); + assertEquals(2, out.length); + assertEquals("'body'", out[0]); + assertEquals("\"world\"", out[1]); + + out = StringQuoteHelper.splitSafeQuote("'body', \"world\", 123", ',', false, true); + assertEquals(3, out.length); + assertEquals("'body'", out[0]); + assertEquals("\"world\"", out[1]); + assertEquals("123", out[2]); + } + } diff --git a/core/camel-util/src/main/java/org/apache/camel/util/StringQuoteHelper.java b/core/camel-util/src/main/java/org/apache/camel/util/StringQuoteHelper.java index 414cb95c691..49f6b9c948a 100644 --- a/core/camel-util/src/main/java/org/apache/camel/util/StringQuoteHelper.java +++ b/core/camel-util/src/main/java/org/apache/camel/util/StringQuoteHelper.java @@ -66,26 +66,51 @@ public final class StringQuoteHelper { * @return the input split, or <tt>null</tt> if the input is null. */ public static String[] splitSafeQuote(String input, char separator) { - return splitSafeQuote(input, separator, true); + return splitSafeQuote(input, separator, true, false); } /** * Splits the input safely honoring if values is enclosed in quotes. * <p/> * Though this method does not support double quoting values. A quoted value must start with the same start and - * ending quote, which is either a single quote or double quote value. \ - * + * ending quote, which is either a single quote or double quote value. + * * @param input the input * @param separator the separator char to split the input, for example a comma. * @param trim whether to trim each split value * @return the input split, or <tt>null</tt> if the input is null. */ public static String[] splitSafeQuote(String input, char separator, boolean trim) { + return splitSafeQuote(input, separator, trim, false); + } + + /** + * Splits the input safely honoring if values is enclosed in quotes. + * <p/> + * Though this method does not support double quoting values. A quoted value must start with the same start and + * ending quote, which is either a single quote or double quote value. + * + * @param input the input + * @param separator the separator char to split the input, for example a comma. + * @param trim whether to trim each split value + * @param keepQuotes whether to keep quotes + * @return the input split, or <tt>null</tt> if the input is null. + */ + public static String[] splitSafeQuote(String input, char separator, boolean trim, boolean keepQuotes) { if (input == null) { return null; } if (input.indexOf(separator) == -1) { + if (input.length() > 1) { + char ch = input.charAt(0); + char ch2 = input.charAt(input.length() - 1); + boolean singleQuoted = ch == '\'' && ch2 == '\''; + boolean doubleQuoted = ch == '"' && ch2 == '"'; + if (!keepQuotes && (singleQuoted || doubleQuoted)) { + input = input.substring(1, input.length() - 1); + } + } // no separator in data, so return single string with input as is return new String[] { trim ? input.trim() : input }; } @@ -101,38 +126,63 @@ public final class StringQuoteHelper { char ch = input.charAt(i); char prev = i > 0 ? input.charAt(i - 1) : 0; boolean isQuoting = singleQuoted || doubleQuoted; + boolean last = i == input.length() - 1; if (!doubleQuoted && ch == '\'') { if (singleQuoted && prev == ch && sb.length() == 0) { // its an empty quote so add empty text - answer.add(""); + if (keepQuotes) { + answer.add("''"); + } else { + answer.add(""); + } } // special logic needed if this quote is the end - if (i == input.length() - 1) { + if (last) { if (singleQuoted && sb.length() > 0) { String text = sb.toString(); // do not trim a quoted string - answer.add(text); + if (keepQuotes) { + answer.add(text + "'"); // append ending quote + } else { + answer.add(text); + } sb.setLength(0); } + break; // break out as we are finished } singleQuoted = !singleQuoted; + if (keepQuotes) { + sb.append(ch); + } continue; } else if (!singleQuoted && ch == '"') { if (doubleQuoted && prev == ch && sb.length() == 0) { // its an empty quote so add empty text - answer.add(""); + if (keepQuotes) { + answer.add("\""); // append ending quote + } else { + answer.add(""); + } } // special logic needed if this quote is the end - if (i == input.length() - 1) { + if (last) { if (doubleQuoted && sb.length() > 0) { String text = sb.toString(); // do not trim a quoted string - answer.add(text); + if (keepQuotes) { + answer.add(text + "\""); + } else { + answer.add(text); + } sb.setLength(0); } + break; // break out as we are finished } doubleQuoted = !doubleQuoted; + if (keepQuotes) { + sb.append(ch); + } continue; } else if (!isQuoting && separator != ' ' && ch == ' ') { if (skipLeadingWhitespace) { @@ -152,6 +202,7 @@ public final class StringQuoteHelper { continue; } + // append char sb.append(ch); }