This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new dea953fa88ea CAMEL-25121: camel-util - splitSafeQuote keeps the spaces 
inside every quoted value (#27027)
dea953fa88ea is described below

commit dea953fa88ea67da99e5bd85eb1e04de4cc102fb
Author: Claus Ibsen <[email protected]>
AuthorDate: Mon Sep 28 23:21:38 2026 +0200

    CAMEL-25121: camel-util - splitSafeQuote keeps the spaces inside every 
quoted value (#27027)
    
    Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 .../component/exec/impl/ExecParseUtilsTest.java    |  3 +-
 .../org/apache/camel/util/StringQuoteHelper.java   | 49 +++++++++++++++++-----
 .../apache/camel/util/StringQuoteHelperTest.java   | 22 ++++++++++
 .../ROOT/pages/camel-4x-upgrade-guide-4_23.adoc    |  8 ++++
 4 files changed, 71 insertions(+), 11 deletions(-)

diff --git 
a/components/camel-exec/src/test/java/org/apache/camel/component/exec/impl/ExecParseUtilsTest.java
 
b/components/camel-exec/src/test/java/org/apache/camel/component/exec/impl/ExecParseUtilsTest.java
index 9070f41ba7f5..e31674a4c8c8 100644
--- 
a/components/camel-exec/src/test/java/org/apache/camel/component/exec/impl/ExecParseUtilsTest.java
+++ 
b/components/camel-exec/src/test/java/org/apache/camel/component/exec/impl/ExecParseUtilsTest.java
@@ -52,7 +52,8 @@ public class ExecParseUtilsTest {
     @Test
     public void testWhitespaceSeparatedArgsWithSpaces() {
         List<String> args = splitToWhiteSpaceSeparatedTokens("\"arg 0 \"   
arg1 \"arg 2\"");
-        assertEquals("arg 0", args.get(0));
+        // the text inside quotes is kept as-is, like a shell does
+        assertEquals("arg 0 ", args.get(0));
         assertEquals("arg1", args.get(1));
         assertEquals("arg 2", args.get(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 b80cbbb2aa34..1932d857d994 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
@@ -188,6 +188,9 @@ public final class StringQuoteHelper {
         boolean doubleQuoted = false;
         boolean separating = false;
         int depth = 0;
+        // where quoted text starts and ends in the current value, so trim 
does not remove spaces inside quotes
+        int quoteStart = -1;
+        int quoteEnd = -1;
 
         for (int i = 0; i < input.length(); i++) {
             char ch = input.charAt(i);
@@ -222,6 +225,11 @@ public final class StringQuoteHelper {
                 if (keepQuotes) {
                     sb.append(ch);
                 }
+                if (singleQuoted && quoteStart == -1) {
+                    quoteStart = sb.length();
+                } else if (!singleQuoted) {
+                    quoteEnd = sb.length();
+                }
                 continue;
             } else if (!singleQuoted && ch == '"') {
                 if (doubleQuoted && prev == ch && sb.isEmpty()) {
@@ -250,18 +258,21 @@ public final class StringQuoteHelper {
                 if (keepQuotes) {
                     sb.append(ch);
                 }
+                if (doubleQuoted && quoteStart == -1) {
+                    quoteStart = sb.length();
+                } else if (!doubleQuoted) {
+                    quoteEnd = sb.length();
+                }
                 continue;
             } else if (!isQuoting && ch == separator && depth == 0) {
                 separating = true;
                 // add as answer if we are not in a quote
                 if (!sb.isEmpty()) {
-                    String text = sb.toString();
-                    if (trim) {
-                        text = text.trim();
-                    }
-                    answer.add(text);
+                    answer.add(trim ? trimOutsideQuotes(sb, quoteStart, 
quoteEnd) : sb.toString());
                     sb.setLength(0);
                 }
+                quoteStart = -1;
+                quoteEnd = -1;
                 // we should avoid adding the separator
                 continue;
             }
@@ -285,14 +296,32 @@ public final class StringQuoteHelper {
 
         // any leftover
         if (!sb.isEmpty()) {
-            String text = sb.toString();
-            if (trim) {
-                text = text.trim();
-            }
-            answer.add(text);
+            answer.add(trim ? trimOutsideQuotes(sb, quoteStart, quoteEnd) : 
sb.toString());
         }
 
         return answer.toArray(new String[0]);
     }
 
+    /**
+     * Trims the value, but not the text between quoteStart and quoteEnd (the 
quoted text, when there is any).
+     */
+    private static String trimOutsideQuotes(StringBuilder sb, int quoteStart, 
int quoteEnd) {
+        if (quoteStart == -1) {
+            return sb.toString().trim();
+        }
+        if (quoteEnd < quoteStart) {
+            // an unterminated quote runs to the end of the value
+            quoteEnd = sb.length();
+        }
+        int begin = 0;
+        while (begin < quoteStart && sb.charAt(begin) <= ' ') {
+            begin++;
+        }
+        int end = sb.length();
+        while (end > quoteEnd && sb.charAt(end - 1) <= ' ') {
+            end--;
+        }
+        return sb.substring(begin, end);
+    }
+
 }
diff --git 
a/core/camel-util/src/test/java/org/apache/camel/util/StringQuoteHelperTest.java
 
b/core/camel-util/src/test/java/org/apache/camel/util/StringQuoteHelperTest.java
index 7304a8caf7dd..df9a52cb3647 100644
--- 
a/core/camel-util/src/test/java/org/apache/camel/util/StringQuoteHelperTest.java
+++ 
b/core/camel-util/src/test/java/org/apache/camel/util/StringQuoteHelperTest.java
@@ -41,6 +41,28 @@ public class StringQuoteHelperTest {
         Assertions.assertEquals("String.class Mars", arr[1]);
     }
 
+    @Test
+    public void testSplitTrimKeepsSpacesInsideQuotes() {
+        // the quoted text is kept as-is whether or not it is the last value
+        String[] arr = StringQuoteHelper.splitSafeQuote("' a ', ' b '", ',', 
true, false);
+        Assertions.assertArrayEquals(new String[] { " a ", " b " }, arr);
+
+        arr = StringQuoteHelper.splitSafeQuote("  \" a \"  ,  \" b \"  ,c", 
',', true, false);
+        Assertions.assertArrayEquals(new String[] { " a ", " b ", "c" }, arr);
+
+        // spaces outside the quotes are still trimmed
+        arr = StringQuoteHelper.splitSafeQuote("x, ' b '  ", ',', true, false);
+        Assertions.assertArrayEquals(new String[] { "x", " b " }, arr);
+
+        // with keepQuotes the quotes protect the text
+        arr = StringQuoteHelper.splitSafeQuote(" ' a ' , ' b ' ", ',', true, 
true);
+        Assertions.assertArrayEquals(new String[] { "' a '", "' b '" }, arr);
+
+        // space as separator (such as exec arguments)
+        arr = StringQuoteHelper.splitSafeQuote("'  a  ' b", ' ', true, false);
+        Assertions.assertArrayEquals(new String[] { "  a  ", "b" }, arr);
+    }
+
     @Test
     public void testSplitBeanParametersNoTrim() throws Exception {
         String[] arr = StringQuoteHelper.splitSafeQuote("String.class ${body}, 
String.class Mars", ',', false, true);
diff --git 
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
index c217e79bcae6..74aacb03f550 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
@@ -793,6 +793,14 @@ replacing them. The keywords apply to the whole JVM and 
cannot be removed.
 ends at the last `@` before the path, so a password may contain `@`, and an 
`@` in the query of a URI is no longer
 taken as the end of a password.
 
+=== camel-core - spaces inside quoted values are kept
+
+When a list of values is split, such as the parameters of a simple function 
(for example `${list(' a ','b')}`),
+the arguments of `camel-exec`, or the values of a `camel-sql` IN query, the 
spaces inside a quoted value were removed
+unless it was the last value. They are now kept for every value, so `${list(' 
a ',' b ')}` gives `" a "` and `" b "`,
+and the exec argument `"arg 0 "` is passed as `arg 0 ` (with the trailing 
space). Spaces outside the quotes are still
+removed.
+
 === camel-core - property placeholders in pollEnrich
 
 Camel 4.22 stopped resolving property placeholders (`{{...}}`) on the 
_per-message evaluated_

Reply via email to