This is an automated email from the ASF dual-hosted git repository.
mattcasters pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git
The following commit(s) were added to refs/heads/main by this push:
new 70805d51dc Fix ExecProcess command-line tokenization after (#7581)
70805d51dc is described below
commit 70805d51dc94e5d19534170d0db66270ccec5a27
Author: Lance <[email protected]>
AuthorDate: Mon Jul 20 23:25:50 2026 +0800
Fix ExecProcess command-line tokenization after (#7581)
Signed-off-by: lance <[email protected]>
---
.../pipeline/transforms/execprocess/ExecProcess.java | 19 ++++++++++++++++++-
.../transforms/execprocess/ExecProcessTest.java | 10 ++++++++++
2 files changed, 28 insertions(+), 1 deletion(-)
diff --git
a/plugins/transforms/execprocess/src/main/java/org/apache/hop/pipeline/transforms/execprocess/ExecProcess.java
b/plugins/transforms/execprocess/src/main/java/org/apache/hop/pipeline/transforms/execprocess/ExecProcess.java
index d275946a6a..922ba64803 100644
---
a/plugins/transforms/execprocess/src/main/java/org/apache/hop/pipeline/transforms/execprocess/ExecProcess.java
+++
b/plugins/transforms/execprocess/src/main/java/org/apache/hop/pipeline/transforms/execprocess/ExecProcess.java
@@ -23,6 +23,7 @@ import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.StringTokenizer;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.CountDownLatch;
@@ -218,7 +219,10 @@ public class ExecProcess extends
BaseTransform<ExecProcessMeta, ExecProcessData>
// execute process
try {
if (!meta.isArgumentsInFields()) {
- p = data.runtime.exec(new String[] {process[0]});
+ // Match historical Runtime.exec(String) whitespace tokenization
without using the
+ // deprecated String overload. A single-element String[] would treat
the whole command
+ // line (e.g. "/bin/echo hop-single") as the executable name.
+ p = data.runtime.exec(tokenizeCommandLine(process[0]));
} else {
p = data.runtime.exec(process);
}
@@ -323,6 +327,19 @@ public class ExecProcess extends
BaseTransform<ExecProcessMeta, ExecProcessData>
}
}
+ /**
+ * Tokenize a command line the same way Runtime.exec(String) historically
did (whitespace via
+ * {@link StringTokenizer}).
+ */
+ static String[] tokenizeCommandLine(String command) {
+ StringTokenizer st = new StringTokenizer(command);
+ String[] cmdArray = new String[st.countTokens()];
+ for (int i = 0; st.hasMoreTokens(); i++) {
+ cmdArray[i] = st.nextToken();
+ }
+ return cmdArray;
+ }
+
private String getOutputString(BufferedReader b) throws IOException {
StringBuilder returnValueBuffer = new StringBuilder();
String line;
diff --git
a/plugins/transforms/execprocess/src/test/java/org/apache/hop/pipeline/transforms/execprocess/ExecProcessTest.java
b/plugins/transforms/execprocess/src/test/java/org/apache/hop/pipeline/transforms/execprocess/ExecProcessTest.java
index 7cfd1e7c7a..832673cbcd 100644
---
a/plugins/transforms/execprocess/src/test/java/org/apache/hop/pipeline/transforms/execprocess/ExecProcessTest.java
+++
b/plugins/transforms/execprocess/src/test/java/org/apache/hop/pipeline/transforms/execprocess/ExecProcessTest.java
@@ -25,6 +25,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
+import java.util.Arrays;
+import java.util.List;
import org.apache.hop.core.HopEnvironment;
import org.apache.hop.core.IRowSet;
import org.apache.hop.core.QueueRowSet;
@@ -215,6 +217,14 @@ class ExecProcessTest {
assertEquals(1, transform.getErrors());
}
+ @Test
+ void tokenizeCommandLine_splitsOnWhitespaceLikeRuntimeExecString() {
+ assertEquals(
+ Arrays.asList("/bin/echo", "hop-single"),
+ Arrays.asList(ExecProcess.tokenizeCommandLine("/bin/echo
hop-single")));
+ assertEquals(List.of("cmd"),
Arrays.asList(ExecProcess.tokenizeCommandLine("cmd")));
+ }
+
@Test
void processRow_emptyProcessField_throws() throws HopException {
HopEnvironment.init();