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 2022/04/06 17:35:53 UTC
[camel] branch main updated: CAMEL-17897: camel-exec - add exitValues parameter (#7376)
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 e657c37d515 CAMEL-17897: camel-exec - add exitValues parameter (#7376)
e657c37d515 is described below
commit e657c37d515d156397648edd8221b812a01236d7
Author: sbalmer <sb...@cis.ch>
AuthorDate: Wed Apr 6 19:35:46 2022 +0200
CAMEL-17897: camel-exec - add exitValues parameter (#7376)
Co-authored-by: Stephan Balmer <st...@meteotest.ch>
---
.../org/apache/camel/catalog/components/exec.json | 51 ----------------------
.../component/exec/ExecEndpointConfigurer.java | 6 +++
.../component/exec/ExecEndpointUriFactory.java | 3 +-
.../org/apache/camel/component/exec/exec.json | 2 +
.../apache/camel/component/exec/ExecBinding.java | 10 +++++
.../apache/camel/component/exec/ExecCommand.java | 19 +++++++-
.../apache/camel/component/exec/ExecEndpoint.java | 15 +++++++
.../component/exec/impl/DefaultExecBinding.java | 15 ++++++-
.../exec/impl/DefaultExecCommandExecutor.java | 6 +++
.../camel/component/exec/impl/ExecParseUtils.java | 9 ++++
.../camel/component/exec/ExecEndpointTest.java | 14 ++++++
.../camel/component/exec/ExecProducerTest.java | 28 ++++++++++++
.../endpoint/dsl/ExecEndpointBuilderFactory.java | 17 ++++++++
13 files changed, 139 insertions(+), 56 deletions(-)
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/exec.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/exec.json
deleted file mode 100644
index f53b85b1274..00000000000
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/exec.json
+++ /dev/null
@@ -1,51 +0,0 @@
-{
- "component": {
- "kind": "component",
- "name": "exec",
- "title": "Exec",
- "description": "Execute commands on the underlying operating system.",
- "deprecated": false,
- "firstVersion": "2.3.0",
- "label": "system",
- "javaType": "org.apache.camel.component.exec.ExecComponent",
- "supportLevel": "Stable",
- "groupId": "org.apache.camel",
- "artifactId": "camel-exec",
- "version": "3.17.0-SNAPSHOT",
- "scheme": "exec",
- "extendsScheme": "",
- "syntax": "exec:executable",
- "async": false,
- "api": false,
- "consumerOnly": false,
- "producerOnly": true,
- "lenientProperties": false
- },
- "componentProperties": {
- "lazyStartProducer": { "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during star [...]
- "autowiredEnabled": { "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching type, which t [...]
- },
- "headers": {
- "CamelExecCommandExecutable": { "kind": "header", "displayName": "", "group": "in", "label": "in", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The name of the system command that will be executed. Overrides executable in the URI." },
- "CamelExecCommandArgs": { "kind": "header", "displayName": "", "group": "in", "label": "in", "required": false, "javaType": "java.util.List<String> or String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Command-line argument(s) to pass to the executed process. The argument(s) is\/are used literally - no quoting is applied. Overrides any existing args in the URI." },
- "CamelExecCommandOutFile": { "kind": "header", "displayName": "", "group": "in", "label": "in", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The name of a file, created by the executable, that should be considered as its output. Overrides any existing outFile in the URI." },
- "CamelExecCommandWorkingDir": { "kind": "header", "displayName": "", "group": "in", "label": "in", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The directory in which the command should be executed. Overrides any existing workingDir in the URI." },
- "CamelExecCommandTimeout": { "kind": "header", "displayName": "", "group": "in", "label": "in", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The timeout, in milliseconds, after which the executable should be terminated. Overrides any existing timeout in the URI." },
- "CamelExecStderr": { "kind": "header", "displayName": "", "group": "out", "label": "out", "required": false, "javaType": "java.io.InputStream", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The value of this header points to the standard error stream (stderr) of the executable. If no stderr is written, the value is null." },
- "CamelExecExitValue": { "kind": "header", "displayName": "", "group": "out", "label": "out", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The value of this header is the _exit value_ of the executable. Non-zero exit values typically indicate abnormal termination. Note that the exit value is OS-dependent." },
- "CamelExecUseStderrOnEmptyStdout": { "kind": "header", "displayName": "", "group": "in", "label": "in", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Indicates that when stdout is empty, this component will populate the Camel Message Body with stderr. This behavior is disabled (false) by default." },
- "CamelExecCommandLogLevel": { "kind": "header", "displayName": "", "group": "in", "label": "in", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Logging level to be used for commands during execution. The default value is DEBUG. Possible values are TRACE, DEBUG, INFO, WARN, ERROR or OFF (Values of LoggingLevel enum)" }
- },
- "properties": {
- "executable": { "kind": "path", "displayName": "Executable", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Sets the executable to be executed. The executable must not be empty or null." },
- "args": { "kind": "parameter", "displayName": "Args", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The arguments may be one or many whitespace-separated tokens." },
- "binding": { "kind": "parameter", "displayName": "Binding", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.exec.ExecBinding", "deprecated": false, "autowired": false, "secret": false, "description": "A reference to a org.apache.commons.exec.ExecBinding in the Registry." },
- "commandExecutor": { "kind": "parameter", "displayName": "Command Executor", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.exec.ExecCommandExecutor", "deprecated": false, "autowired": false, "secret": false, "description": "A reference to a org.apache.commons.exec.ExecCommandExecutor in the Registry that customizes the command execution. The default command executor utilizes the commons-exec library, which adds a shutdo [...]
- "commandLogLevel": { "kind": "parameter", "displayName": "Command Log Level", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.LoggingLevel", "enum": [ "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "DEBUG", "description": "Logging level to be used for commands during execution. The default value is DEBUG. Possible values are TRACE, DEBUG, INFO, WARN, ERR [...]
- "lazyStartProducer": { "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during sta [...]
- "outFile": { "kind": "parameter", "displayName": "Out File", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The name of a file, created by the executable, that should be considered as its output. If no outFile is set, the standard output (stdout) of the executable will be used instead." },
- "timeout": { "kind": "parameter", "displayName": "Timeout", "group": "producer", "label": "", "required": false, "type": "duration", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "description": "The timeout, in milliseconds, after which the executable should be terminated. If execution has not completed within the timeout, the component will send a termination request." },
- "useStderrOnEmptyStdout": { "kind": "parameter", "displayName": "Use Stderr On Empty Stdout", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "A boolean indicating that when stdout is empty, this component will populate the Camel Message Body with stderr. This behavior is disabled (false) by default." },
- "workingDir": { "kind": "parameter", "displayName": "Working Dir", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The directory in which the command should be executed. If null, the working directory of the current process will be used." }
- }
-}
diff --git a/components/camel-exec/src/generated/java/org/apache/camel/component/exec/ExecEndpointConfigurer.java b/components/camel-exec/src/generated/java/org/apache/camel/component/exec/ExecEndpointConfigurer.java
index dfabbb7f22e..fee0b475eeb 100644
--- a/components/camel-exec/src/generated/java/org/apache/camel/component/exec/ExecEndpointConfigurer.java
+++ b/components/camel-exec/src/generated/java/org/apache/camel/component/exec/ExecEndpointConfigurer.java
@@ -27,6 +27,8 @@ public class ExecEndpointConfigurer extends PropertyConfigurerSupport implements
case "commandExecutor": target.setCommandExecutor(property(camelContext, org.apache.camel.component.exec.ExecCommandExecutor.class, value)); return true;
case "commandloglevel":
case "commandLogLevel": target.setCommandLogLevel(property(camelContext, org.apache.camel.LoggingLevel.class, value)); return true;
+ case "exitvalues":
+ case "exitValues": target.setExitValues(property(camelContext, java.lang.String.class, value)); return true;
case "lazystartproducer":
case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
case "outfile":
@@ -49,6 +51,8 @@ public class ExecEndpointConfigurer extends PropertyConfigurerSupport implements
case "commandExecutor": return org.apache.camel.component.exec.ExecCommandExecutor.class;
case "commandloglevel":
case "commandLogLevel": return org.apache.camel.LoggingLevel.class;
+ case "exitvalues":
+ case "exitValues": return java.lang.String.class;
case "lazystartproducer":
case "lazyStartProducer": return boolean.class;
case "outfile":
@@ -72,6 +76,8 @@ public class ExecEndpointConfigurer extends PropertyConfigurerSupport implements
case "commandExecutor": return target.getCommandExecutor();
case "commandloglevel":
case "commandLogLevel": return target.getCommandLogLevel();
+ case "exitvalues":
+ case "exitValues": return target.getExitValues();
case "lazystartproducer":
case "lazyStartProducer": return target.isLazyStartProducer();
case "outfile":
diff --git a/components/camel-exec/src/generated/java/org/apache/camel/component/exec/ExecEndpointUriFactory.java b/components/camel-exec/src/generated/java/org/apache/camel/component/exec/ExecEndpointUriFactory.java
index b1c237c8ca6..e6d32573e4c 100644
--- a/components/camel-exec/src/generated/java/org/apache/camel/component/exec/ExecEndpointUriFactory.java
+++ b/components/camel-exec/src/generated/java/org/apache/camel/component/exec/ExecEndpointUriFactory.java
@@ -21,12 +21,13 @@ public class ExecEndpointUriFactory extends org.apache.camel.support.component.E
private static final Set<String> SECRET_PROPERTY_NAMES;
private static final Set<String> MULTI_VALUE_PREFIXES;
static {
- Set<String> props = new HashSet<>(10);
+ Set<String> props = new HashSet<>(11);
props.add("args");
props.add("binding");
props.add("commandExecutor");
props.add("commandLogLevel");
props.add("executable");
+ props.add("exitValues");
props.add("lazyStartProducer");
props.add("outFile");
props.add("timeout");
diff --git a/components/camel-exec/src/generated/resources/org/apache/camel/component/exec/exec.json b/components/camel-exec/src/generated/resources/org/apache/camel/component/exec/exec.json
index f53b85b1274..2e0dcc77377 100644
--- a/components/camel-exec/src/generated/resources/org/apache/camel/component/exec/exec.json
+++ b/components/camel-exec/src/generated/resources/org/apache/camel/component/exec/exec.json
@@ -31,6 +31,7 @@
"CamelExecCommandOutFile": { "kind": "header", "displayName": "", "group": "in", "label": "in", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The name of a file, created by the executable, that should be considered as its output. Overrides any existing outFile in the URI." },
"CamelExecCommandWorkingDir": { "kind": "header", "displayName": "", "group": "in", "label": "in", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The directory in which the command should be executed. Overrides any existing workingDir in the URI." },
"CamelExecCommandTimeout": { "kind": "header", "displayName": "", "group": "in", "label": "in", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The timeout, in milliseconds, after which the executable should be terminated. Overrides any existing timeout in the URI." },
+ "CamelExecExitValues": { "kind": "header", "displayName": "", "group": "in", "label": "in", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The exit values for successful execution of the process. Overrides any existing exitValues in the URI." },
"CamelExecStderr": { "kind": "header", "displayName": "", "group": "out", "label": "out", "required": false, "javaType": "java.io.InputStream", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The value of this header points to the standard error stream (stderr) of the executable. If no stderr is written, the value is null." },
"CamelExecExitValue": { "kind": "header", "displayName": "", "group": "out", "label": "out", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The value of this header is the _exit value_ of the executable. Non-zero exit values typically indicate abnormal termination. Note that the exit value is OS-dependent." },
"CamelExecUseStderrOnEmptyStdout": { "kind": "header", "displayName": "", "group": "in", "label": "in", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Indicates that when stdout is empty, this component will populate the Camel Message Body with stderr. This behavior is disabled (false) by default." },
@@ -42,6 +43,7 @@
"binding": { "kind": "parameter", "displayName": "Binding", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.exec.ExecBinding", "deprecated": false, "autowired": false, "secret": false, "description": "A reference to a org.apache.commons.exec.ExecBinding in the Registry." },
"commandExecutor": { "kind": "parameter", "displayName": "Command Executor", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.exec.ExecCommandExecutor", "deprecated": false, "autowired": false, "secret": false, "description": "A reference to a org.apache.commons.exec.ExecCommandExecutor in the Registry that customizes the command execution. The default command executor utilizes the commons-exec library, which adds a shutdo [...]
"commandLogLevel": { "kind": "parameter", "displayName": "Command Log Level", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.LoggingLevel", "enum": [ "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "DEBUG", "description": "Logging level to be used for commands during execution. The default value is DEBUG. Possible values are TRACE, DEBUG, INFO, WARN, ERR [...]
+ "exitValues": { "kind": "parameter", "displayName": "Exit Values", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The exit values of successful executions. If the process exits with another value, an exception is raised. Comma-separated list of exit values. And empty list (the default) sets no expected exit values and disables the check." },
"lazyStartProducer": { "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during sta [...]
"outFile": { "kind": "parameter", "displayName": "Out File", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The name of a file, created by the executable, that should be considered as its output. If no outFile is set, the standard output (stdout) of the executable will be used instead." },
"timeout": { "kind": "parameter", "displayName": "Timeout", "group": "producer", "label": "", "required": false, "type": "duration", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "description": "The timeout, in milliseconds, after which the executable should be terminated. If execution has not completed within the timeout, the component will send a termination request." },
diff --git a/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecBinding.java b/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecBinding.java
index dfcee03f0bf..a481088837f 100644
--- a/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecBinding.java
+++ b/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecBinding.java
@@ -81,6 +81,16 @@ public interface ExecBinding {
javaType = "long")
String EXEC_COMMAND_TIMEOUT = "CamelExecCommandTimeout";
+ /**
+ * Which exit values of the process are considered a success. When the process exits with a value not in this list,
+ * an ExecuteException is raised. When the list is empty (the default), no exception is raised based on the exit
+ * value. Example:
+ */
+ @Metadata(label = "in", description = "The exit values for successful execution of the process.\n" +
+ "Overrides any existing `exitValues` in the URI.",
+ javaType = "String")
+ String EXEC_COMMAND_EXIT_VALUES = "CamelExecExitValues";
+
/**
* The value of this header is a {@link InputStream} with the standard error stream of the executable.
*/
diff --git a/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecCommand.java b/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecCommand.java
index 7ed02c7c6cb..a0d256d4f5f 100644
--- a/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecCommand.java
+++ b/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecCommand.java
@@ -22,6 +22,8 @@ import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
import org.apache.camel.LoggingLevel;
@@ -39,6 +41,11 @@ public class ExecCommand implements Serializable {
*/
private final String executable;
+ /**
+ * @see ExecBinding#EXEC_COMMAND_EXIT_VALUES
+ */
+ private final Set<Integer> exitValues;
+
/**
* @see ExecBinding#EXEC_COMMAND_ARGS
*/
@@ -71,10 +78,11 @@ public class ExecCommand implements Serializable {
private final boolean useStderrOnEmptyStdout;
- public ExecCommand(String executable, List<String> args, String workingDir, Long timeout,
+ public ExecCommand(String executable, List<String> args, String workingDir, Long timeout, Set<Integer> exitValues,
InputStream input, File outFile, boolean useStderrOnEmptyStdout, LoggingLevel commandLogLevel) {
notNull(executable, "command executable");
this.executable = executable;
+ this.exitValues = exitValues;
this.args = unmodifiableOrEmptyList(args);
this.workingDir = workingDir;
this.timeout = timeout;
@@ -92,6 +100,10 @@ public class ExecCommand implements Serializable {
return executable;
}
+ public Set<Integer> getExitValues() {
+ return exitValues;
+ }
+
public InputStream getInput() {
return input;
}
@@ -120,7 +132,10 @@ public class ExecCommand implements Serializable {
public String toString() {
String dirToPrint = workingDir == null ? "null" : workingDir;
String outFileToPrint = outFile == null ? "null" : outFile.getPath();
- return "ExecCommand [args=" + args + ", executable=" + executable + ", timeout=" + timeout + ", outFile="
+ String exitValuesString = exitValues.stream().map(Object::toString)
+ .collect(Collectors.joining(","));
+ return "ExecCommand [args=" + args + ", executable=" + executable + ", timeout=" + timeout
+ + ", exitValues=" + exitValuesString + ", outFile="
+ outFileToPrint + ", workingDir=" + dirToPrint + ", commandLogLevel=" + commandLogLevel
+ ", useStderrOnEmptyStdout=" + useStderrOnEmptyStdout + "]";
}
diff --git a/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecEndpoint.java b/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecEndpoint.java
index 5a54d777fec..f8219de8e9c 100644
--- a/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecEndpoint.java
+++ b/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecEndpoint.java
@@ -52,6 +52,8 @@ public class ExecEndpoint extends DefaultEndpoint {
@UriParam(javaType = "java.time.Duration")
private long timeout;
@UriParam
+ private String exitValues;
+ @UriParam
private String outFile;
@UriParam
private ExecCommandExecutor commandExecutor;
@@ -128,6 +130,19 @@ public class ExecEndpoint extends DefaultEndpoint {
this.timeout = timeout;
}
+ public String getExitValues() {
+ return exitValues;
+ }
+
+ /**
+ * The exit values of successful executions. If the process exits with another value, an exception is raised.
+ * Comma-separated list of exit values. And empty list (the default) sets no expected exit values and disables the
+ * check.
+ */
+ public void setExitValues(String exitValues) {
+ this.exitValues = exitValues;
+ }
+
public String getOutFile() {
return outFile;
}
diff --git a/components/camel-exec/src/main/java/org/apache/camel/component/exec/impl/DefaultExecBinding.java b/components/camel-exec/src/main/java/org/apache/camel/component/exec/impl/DefaultExecBinding.java
index fe93cff6fda..d15dd9eb19d 100644
--- a/components/camel-exec/src/main/java/org/apache/camel/component/exec/impl/DefaultExecBinding.java
+++ b/components/camel-exec/src/main/java/org/apache/camel/component/exec/impl/DefaultExecBinding.java
@@ -18,7 +18,9 @@ package org.apache.camel.component.exec.impl;
import java.io.File;
import java.io.InputStream;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import org.apache.camel.Exchange;
import org.apache.camel.LoggingLevel;
@@ -31,11 +33,12 @@ import org.apache.camel.util.ObjectHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import static org.apache.camel.component.exec.impl.ExecParseUtils.splitCommaSeparatedToListOfInts;
import static org.apache.camel.component.exec.impl.ExecParseUtils.splitToWhiteSpaceSeparatedTokens;
/**
* Default implementation of {@link ExecBinding}.
- *
+ *
* @see DefaultExecBinding#writeOutputInMessage(Message, ExecResult)
*/
public class DefaultExecBinding implements ExecBinding {
@@ -53,6 +56,8 @@ public class DefaultExecBinding implements ExecBinding {
String cmd = getAndRemoveHeader(exchange.getIn(), EXEC_COMMAND_EXECUTABLE, endpoint.getExecutable(), String.class);
String dir = getAndRemoveHeader(exchange.getIn(), EXEC_COMMAND_WORKING_DIR, endpoint.getWorkingDir(), String.class);
long timeout = getAndRemoveHeader(exchange.getIn(), EXEC_COMMAND_TIMEOUT, endpoint.getTimeout(), Long.class);
+ String exitValuesString
+ = getAndRemoveHeader(exchange.getIn(), EXEC_COMMAND_EXIT_VALUES, endpoint.getExitValues(), String.class);
String outFilePath = getAndRemoveHeader(exchange.getIn(), EXEC_COMMAND_OUT_FILE, endpoint.getOutFile(), String.class);
boolean useStderrOnEmptyStdout = getAndRemoveHeader(exchange.getIn(), EXEC_USE_STDERR_ON_EMPTY_STDOUT,
endpoint.isUseStderrOnEmptyStdout(), Boolean.class);
@@ -77,8 +82,14 @@ public class DefaultExecBinding implements ExecBinding {
argsList = splitToWhiteSpaceSeparatedTokens(s);
}
+ Set<Integer> exitValues = new HashSet<Integer>();
+ if (exitValuesString != null && exitValuesString.length() > 0) {
+ exitValues = new HashSet<Integer>(splitCommaSeparatedToListOfInts(exitValuesString));
+ }
+
File outFile = outFilePath == null ? null : new File(outFilePath);
- return new ExecCommand(cmd, argsList, dir, timeout, input, outFile, useStderrOnEmptyStdout, commandLogLevel);
+ return new ExecCommand(
+ cmd, argsList, dir, timeout, exitValues, input, outFile, useStderrOnEmptyStdout, commandLogLevel);
}
private boolean isListOfStrings(Object o) {
diff --git a/components/camel-exec/src/main/java/org/apache/camel/component/exec/impl/DefaultExecCommandExecutor.java b/components/camel-exec/src/main/java/org/apache/camel/component/exec/impl/DefaultExecCommandExecutor.java
index 91bd423c839..dd50d7dfc2f 100644
--- a/components/camel-exec/src/main/java/org/apache/camel/component/exec/impl/DefaultExecCommandExecutor.java
+++ b/components/camel-exec/src/main/java/org/apache/camel/component/exec/impl/DefaultExecCommandExecutor.java
@@ -23,6 +23,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Locale;
+import java.util.Set;
import org.apache.camel.component.exec.ExecCommand;
import org.apache.camel.component.exec.ExecCommandExecutor;
@@ -112,7 +113,12 @@ public class DefaultExecCommandExecutor implements ExecCommandExecutor {
protected DefaultExecutor prepareDefaultExecutor(ExecCommand execCommand) {
DefaultExecutor executor = new ExecDefaultExecutor();
+
executor.setExitValues(null);
+ Set<Integer> exitValues = execCommand.getExitValues();
+ if (exitValues.size() > 0) {
+ executor.setExitValues(exitValues.stream().mapToInt(Integer::intValue).toArray());
+ }
if (execCommand.getWorkingDir() != null) {
executor.setWorkingDirectory(new File(execCommand.getWorkingDir()).getAbsoluteFile());
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 ee5c9ae101d..cf1777ec408 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
@@ -109,4 +109,13 @@ public final class ExecParseUtils {
}
return input.matches("(^" + QUOTE_CHAR + "{2}([^" + QUOTE_CHAR + "]+)" + QUOTE_CHAR + "{2})");
}
+
+ public static List<Integer> splitCommaSeparatedToListOfInts(String commaSeparatedInts) {
+ List<Integer> exitValues = new ArrayList<>();
+ StringTokenizer st = new StringTokenizer(commaSeparatedInts, ",");
+ while (st.hasMoreTokens()) {
+ exitValues.add(Integer.valueOf(st.nextToken()));
+ }
+ return exitValues;
+ }
}
diff --git a/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecEndpointTest.java b/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecEndpointTest.java
index a34e8010d00..81c4c304a6b 100644
--- a/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecEndpointTest.java
+++ b/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecEndpointTest.java
@@ -140,6 +140,20 @@ public class ExecEndpointTest {
assertEquals(timeout, e.getTimeout());
}
+ @Test
+ @DirtiesContext
+ public void testCreateEndpointWithExitValues() throws Exception {
+ ExecEndpoint e = createExecEndpoint("exec:test?exitValues=1,2,3");
+ assertEquals("1,2,3", e.getExitValues());
+ }
+
+ @Test
+ @DirtiesContext
+ public void testCreateEndpointWithEmptyExitValues() throws Exception {
+ ExecEndpoint e = createExecEndpoint("exec:test?exitValues=");
+ assertEquals("", e.getExitValues());
+ }
+
@Test
@DirtiesContext
public void testCreateEndpointWithOutFile() throws Exception {
diff --git a/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecProducerTest.java b/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecProducerTest.java
index 23f3c81ce12..3372d5a1406 100644
--- a/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecProducerTest.java
+++ b/components/camel-exec/src/test/java/org/apache/camel/component/exec/ExecProducerTest.java
@@ -36,11 +36,13 @@ import org.springframework.test.context.ContextConfiguration;
import static org.apache.camel.component.exec.ExecBinding.EXEC_COMMAND_ARGS;
import static org.apache.camel.component.exec.ExecBinding.EXEC_COMMAND_EXECUTABLE;
+import static org.apache.camel.component.exec.ExecBinding.EXEC_COMMAND_EXIT_VALUES;
import static org.apache.camel.component.exec.ExecBinding.EXEC_COMMAND_TIMEOUT;
import static org.apache.camel.component.exec.ExecBinding.EXEC_COMMAND_WORKING_DIR;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* Test the functionality of {@link ExecProducer}
@@ -112,6 +114,32 @@ public class ExecProducerTest {
assertEquals(1000, execCommandExecutorMock.lastCommandResult.getCommand().getTimeout());
}
+ @Test
+ @DirtiesContext
+ public void testExitValues() {
+ producerTemplate.send(new Processor() {
+
+ public void process(Exchange exchange) throws Exception {
+ exchange.getIn().setBody("noinput");
+ exchange.getIn().setHeader(EXEC_COMMAND_EXIT_VALUES, "0,1");
+ }
+ });
+ assertTrue(execCommandExecutorMock.lastCommandResult.getCommand().getExitValues().contains(1));
+ }
+
+ @Test
+ @DirtiesContext
+ public void testExitValueNone() {
+ producerTemplate.send(new Processor() {
+
+ public void process(Exchange exchange) throws Exception {
+ exchange.getIn().setBody("noinput");
+ exchange.getIn().setHeader(EXEC_COMMAND_EXIT_VALUES, "");
+ }
+ });
+ assertEquals(0, execCommandExecutorMock.lastCommandResult.getCommand().getExitValues().size());
+ }
+
@Test
@DirtiesContext
public void testInputLines() throws IOException {
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/ExecEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/ExecEndpointBuilderFactory.java
index f5418e0df3d..9d91296a8a5 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/ExecEndpointBuilderFactory.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/ExecEndpointBuilderFactory.java
@@ -159,6 +159,23 @@ public interface ExecEndpointBuilderFactory {
doSetProperty("commandLogLevel", commandLogLevel);
return this;
}
+ /**
+ * The exit values of successful executions. If the process exits with
+ * another value, an exception is raised. Comma-separated list of exit
+ * values. And empty list (the default) sets no expected exit values and
+ * disables the check.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: producer
+ *
+ * @param exitValues the value to set
+ * @return the dsl builder
+ */
+ default ExecEndpointBuilder exitValues(String exitValues) {
+ doSetProperty("exitValues", exitValues);
+ return this;
+ }
/**
* Whether the producer should be started lazy (on the first message).
* By starting lazy you can use this to allow CamelContext and routes to