1 package org
.argeo
.slc
.core
.execution
.tasks
;
3 import java
.io
.BufferedReader
;
5 import java
.io
.IOException
;
6 import java
.io
.InputStream
;
7 import java
.io
.InputStreamReader
;
8 import java
.io
.OutputStream
;
9 import java
.io
.OutputStreamWriter
;
10 import java
.io
.Writer
;
11 import java
.util
.HashMap
;
12 import java
.util
.List
;
15 import org
.apache
.commons
.exec
.CommandLine
;
16 import org
.apache
.commons
.exec
.DefaultExecutor
;
17 import org
.apache
.commons
.exec
.ExecuteException
;
18 import org
.apache
.commons
.exec
.ExecuteResultHandler
;
19 import org
.apache
.commons
.exec
.ExecuteWatchdog
;
20 import org
.apache
.commons
.exec
.Executor
;
21 import org
.apache
.commons
.exec
.LogOutputStream
;
22 import org
.apache
.commons
.exec
.PumpStreamHandler
;
23 import org
.apache
.commons
.exec
.ShutdownHookProcessDestroyer
;
24 import org
.apache
.commons
.exec
.launcher
.CommandLauncher
;
25 import org
.apache
.commons
.exec
.launcher
.CommandLauncherFactory
;
26 import org
.apache
.commons
.io
.IOUtils
;
27 import org
.apache
.commons
.lang
.NotImplementedException
;
28 import org
.apache
.commons
.logging
.Log
;
29 import org
.apache
.commons
.logging
.LogFactory
;
30 import org
.argeo
.slc
.SlcException
;
32 public class SystemCall
implements Runnable
{
33 // TODO: specify environment variables
35 private final Log log
= LogFactory
.getLog(getClass());
37 private String execDir
;
39 private String cmd
= null;
40 private List
<String
> command
= null;
42 private Boolean synchronous
= true;
43 // private Boolean captureStdIn = false;
45 private String stdErrLogLevel
= "ERROR";
46 private String stdOutLogLevel
= "INFO";
48 private Map
<String
, List
<String
>> osCommands
= new HashMap
<String
, List
<String
>>();
49 private Map
<String
, String
> osCmds
= new HashMap
<String
, String
>();
50 private Map
<String
, String
> environmentVariables
= new HashMap
<String
, String
>();
52 private Long watchdogTimeout
= 24 * 60 * 60 * 1000l;
56 if (log
.isTraceEnabled()) {
57 log
.debug("os.name=" + System
.getProperty("os.name"));
58 log
.debug("os.arch=" + System
.getProperty("os.arch"));
59 log
.debug("os.version=" + System
.getProperty("os.version"));
62 // Execution directory
64 if (execDir
!= null) {
65 // Replace '/' by local file separator, for portability
66 execDir
.replace('/', File
.separatorChar
);
67 dir
= new File(execDir
).getCanonicalFile();
70 // Process process = null;
72 // Check if an OS specific command overrides
73 String osName
= System
.getProperty("os.name");
74 List
<String
> commandToUse
= null;
75 if (osCommands
.containsKey(osName
))
76 commandToUse
= osCommands
.get(osName
);
78 commandToUse
= command
;
79 String cmdToUse
= null;
80 if (osCmds
.containsKey(osName
))
81 cmdToUse
= osCmds
.get(osName
);
87 dir
= new File(getUsedDir(dir
));
91 Executor executor
= new DefaultExecutor();
92 executor
.setWatchdog(new ExecuteWatchdog(watchdogTimeout
));
93 PumpStreamHandler pumpStreamHandler
= new PumpStreamHandler(
94 new LogOutputStream() {
95 protected void processLine(String line
, int level
) {
96 log(stdOutLogLevel
, line
);
98 }, new LogOutputStream() {
99 protected void processLine(String line
, int level
) {
100 log(stdErrLogLevel
, line
);
103 executor
.setStreamHandler(pumpStreamHandler
);
104 executor
.setProcessDestroyer(new ShutdownHookProcessDestroyer());
105 executor
.setWorkingDirectory(dir
);
106 final CommandLine commandLine
;
108 // Which command definition to use
109 if (commandToUse
== null && cmdToUse
== null)
110 throw new SlcException("Please specify a command.");
111 else if (commandToUse
!= null && cmdToUse
!= null)
112 throw new SlcException(
113 "Specify the command either as a line or as a list.");
114 else if (cmdToUse
!= null) {
115 if (log
.isTraceEnabled())
116 log
.trace("Execute '" + cmdToUse
+ "' in "
119 commandLine
= CommandLine
.parse(cmdToUse
);
120 // process = Runtime.getRuntime().exec(cmdToUse, null, dir);
121 } else if (commandToUse
!= null) {
122 if (log
.isTraceEnabled())
123 log
.trace("Execute '" + commandToUse
+ "' in "
125 if (commandToUse
.size() == 0)
126 throw new SlcException("Command line is empty.");
128 commandLine
= new CommandLine(commandToUse
.get(0));
129 for (int i
= 1; i
< commandToUse
.size(); i
++)
130 commandLine
.addArgument(commandToUse
.get(i
));
131 // ProcessBuilder processBuilder = new
132 // ProcessBuilder(commandToUse);
133 // processBuilder.directory(dir);
134 // process = processBuilder.start();
136 // all cases covered previously
137 throw new NotImplementedException();
141 Map
<String
, String
> environmentVariablesToUse
= environmentVariables
142 .size() > 0 ? environmentVariables
: null;
145 ExecuteResultHandler executeResultHandler
= new ExecuteResultHandler() {
147 public void onProcessComplete(int exitValue
) {
148 log
.info("Process " + commandLine
+ " properly completed.");
151 public void onProcessFailed(ExecuteException e
) {
152 throw new SlcException("Process " + commandLine
159 int exitValue
= executor
.execute(commandLine
,
160 environmentVariablesToUse
);
161 executeResultHandler
.onProcessComplete(exitValue
);
162 } catch (ExecuteException e1
) {
163 executeResultHandler
.onProcessFailed(e1
);
166 executor
.execute(commandLine
, environmentVariablesToUse
,
167 executeResultHandler
);
169 // Manage standard streams
170 // StreamReaderThread stdOutThread = new StreamReaderThread(process
171 // .getInputStream()) {
172 // protected void callback(String line) {
173 // stdOutCallback(line);
176 // stdOutThread.start();
177 // StreamReaderThread stdErrThread = new StreamReaderThread(process
178 // .getErrorStream()) {
179 // protected void callback(String line) {
180 // stdErrCallback(line);
183 // stdErrThread.start();
185 // new StdInThread(process.getOutputStream()).start();
187 // // Wait for the end of the process
188 // if (synchronous) {
189 // Integer exitCode = process.waitFor();
190 // if (exitCode != 0) {
191 // Thread.sleep(5000);// leave the process a chance to log
192 // log.warn("Process return exit code " + exitCode);
195 // // asynchronous: return
197 } catch (Exception e
) {
198 throw new SlcException("Could not execute command " + cmd
, e
);
204 * Shortcut method returning the current exec dir if the specified one is
207 private String
getUsedDir(File dir
) {
209 return System
.getProperty("user.dir");
211 return dir
.getPath();
214 // protected void stdOutCallback(String line) {
215 // log(stdOutLogLevel, line);
218 // protected void stdErrCallback(String line) {
219 // log(stdErrLogLevel, line);
222 protected void log(String logLevel
, String line
) {
223 if ("ERROR".equals(logLevel
))
225 else if ("WARN".equals(logLevel
))
227 else if ("INFO".equals(logLevel
))
229 else if ("DEBUG".equals(logLevel
))
231 else if ("TRACE".equals(logLevel
))
234 throw new SlcException("Unknown log level " + logLevel
);
237 public void setCmd(String command
) {
241 public void setExecDir(String execdir
) {
242 this.execDir
= execdir
;
245 public void setStdErrLogLevel(String stdErrLogLevel
) {
246 this.stdErrLogLevel
= stdErrLogLevel
;
249 public void setStdOutLogLevel(String stdOutLogLevel
) {
250 this.stdOutLogLevel
= stdOutLogLevel
;
253 public void setSynchronous(Boolean synchronous
) {
254 this.synchronous
= synchronous
;
257 // public void setCaptureStdIn(Boolean captureStdIn) {
258 // this.captureStdIn = captureStdIn;
261 public void setCommand(List
<String
> command
) {
262 this.command
= command
;
265 public void setOsCommands(Map
<String
, List
<String
>> osCommands
) {
266 this.osCommands
= osCommands
;
269 public void setOsCmds(Map
<String
, String
> osCmds
) {
270 this.osCmds
= osCmds
;
273 // protected abstract class StreamReaderThread extends Thread {
274 // private final InputStream stream;
276 // public StreamReaderThread(InputStream stream) {
277 // this.stream = stream;
281 // public void run() {
282 // BufferedReader in = null;
284 // in = new BufferedReader(new InputStreamReader(stream));
285 // String line = null;
286 // while ((line = in.readLine()) != null) {
287 // stdOutCallback(line);
289 // } catch (IOException e) {
290 // if (log.isTraceEnabled()) {
291 // log.trace("Could not read stream", e);
293 // // because the other methods
294 // // to check whether the stream
295 // // is closed would probably
300 // IOUtils.closeQuietly(in);
304 // protected abstract void callback(String line);
307 // protected class StdInThread extends Thread {
308 // private final OutputStream stream;
310 // public StdInThread(OutputStream stream) {
311 // this.stream = stream;
315 // public void run() {
316 // BufferedReader in = null;
317 // Writer out = null;
319 // out = new OutputStreamWriter(stream);
320 // in = new BufferedReader(new InputStreamReader(System.in));
321 // String line = null;
322 // while ((line = in.readLine()) != null) {
327 // } catch (IOException e) {
328 // throw new SlcException("Could not write to stdin stream", e);
330 // if (synchronous) {
331 // IOUtils.closeQuietly(in);
332 // IOUtils.closeQuietly(out);