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 2025/08/20 19:21:55 UTC
(camel) branch camel-4.14.x updated: CAMEL-22362: camel-exec - Use quote safe arg parser (#18956)
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch camel-4.14.x
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/camel-4.14.x by this push:
new 36296295736 CAMEL-22362: camel-exec - Use quote safe arg parser (#18956)
36296295736 is described below
commit 36296295736c58a8e0a7116cef5b79c9be5c0cd3
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Aug 20 21:20:34 2025 +0200
CAMEL-22362: camel-exec - Use quote safe arg parser (#18956)
---
.../camel/component/exec/impl/ExecParseUtils.java | 83 +++-------------------
.../component/exec/impl/ExecParseUtilsTest.java | 70 +++---------------
2 files changed, 17 insertions(+), 136 deletions(-)
diff --git a/components/camel-exec/src/main/java/org/apache/camel/component/exec/impl/ExecParseUtils.java b/components/camel-exec/src/main/java/org/apache/camel/component/exec/impl/ExecParseUtils.java
index 65bb68b8dc6..7c1f09f2aef 100644
--- a/components/camel-exec/src/main/java/org/apache/camel/component/exec/impl/ExecParseUtils.java
+++ b/components/camel-exec/src/main/java/org/apache/camel/component/exec/impl/ExecParseUtils.java
@@ -17,97 +17,30 @@
package org.apache.camel.component.exec.impl;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;
+import org.apache.camel.util.StringQuoteHelper;
+
/**
* Utility class for parsing, used by the Camel Exec component.<br>
* Note: the class should be dropped, when the commons-exec library implements similar functionality.
*/
public final class ExecParseUtils {
- public static final String WHITESPACE = " ";
-
- public static final String QUOTE_CHAR = "\"";
-
private ExecParseUtils() {
}
- /**
- * Splits the input line string by {@link #WHITESPACE}. Supports quoting the white-spaces with a
- * {@link #QUOTE_CHAR}. A quote itself can also be enclosed within #{@link #QUOTE_CHAR}#{@link #QUOTE_CHAR}. More
- * than two double-quotes in a sequence is not allowed. Nested quotes are not allowed.<br>
- * E.g. The string <code>"arg 1" arg2<code> will return the tokens <code>arg 1</code>, <code>arg2</code><br>
- * The string <code>""arg 1"" "arg2" arg 3<code> will return the tokens <code>"arg 1"</code> ,
- * <code>arg2</code>,<code>arg</code> and <code>3</code> <br>
- *
- * @param input the input to split.
- * @return a not-null list of tokens
- */
public static List<String> splitToWhiteSpaceSeparatedTokens(String input) {
+ List<String> answer = new ArrayList<>();
if (input == null) {
- return new ArrayList<>();
- }
- StringTokenizer tokenizer = new StringTokenizer(input.trim(), QUOTE_CHAR + WHITESPACE, true);
- List<String> tokens = new ArrayList<>();
-
- StringBuilder quotedText = new StringBuilder();
-
- while (tokenizer.hasMoreTokens()) {
- String token = tokenizer.nextToken();
- if (QUOTE_CHAR.equals(token)) {
- // if we have a quote, add the next tokens to the quoted text
- // until the quoting has finished
- quotedText.append(QUOTE_CHAR);
- String buffer = quotedText.toString();
- if (isSingleQuoted(buffer) || isDoubleQuoted(buffer)) {
- tokens.add(buffer.substring(1, buffer.length() - 1));
- quotedText = new StringBuilder();
- }
- } else if (WHITESPACE.equals(token)) {
- // a white space, if in quote, add the white space, otherwise
- // skip it
- if (quotedText.length() > 0) {
- quotedText.append(WHITESPACE);
- }
- } else {
- if (quotedText.length() > 0) {
- quotedText.append(token);
- } else {
- tokens.add(token);
- }
- }
+ return answer;
}
- if (quotedText.length() > 0) {
- throw new IllegalArgumentException("Invalid quoting found in args " + quotedText);
- }
- return tokens;
- }
-
- /**
- * Tests if the input is enclosed within {@link #QUOTE_CHAR} characters
- *
- * @param input a not null String
- * @return true if the regular expression is matched
- */
- protected static boolean isSingleQuoted(String input) {
- if (input == null || input.isBlank()) {
- return false;
- }
- return input.matches("(^" + QUOTE_CHAR + "{1}([^" + QUOTE_CHAR + "]+)" + QUOTE_CHAR + "{1})");
- }
- /**
- * Tests if the input is enclosed within a double-{@link #QUOTE_CHAR} string
- *
- * @param input a not null String
- * @return true if the regular expression is matched
- */
- protected static boolean isDoubleQuoted(String input) {
- if (input == null || input.isBlank()) {
- return false;
- }
- return input.matches("(^" + QUOTE_CHAR + "{2}([^" + QUOTE_CHAR + "]+)" + QUOTE_CHAR + "{2})");
+ String[] arr = StringQuoteHelper.splitSafeQuote(input, ' ', true, false);
+ Collections.addAll(answer, arr);
+ return answer;
}
public static List<Integer> splitCommaSeparatedToListOfInts(String commaSeparatedInts) {
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 9e78e9018d9..9070f41ba7f 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
@@ -20,64 +20,14 @@ import java.util.List;
import org.junit.jupiter.api.Test;
-import static org.apache.camel.component.exec.impl.ExecParseUtils.isDoubleQuoted;
-import static org.apache.camel.component.exec.impl.ExecParseUtils.isSingleQuoted;
import static org.apache.camel.component.exec.impl.ExecParseUtils.splitToWhiteSpaceSeparatedTokens;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* Tests for {@link ExecParseUtils}
*/
public class ExecParseUtilsTest {
- @Test
- public void testSingleQuoted() {
- assertTrue(isSingleQuoted("\"c:\\program files\\test\""));
- }
-
- @Test
- public void testSingleQuoted2() {
- assertTrue(isSingleQuoted("\"with space\""));
- }
-
- @Test
- public void testSingleQuotedNegative() {
- assertFalse(isSingleQuoted("arg 0"));
- }
-
- @Test
- public void testSingleQuotedNegative2() {
- assertFalse(isSingleQuoted("\" \" space not allowed between quotes \""));
- }
-
- @Test
- public void testSingleQuotedNegative3() {
- assertFalse(isSingleQuoted("\"\"double quoted is not single quoted\"\""));
- }
-
- @Test
- public void testEmptySingleQuotedNegative() {
- assertFalse(isSingleQuoted("\"\""));
- }
-
- @Test
- public void testEmptySingleQuotedNegative2() {
- assertFalse(isSingleQuoted("\""));
- }
-
- @Test
- public void testDoubleQuoted() {
- assertTrue(isDoubleQuoted("\"\"c:\\program files\\test\\\"\""));
- }
-
- @Test
- public void testEmptyDoubleQuotedNegative() {
- assertFalse(isDoubleQuoted("\"\"\"\""));
- }
-
@Test
public void testWhiteSpaceSeparatedArgs() {
List<String> args = splitToWhiteSpaceSeparatedTokens("arg0 arg1 arg2");
@@ -102,7 +52,7 @@ public class ExecParseUtilsTest {
@Test
public void testWhitespaceSeparatedArgsWithSpaces() {
List<String> args = splitToWhiteSpaceSeparatedTokens("\"arg 0 \" arg1 \"arg 2\"");
- assertEquals("arg 0 ", args.get(0));
+ assertEquals("arg 0", args.get(0));
assertEquals("arg1", args.get(1));
assertEquals("arg 2", args.get(2));
}
@@ -115,27 +65,25 @@ public class ExecParseUtilsTest {
@Test
public void testDoubleQuoteAndSpace() {
- List<String> args = splitToWhiteSpaceSeparatedTokens("\"\"arg0\"\" arg1");
+ List<String> args = splitToWhiteSpaceSeparatedTokens("'\"arg0\"' arg1");
assertEquals("\"arg0\"", args.get(0));
assertEquals("arg1", args.get(1));
}
@Test
public void testTwoDoubleQuotes() {
- List<String> args = splitToWhiteSpaceSeparatedTokens("\"\"arg0\"\" \"\"arg1\"\"");
+ List<String> args = splitToWhiteSpaceSeparatedTokens("'\"arg0\"' '\"arg1\"'");
assertEquals("\"arg0\"", args.get(0));
assertEquals("\"arg1\"", args.get(1));
}
@Test
- public void testWhiteSpaceSeparatedArgsNotClosed() {
- assertThrows(IllegalArgumentException.class,
- () -> splitToWhiteSpaceSeparatedTokens("arg 0 \" arg1 \"arg 2\""));
+ public void testRuby() {
+ List<String> args = splitToWhiteSpaceSeparatedTokens("ruby -e 'puts \"Hello, world!\"'");
+ assertEquals(3, args.size());
+ assertEquals("ruby", args.get(0));
+ assertEquals("-e", args.get(1));
+ assertEquals("puts \"Hello, world!\"", args.get(2));
}
- @Test
- public void testInvalidQuotes() {
- assertThrows(IllegalArgumentException.class,
- () -> splitToWhiteSpaceSeparatedTokens("\"\"arg 0 \" arg1 \"arg 2\""));
- }
}