46
46
* so that the batch job does not hang forever if the external process hangs.
47
47
*
48
48
* Tasklet periodically checks for termination status (i.e.
49
- * {@link #setCommand(String)} finished its execution or
49
+ * {@link #setCommand(String... )} finished its execution or
50
50
* {@link #setTimeout(long)} expired or job was interrupted). The check interval
51
51
* is given by {@link #setTerminationCheckInterval(long)}.
52
52
*
@@ -64,7 +64,7 @@ public class SystemCommandTasklet extends StepExecutionListenerSupport implement
64
64
65
65
protected static final Log logger = LogFactory .getLog (SystemCommandTasklet .class );
66
66
67
- private String command ;
67
+ private String [] cmdArray ;
68
68
69
69
private String [] environmentParams = null ;
70
70
@@ -100,8 +100,15 @@ public RepeatStatus execute(StepContribution contribution, ChunkContext chunkCon
100
100
101
101
@ Override
102
102
public Integer call () throws Exception {
103
- Process process = Runtime .getRuntime ().exec (command , environmentParams , workingDirectory );
104
- return process .waitFor ();
103
+ if (cmdArray .length == 1 ) {
104
+ String command = cmdArray [0 ];
105
+ Process process = Runtime .getRuntime ().exec (command , environmentParams , workingDirectory );
106
+ return process .waitFor ();
107
+ } else {
108
+ Process process = Runtime .getRuntime ().exec (cmdArray , environmentParams , workingDirectory );
109
+ return process .waitFor ();
110
+ }
111
+
105
112
}
106
113
107
114
});
@@ -132,6 +139,7 @@ else if (System.currentTimeMillis() - t0 > timeout) {
132
139
}
133
140
else if (execution .isTerminateOnly ()) {
134
141
systemCommandTask .cancel (interruptOnCancel );
142
+ String command = String .join (" " , cmdArray );
135
143
throw new JobInterruptedException ("Job interrupted while executing system command '" + command + "'" );
136
144
}
137
145
else if (stopped ) {
@@ -143,10 +151,17 @@ else if (stopped) {
143
151
}
144
152
145
153
/**
146
- * @param command command to be executed in a separate system process
154
+ * @param command command to be executed in a separate system process. Either a single command can be supplied
155
+ * to be tokenized with a space delimiter, or the command and its arguments are supplied as multiple
156
+ * strings that are not tokenized.
157
+ * <p>
158
+ * <p>Possible calls to setCommand:
159
+ *
160
+ * <pre> {@code setCommand("myCommand myArg1 myArg2");}</pre>
161
+ * <pre> {@code setCommand("myCommand", "myArg1", "myArg2 'args for myArg2'");}</pre>
147
162
*/
148
- public void setCommand (String command ) {
149
- this .command = command ;
163
+ public void setCommand (String ... command ) {
164
+ this .cmdArray = command ;
150
165
}
151
166
152
167
/**
@@ -174,7 +189,10 @@ public void setWorkingDirectory(String dir) {
174
189
175
190
@ Override
176
191
public void afterPropertiesSet () throws Exception {
177
- Assert .hasLength (command , "'command' property value is required" );
192
+ Assert .notNull (cmdArray , "'cmdArray' property value is required with at least 1 element" );
193
+ Assert .notEmpty (cmdArray , "'cmdArray' property value is required with at least 1 element" );
194
+ Assert .noNullElements (cmdArray , "'cmdArray' property value is required with at least 1 element" );
195
+ Assert .hasLength (cmdArray [0 ], "'cmdArray' property value is required with at least 1 element" );
178
196
Assert .notNull (systemProcessExitCodeMapper , "SystemProcessExitCodeMapper must be set" );
179
197
Assert .isTrue (timeout > 0 , "timeout value must be greater than zero" );
180
198
Assert .notNull (taskExecutor , "taskExecutor is required" );
0 commit comments