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
;
20 public class SystemCall
implements Runnable
{
21 // TODO: specify environment variables
23 private final Log log
= LogFactory
.getLog(getClass());
25 private String execDir
;
27 private String cmd
= null;
28 private List
<String
> command
= null;
30 private Boolean synchronous
= true;
31 private Boolean captureStdIn
= false;
33 private String stdErrLogLevel
= "ERROR";
34 private String stdOutLogLevel
= "INFO";
36 private Map
<String
, List
<String
>> osCommands
= new HashMap
<String
, List
<String
>>();
37 private Map
<String
, String
> osCmds
= new HashMap
<String
, String
>();
41 if (log
.isTraceEnabled()) {
42 log
.debug("os.name=" + System
.getProperty("os.name"));
43 log
.debug("os.arch=" + System
.getProperty("os.arch"));
44 log
.debug("os.version=" + System
.getProperty("os.version"));
47 // Execution directory
49 if (execDir
!= null) {
50 // Replace '/' by local file separator, for portability
51 execDir
.replace('/', File
.separatorChar
);
52 dir
= new File(execDir
).getCanonicalFile();
55 Process process
= null;
57 // Check if an OS specific command overrides
58 String osName
= System
.getProperty("os.name");
59 List
<String
> commandToUse
= null;
60 if (osCommands
.containsKey(osName
))
61 commandToUse
= osCommands
.get(osName
);
63 commandToUse
= command
;
64 String cmdToUse
= null;
65 if (osCmds
.containsKey(osName
))
66 cmdToUse
= osCmds
.get(osName
);
70 // Which command definition to use
71 if (commandToUse
== null && cmdToUse
== null)
72 throw new SlcException("Please specify a command.");
73 else if (commandToUse
!= null && cmdToUse
!= null)
74 throw new SlcException(
75 "Specify the command either as a line or as a list.");
76 else if (cmdToUse
!= null) {
77 if (log
.isTraceEnabled())
78 log
.trace("Execute '" + cmdToUse
+ "' in "
80 process
= Runtime
.getRuntime().exec(cmdToUse
, null, dir
);
81 } else if (commandToUse
!= null) {
82 if (log
.isTraceEnabled())
83 log
.trace("Execute '" + commandToUse
+ "' in "
85 ProcessBuilder processBuilder
= new ProcessBuilder(commandToUse
);
86 processBuilder
.directory(dir
);
87 process
= processBuilder
.start();
89 // all cases covered previously
92 // Manage standard streams
93 StreamReaderThread stdOutThread
= new StreamReaderThread(process
95 protected void callback(String line
) {
100 StreamReaderThread stdErrThread
= new StreamReaderThread(process
102 protected void callback(String line
) {
103 stdErrCallback(line
);
106 stdErrThread
.start();
108 new StdInThread(process
.getOutputStream()).start();
110 // Wait for the end of the process
112 Integer exitCode
= process
.waitFor();
114 Thread
.sleep(5000);// leave the process a chance to log
115 log
.warn("Process return exit code " + exitCode
);
118 // asynchronous: return
120 } catch (Exception e
) {
121 throw new SlcException("Could not execute command " + cmd
, e
);
127 * Shortcut method returning the current exec dir if the specified one is
130 private String
getUsedDir(File dir
) {
132 return System
.getProperty("user.dir");
134 return dir
.getPath();
137 protected void stdOutCallback(String line
) {
138 log(stdOutLogLevel
, line
);
141 protected void stdErrCallback(String line
) {
142 log(stdErrLogLevel
, line
);
145 protected void log(String logLevel
, String line
) {
146 if ("ERROR".equals(logLevel
))
148 else if ("WARN".equals(logLevel
))
150 else if ("INFO".equals(logLevel
))
152 else if ("DEBUG".equals(logLevel
))
154 else if ("TRACE".equals(logLevel
))
157 throw new SlcException("Unknown log level " + logLevel
);
160 public void setCmd(String command
) {
164 public void setExecDir(String execdir
) {
165 this.execDir
= execdir
;
168 public void setStdErrLogLevel(String stdErrLogLevel
) {
169 this.stdErrLogLevel
= stdErrLogLevel
;
172 public void setStdOutLogLevel(String stdOutLogLevel
) {
173 this.stdOutLogLevel
= stdOutLogLevel
;
176 public void setSynchronous(Boolean synchronous
) {
177 this.synchronous
= synchronous
;
180 public void setCaptureStdIn(Boolean captureStdIn
) {
181 this.captureStdIn
= captureStdIn
;
184 public void setCommand(List
<String
> command
) {
185 this.command
= command
;
188 public void setOsCommands(Map
<String
, List
<String
>> osCommands
) {
189 this.osCommands
= osCommands
;
192 public void setOsCmds(Map
<String
, String
> osCmds
) {
193 this.osCmds
= osCmds
;
196 protected abstract class StreamReaderThread
extends Thread
{
197 private final InputStream stream
;
199 public StreamReaderThread(InputStream stream
) {
200 this.stream
= stream
;
205 BufferedReader in
= null;
207 in
= new BufferedReader(new InputStreamReader(stream
));
209 while ((line
= in
.readLine()) != null) {
210 stdOutCallback(line
);
212 } catch (IOException e
) {
213 if (log
.isTraceEnabled()) {
214 log
.trace("Could not read stream", e
);
216 // because the other methods
217 // to check whether the stream
218 // is closed would probably
223 IOUtils
.closeQuietly(in
);
227 protected abstract void callback(String line
);
230 protected class StdInThread
extends Thread
{
231 private final OutputStream stream
;
233 public StdInThread(OutputStream stream
) {
234 this.stream
= stream
;
239 BufferedReader in
= null;
242 out
= new OutputStreamWriter(stream
);
243 in
= new BufferedReader(new InputStreamReader(System
.in
));
245 while ((line
= in
.readLine()) != null) {
250 } catch (IOException e
) {
251 throw new SlcException("Could not write to stdin stream", e
);
254 IOUtils
.closeQuietly(in
);
255 IOUtils
.closeQuietly(out
);