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 2023/03/01 11:52:55 UTC

[camel] branch camel-3.18.x updated: CAMEL-19098: camel-bean - Performance overhead when invoking methods with string parameters.

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 <cl...@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);
         }