]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/tasks/SystemCall.java
Don't run system call tests under Windows
[gpl/argeo-slc.git] / runtime / org.argeo.slc.support.simple / src / main / java / org / argeo / slc / core / execution / tasks / SystemCall.java
1 package org.argeo.slc.core.execution.tasks;
2
3 import java.io.BufferedReader;
4 import java.io.File;
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;
13 import java.util.Map;
14
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;
20
21 public class SystemCall implements Executable {
22 // TODO: specify environment variables
23
24 private final Log log = LogFactory.getLog(getClass());
25
26 private String execDir;
27
28 private String cmd = null;
29 private List<String> command = null;
30
31 private Boolean synchronous = true;
32 private Boolean captureStdIn = false;
33
34 private String stdErrLogLevel = "ERROR";
35 private String stdOutLogLevel = "INFO";
36
37 private Map<String, List<String>> osCommands = new HashMap<String, List<String>>();
38 private Map<String, String> osCmds = new HashMap<String, String>();
39
40 public void execute() {
41 try {
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"));
46 }
47
48 // Execution directory
49 File dir = null;
50 if (execDir != null) {
51 // Replace '/' by local file separator, for portability
52 execDir.replace('/', File.separatorChar);
53 dir = new File(execDir).getCanonicalFile();
54 }
55
56 Process process = null;
57
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);
63 else
64 commandToUse = command;
65 String cmdToUse = null;
66 if (osCmds.containsKey(osName))
67 cmdToUse = osCmds.get(osName);
68 else
69 cmdToUse = cmd;
70
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 "
80 + getUsedDir(dir));
81 process = Runtime.getRuntime().exec(cmdToUse, null, dir);
82 } else if (commandToUse != null) {
83 if (log.isTraceEnabled())
84 log.trace("Execute '" + commandToUse + "' in "
85 + getUsedDir(dir));
86 ProcessBuilder processBuilder = new ProcessBuilder(commandToUse);
87 processBuilder.directory(dir);
88 process = processBuilder.start();
89 } else {
90 // all cases covered previously
91 }
92
93 // Manage standard streams
94 StreamReaderThread stdOutThread = new StreamReaderThread(process
95 .getInputStream()) {
96 protected void callback(String line) {
97 stdOutCallback(line);
98 }
99 };
100 stdOutThread.start();
101 StreamReaderThread stdErrThread = new StreamReaderThread(process
102 .getInputStream()) {
103 protected void callback(String line) {
104 stdErrCallback(line);
105 }
106 };
107 stdErrThread.start();
108 if (captureStdIn)
109 new StdInThread(process.getOutputStream()).start();
110
111 // Wait for the end of the process
112 if (synchronous) {
113 Integer exitCode = process.waitFor();
114 if (exitCode != 0)
115 log.warn("Process return exit code " + exitCode);
116 } else {
117 // asynchronous: return
118 }
119 } catch (Exception e) {
120 throw new SlcException("Could not execute command " + cmd, e);
121 }
122
123 }
124
125 /**
126 * Shortcut method returning the current exec dir if the specified one is
127 * null.
128 */
129 private String getUsedDir(File dir) {
130 if (dir == null)
131 return System.getProperty("user.dir");
132 else
133 return dir.getPath();
134 }
135
136 protected void stdOutCallback(String line) {
137 log(stdOutLogLevel, line);
138 }
139
140 protected void stdErrCallback(String line) {
141 log(stdErrLogLevel, line);
142 }
143
144 protected void log(String logLevel, String line) {
145 if ("ERROR".equals(logLevel))
146 log.error(line);
147 else if ("WARN".equals(logLevel))
148 log.warn(line);
149 else if ("INFO".equals(logLevel))
150 log.info(line);
151 else if ("DEBUG".equals(logLevel))
152 log.debug(line);
153 else if ("TRACE".equals(logLevel))
154 log.trace(line);
155 else
156 throw new SlcException("Unknown log level " + logLevel);
157 }
158
159 public void setCmd(String command) {
160 this.cmd = command;
161 }
162
163 public void setExecDir(String execdir) {
164 this.execDir = execdir;
165 }
166
167 public void setStdErrLogLevel(String stdErrLogLevel) {
168 this.stdErrLogLevel = stdErrLogLevel;
169 }
170
171 public void setStdOutLogLevel(String stdOutLogLevel) {
172 this.stdOutLogLevel = stdOutLogLevel;
173 }
174
175 public void setSynchronous(Boolean synchronous) {
176 this.synchronous = synchronous;
177 }
178
179 public void setCaptureStdIn(Boolean captureStdIn) {
180 this.captureStdIn = captureStdIn;
181 }
182
183 public void setCommand(List<String> command) {
184 this.command = command;
185 }
186
187 public void setOsCommands(Map<String, List<String>> osCommands) {
188 this.osCommands = osCommands;
189 }
190
191 public void setOsCmds(Map<String, String> osCmds) {
192 this.osCmds = osCmds;
193 }
194
195 protected abstract class StreamReaderThread extends Thread {
196 private final InputStream stream;
197
198 public StreamReaderThread(InputStream stream) {
199 this.stream = stream;
200 }
201
202 @Override
203 public void run() {
204 BufferedReader in = null;
205 try {
206 in = new BufferedReader(new InputStreamReader(stream));
207 String line = null;
208 while ((line = in.readLine()) != null) {
209 stdOutCallback(line);
210 }
211 } catch (IOException e) {
212 if (log.isTraceEnabled()) {
213 log.trace("Could not read stream", e);
214 // catch silently
215 // because the other methods
216 // to check whether the stream
217 // is closed would probably
218 // be to costly
219 }
220 } finally {
221 if (synchronous)
222 IOUtils.closeQuietly(in);
223 }
224 }
225
226 protected abstract void callback(String line);
227 }
228
229 protected class StdInThread extends Thread {
230 private final OutputStream stream;
231
232 public StdInThread(OutputStream stream) {
233 this.stream = stream;
234 }
235
236 @Override
237 public void run() {
238 BufferedReader in = null;
239 Writer out = null;
240 try {
241 out = new OutputStreamWriter(stream);
242 in = new BufferedReader(new InputStreamReader(System.in));
243 String line = null;
244 while ((line = in.readLine()) != null) {
245 out.write(line);
246 out.write("\n");
247 out.flush();
248 }
249 } catch (IOException e) {
250 throw new SlcException("Could not write to stdin stream", e);
251 } finally {
252 if (synchronous) {
253 IOUtils.closeQuietly(in);
254 IOUtils.closeQuietly(out);
255 }
256 }
257 }
258
259 }
260 }