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
.io
.IOUtils
;
16 import org
.apache
.commons
.logging
.Log
;
17 import org
.apache
.commons
.logging
.LogFactory
;
18 import org
.argeo
.slc
.SlcException
;
19 import org
.argeo
.slc
.execution
.Executable
;
21 public class SystemCall
implements Executable
{
22 // TODO: specify environment variables
24 private final Log log
= LogFactory
.getLog(getClass());
26 private String execDir
;
28 private String cmd
= null;
29 private List
<String
> command
= null;
31 private Boolean synchronous
= true;
32 private Boolean captureStdIn
= false;
34 private String stdErrLogLevel
= "ERROR";
35 private String stdOutLogLevel
= "INFO";
37 private Map
<String
, List
<String
>> osCommands
= new HashMap
<String
, List
<String
>>();
38 private Map
<String
, String
> osCmds
= new HashMap
<String
, String
>();
40 public void execute() {
42 if (log
.isTraceEnabled()) {
43 log
.debug("os.name=" + System
.getProperty("os.name"));
44 log
.debug("os.arch=" + System
.getProperty("os.arch"));
45 log
.debug("os.version=" + System
.getProperty("os.version"));
48 // Execution directory
50 if (execDir
!= null) {
51 // Replace '/' by local file separator, for portability
52 execDir
.replace('/', File
.separatorChar
);
53 dir
= new File(execDir
).getCanonicalFile();
56 Process process
= null;
58 // Check if an OS specific command overrides
59 String osName
= System
.getProperty("os.name");
60 List
<String
> commandToUse
= null;
61 if (osCommands
.containsKey(osName
))
62 commandToUse
= osCommands
.get(osName
);
64 commandToUse
= command
;
65 String cmdToUse
= null;
66 if (osCmds
.containsKey(osName
))
67 cmdToUse
= osCmds
.get(osName
);
71 // Which command definition to use
72 if (commandToUse
== null && cmdToUse
== null)
73 throw new SlcException("Please specify a command.");
74 else if (commandToUse
!= null && cmdToUse
!= null)
75 throw new SlcException(
76 "Specify the command either as a line or as a list.");
77 else if (cmdToUse
!= null) {
78 if (log
.isTraceEnabled())
79 log
.trace("Execute '" + cmdToUse
+ "' in "
81 process
= Runtime
.getRuntime().exec(cmdToUse
, null, dir
);
82 } else if (commandToUse
!= null) {
83 if (log
.isTraceEnabled())
84 log
.trace("Execute '" + commandToUse
+ "' in "
86 ProcessBuilder processBuilder
= new ProcessBuilder(commandToUse
);
87 processBuilder
.directory(dir
);
88 process
= processBuilder
.start();
90 // all cases covered previously
93 // Manage standard streams
94 StreamReaderThread stdOutThread
= new StreamReaderThread(process
96 protected void callback(String line
) {
100 stdOutThread
.start();
101 StreamReaderThread stdErrThread
= new StreamReaderThread(process
103 protected void callback(String line
) {
104 stdErrCallback(line
);
107 stdErrThread
.start();
109 new StdInThread(process
.getOutputStream()).start();
111 // Wait for the end of the process
113 Integer exitCode
= process
.waitFor();
115 Thread
.sleep(5000);// leave the process a chance to log
116 log
.warn("Process return exit code " + exitCode
);
119 // asynchronous: return
121 } catch (Exception e
) {
122 throw new SlcException("Could not execute command " + cmd
, e
);
128 * Shortcut method returning the current exec dir if the specified one is
131 private String
getUsedDir(File dir
) {
133 return System
.getProperty("user.dir");
135 return dir
.getPath();
138 protected void stdOutCallback(String line
) {
139 log(stdOutLogLevel
, line
);
142 protected void stdErrCallback(String line
) {
143 log(stdErrLogLevel
, line
);
146 protected void log(String logLevel
, String line
) {
147 if ("ERROR".equals(logLevel
))
149 else if ("WARN".equals(logLevel
))
151 else if ("INFO".equals(logLevel
))
153 else if ("DEBUG".equals(logLevel
))
155 else if ("TRACE".equals(logLevel
))
158 throw new SlcException("Unknown log level " + logLevel
);
161 public void setCmd(String command
) {
165 public void setExecDir(String execdir
) {
166 this.execDir
= execdir
;
169 public void setStdErrLogLevel(String stdErrLogLevel
) {
170 this.stdErrLogLevel
= stdErrLogLevel
;
173 public void setStdOutLogLevel(String stdOutLogLevel
) {
174 this.stdOutLogLevel
= stdOutLogLevel
;
177 public void setSynchronous(Boolean synchronous
) {
178 this.synchronous
= synchronous
;
181 public void setCaptureStdIn(Boolean captureStdIn
) {
182 this.captureStdIn
= captureStdIn
;
185 public void setCommand(List
<String
> command
) {
186 this.command
= command
;
189 public void setOsCommands(Map
<String
, List
<String
>> osCommands
) {
190 this.osCommands
= osCommands
;
193 public void setOsCmds(Map
<String
, String
> osCmds
) {
194 this.osCmds
= osCmds
;
197 protected abstract class StreamReaderThread
extends Thread
{
198 private final InputStream stream
;
200 public StreamReaderThread(InputStream stream
) {
201 this.stream
= stream
;
206 BufferedReader in
= null;
208 in
= new BufferedReader(new InputStreamReader(stream
));
210 while ((line
= in
.readLine()) != null) {
211 stdOutCallback(line
);
213 } catch (IOException e
) {
214 if (log
.isTraceEnabled()) {
215 log
.trace("Could not read stream", e
);
217 // because the other methods
218 // to check whether the stream
219 // is closed would probably
224 IOUtils
.closeQuietly(in
);
228 protected abstract void callback(String line
);
231 protected class StdInThread
extends Thread
{
232 private final OutputStream stream
;
234 public StdInThread(OutputStream stream
) {
235 this.stream
= stream
;
240 BufferedReader in
= null;
243 out
= new OutputStreamWriter(stream
);
244 in
= new BufferedReader(new InputStreamReader(System
.in
));
246 while ((line
= in
.readLine()) != null) {
251 } catch (IOException e
) {
252 throw new SlcException("Could not write to stdin stream", e
);
255 IOUtils
.closeQuietly(in
);
256 IOUtils
.closeQuietly(out
);