1 package org
.argeo
.slc
.core
.execution
.tasks
;
4 import java
.io
.FileWriter
;
5 import java
.io
.IOException
;
7 import java
.util
.HashMap
;
11 import org
.apache
.commons
.exec
.CommandLine
;
12 import org
.apache
.commons
.exec
.DefaultExecutor
;
13 import org
.apache
.commons
.exec
.ExecuteException
;
14 import org
.apache
.commons
.exec
.ExecuteResultHandler
;
15 import org
.apache
.commons
.exec
.ExecuteWatchdog
;
16 import org
.apache
.commons
.exec
.Executor
;
17 import org
.apache
.commons
.exec
.LogOutputStream
;
18 import org
.apache
.commons
.exec
.PumpStreamHandler
;
19 import org
.apache
.commons
.exec
.ShutdownHookProcessDestroyer
;
20 import org
.apache
.commons
.io
.IOUtils
;
21 import org
.apache
.commons
.logging
.Log
;
22 import org
.apache
.commons
.logging
.LogFactory
;
23 import org
.argeo
.slc
.SlcException
;
24 import org
.argeo
.slc
.core
.structure
.tree
.TreeSPath
;
25 import org
.argeo
.slc
.core
.structure
.tree
.TreeSRelatedHelper
;
26 import org
.argeo
.slc
.core
.test
.SimpleResultPart
;
27 import org
.argeo
.slc
.structure
.StructureAware
;
28 import org
.argeo
.slc
.test
.TestResult
;
29 import org
.argeo
.slc
.test
.TestStatus
;
30 import org
.springframework
.core
.io
.Resource
;
32 /** Execute and OS system call. */
33 public class SystemCall
extends TreeSRelatedHelper
implements Runnable
,
34 StructureAware
<TreeSPath
> {
35 private final Log log
= LogFactory
.getLog(getClass());
37 private String execDir
;
39 private String cmd
= null;
40 private List
<Object
> command
= null;
42 private Boolean synchronous
= true;
44 private String stdErrLogLevel
= "ERROR";
45 private String stdOutLogLevel
= "INFO";
47 private Resource stdOutFile
= null;
48 private Resource stdErrFile
= null;
50 private Map
<String
, List
<Object
>> osCommands
= new HashMap
<String
, List
<Object
>>();
51 private Map
<String
, String
> osCmds
= new HashMap
<String
, String
>();
52 private Map
<String
, String
> environmentVariables
= new HashMap
<String
, String
>();
54 private Long watchdogTimeout
= 24 * 60 * 60 * 1000l;
56 private TestResult testResult
;
62 public SystemCall(List
<Object
> command
) {
64 this.command
= command
;
69 final Writer stdOutWriter
;
70 final Writer stdErrWriter
;
71 if (stdOutFile
!= null) {
72 stdOutWriter
= createWriter(stdOutFile
);
75 if (stdErrFile
!= null) {
76 stdErrWriter
= createWriter(stdErrFile
);
78 if (stdOutFile
!= null) {
79 stdErrWriter
= createWriter(stdOutFile
);
85 if (log
.isTraceEnabled()) {
86 log
.debug("os.name=" + System
.getProperty("os.name"));
87 log
.debug("os.arch=" + System
.getProperty("os.arch"));
88 log
.debug("os.version=" + System
.getProperty("os.version"));
91 // Execution directory
93 if (execDir
!= null) {
94 // Replace '/' by local file separator, for portability
95 execDir
.replace('/', File
.separatorChar
);
96 dir
= new File(execDir
).getCanonicalFile();
99 // Check if an OS specific command overrides
100 String osName
= System
.getProperty("os.name");
101 List
<Object
> commandToUse
= null;
102 if (osCommands
.containsKey(osName
))
103 commandToUse
= osCommands
.get(osName
);
105 commandToUse
= command
;
106 String cmdToUse
= null;
107 if (osCmds
.containsKey(osName
))
108 cmdToUse
= osCmds
.get(osName
);
114 dir
= new File(getUsedDir(dir
));
118 Executor executor
= new DefaultExecutor();
119 executor
.setWatchdog(new ExecuteWatchdog(watchdogTimeout
));
121 PumpStreamHandler pumpStreamHandler
= new PumpStreamHandler(
122 new LogOutputStream() {
123 protected void processLine(String line
, int level
) {
124 log(stdOutLogLevel
, line
);
125 if (stdOutWriter
!= null)
126 appendLineToFile(stdOutWriter
, line
);
128 }, new LogOutputStream() {
129 protected void processLine(String line
, int level
) {
130 log(stdErrLogLevel
, line
);
131 if (stdErrWriter
!= null)
132 appendLineToFile(stdErrWriter
, line
);
135 executor
.setStreamHandler(pumpStreamHandler
);
136 executor
.setProcessDestroyer(new ShutdownHookProcessDestroyer());
137 executor
.setWorkingDirectory(dir
);
138 final CommandLine commandLine
;
140 // Which command definition to use
141 if (commandToUse
== null && cmdToUse
== null)
142 throw new SlcException("Please specify a command.");
143 else if (commandToUse
!= null && cmdToUse
!= null)
144 throw new SlcException(
145 "Specify the command either as a line or as a list.");
146 else if (cmdToUse
!= null) {
147 if (log
.isTraceEnabled())
148 log
.trace("Execute '" + cmdToUse
+ "' in "
151 commandLine
= CommandLine
.parse(cmdToUse
);
152 } else if (commandToUse
!= null) {
153 if (log
.isTraceEnabled())
154 log
.trace("Execute '" + commandToUse
+ "' in "
156 if (commandToUse
.size() == 0)
157 throw new SlcException("Command line is empty.");
159 commandLine
= new CommandLine(commandToUse
.get(0).toString());
160 for (int i
= 1; i
< commandToUse
.size(); i
++)
161 commandLine
.addArgument(commandToUse
.get(i
).toString());
163 // all cases covered previously
164 throw new UnsupportedOperationException();
168 Map
<String
, String
> environmentVariablesToUse
= environmentVariables
169 .size() > 0 ? environmentVariables
: null;
172 ExecuteResultHandler executeResultHandler
= new ExecuteResultHandler() {
174 public void onProcessComplete(int exitValue
) {
175 if (log
.isDebugEnabled())
176 log
.debug("Process " + commandLine
177 + " properly completed.");
178 if (testResult
!= null) {
179 forwardPath(testResult
, null);
180 testResult
.addResultPart(new SimpleResultPart(
181 TestStatus
.PASSED
, "Process " + commandLine
182 + " properly completed."));
186 public void onProcessFailed(ExecuteException e
) {
187 if (testResult
!= null) {
188 forwardPath(testResult
, null);
189 testResult
.addResultPart(new SimpleResultPart(
190 TestStatus
.ERROR
, "Process " + commandLine
193 throw new SlcException("Process " + commandLine
201 int exitValue
= executor
.execute(commandLine
,
202 environmentVariablesToUse
);
203 executeResultHandler
.onProcessComplete(exitValue
);
204 } catch (ExecuteException e1
) {
205 executeResultHandler
.onProcessFailed(e1
);
208 executor
.execute(commandLine
, environmentVariablesToUse
,
209 executeResultHandler
);
210 } catch (Exception e
) {
211 throw new SlcException("Could not execute command " + cmd
, e
);
213 IOUtils
.closeQuietly(stdOutWriter
);
214 IOUtils
.closeQuietly(stdErrWriter
);
220 * Shortcut method returning the current exec dir if the specified one is
223 private String
getUsedDir(File dir
) {
225 return System
.getProperty("user.dir");
227 return dir
.getPath();
230 protected void log(String logLevel
, String line
) {
231 if ("ERROR".equals(logLevel
))
233 else if ("WARN".equals(logLevel
))
235 else if ("INFO".equals(logLevel
))
237 else if ("DEBUG".equals(logLevel
))
239 else if ("TRACE".equals(logLevel
))
242 throw new SlcException("Unknown log level " + logLevel
);
245 protected void appendLineToFile(Writer writer
, String line
) {
247 writer
.append(line
).append('\n');
248 } catch (IOException e
) {
249 log
.error("Cannot write to log file", e
);
253 protected Writer
createWriter(Resource target
) {
254 FileWriter writer
= null;
256 File file
= target
.getFile();
257 writer
= new FileWriter(file
, true);
258 } catch (IOException e
) {
259 log
.error("Cannot create log file " + target
, e
);
260 IOUtils
.closeQuietly(writer
);
265 public void setCmd(String command
) {
269 public void setExecDir(String execdir
) {
270 this.execDir
= execdir
;
273 public void setStdErrLogLevel(String stdErrLogLevel
) {
274 this.stdErrLogLevel
= stdErrLogLevel
;
277 public void setStdOutLogLevel(String stdOutLogLevel
) {
278 this.stdOutLogLevel
= stdOutLogLevel
;
281 public void setSynchronous(Boolean synchronous
) {
282 this.synchronous
= synchronous
;
285 public void setCommand(List
<Object
> command
) {
286 this.command
= command
;
289 public void setOsCommands(Map
<String
, List
<Object
>> osCommands
) {
290 this.osCommands
= osCommands
;
293 public void setOsCmds(Map
<String
, String
> osCmds
) {
294 this.osCmds
= osCmds
;
297 public void setEnvironmentVariables(Map
<String
, String
> environmentVariables
) {
298 this.environmentVariables
= environmentVariables
;
301 public void setWatchdogTimeout(Long watchdogTimeout
) {
302 this.watchdogTimeout
= watchdogTimeout
;
305 public void setStdOutFile(Resource stdOutFile
) {
306 this.stdOutFile
= stdOutFile
;
309 public void setStdErrFile(Resource stdErrFile
) {
310 this.stdErrFile
= stdErrFile
;
313 public void setTestResult(TestResult testResult
) {
314 this.testResult
= testResult
;