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_