From: Mathieu Baudier Date: Tue, 22 Dec 2009 19:22:40 +0000 (+0000) Subject: Improve SystemCall X-Git-Tag: argeo-slc-2.1.7~1509 X-Git-Url: http://git.argeo.org/?a=commitdiff_plain;h=dad97a87545102becea1beb153baa677a2dcd4d8;p=gpl%2Fargeo-slc.git Improve SystemCall git-svn-id: https://svn.argeo.org/slc/trunk@3189 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/SystemCall.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/SystemCall.java index 4d7e5d05d..8b0f3d8e8 100644 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/SystemCall.java +++ b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/SystemCall.java @@ -6,6 +6,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Writer; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -26,17 +27,14 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.slc.SlcException; import org.argeo.slc.UnsupportedException; -import org.argeo.slc.core.structure.tree.TreeSPath; import org.argeo.slc.core.structure.tree.TreeSRelatedHelper; import org.argeo.slc.core.test.SimpleResultPart; -import org.argeo.slc.structure.StructureAware; import org.argeo.slc.test.TestResult; import org.argeo.slc.test.TestStatus; import org.springframework.core.io.Resource; -/** Execute and OS system call. */ -public class SystemCall extends TreeSRelatedHelper implements Runnable, - StructureAware { +/** Execute an OS specific system call. */ +public class SystemCall extends TreeSRelatedHelper implements Runnable { private final Log log = LogFactory.getLog(getClass()); private String execDir; @@ -58,6 +56,9 @@ public class SystemCall extends TreeSRelatedHelper implements Runnable, private Boolean logCommand = false; private Boolean redirectStreams = true; + private Boolean exceptionOnFailed = true; + private Boolean mergeEnvironmentVariables = true; + private String osConsole = null; private String generateScript = null; @@ -65,17 +66,39 @@ public class SystemCall extends TreeSRelatedHelper implements Runnable, private TestResult testResult; - // Internal use - + /** Empty constructor */ public SystemCall() { } + /** + * Constructor based on the provided command list. + * + * @param command + * the command list + */ public SystemCall(List command) { - super(); this.command = command; } + /** + * Constructor based on the provided command. + * + * @param cmd + * the command. If the provided string contains no space a + * command list is initialized with the argument as first + * component (useful for chained construction) + */ + public SystemCall(String cmd) { + if (cmd.indexOf(' ') < 0) { + command = new ArrayList(); + command.add(cmd); + } else { + this.cmd = cmd; + } + } + + /** Executes the system call. */ public void run() { final Writer stdOutWriter; final Writer stdErrWriter; @@ -92,46 +115,52 @@ public class SystemCall extends TreeSRelatedHelper implements Runnable, stdErrWriter = null; } - try { - if (log.isTraceEnabled()) { - log.debug("os.name=" + System.getProperty("os.name")); - log.debug("os.arch=" + System.getProperty("os.arch")); - log.debug("os.version=" + System.getProperty("os.version")); - } + if (log.isTraceEnabled()) { + log.debug("os.name=" + System.getProperty("os.name")); + log.debug("os.arch=" + System.getProperty("os.arch")); + log.debug("os.version=" + System.getProperty("os.version")); + } - // Execution directory - File dir = new File(getExecDirToUse()); - if (!dir.exists()) - dir.mkdirs(); - - // Watchdog to check for lost processes - Executor executor = new DefaultExecutor(); - executor.setWatchdog(new ExecuteWatchdog(watchdogTimeout)); - - if (redirectStreams) { - // Redirect standard streams - executor.setStreamHandler(createExecuteStreamHandler( - stdOutWriter, stdErrWriter)); - } else { - // Dummy stream handler (otherwise pump is used) - executor.setStreamHandler(new DummyexecuteStreamHandler()); - } + // Execution directory + File dir = new File(getExecDirToUse()); + if (!dir.exists()) + dir.mkdirs(); - executor.setProcessDestroyer(new ShutdownHookProcessDestroyer()); - executor.setWorkingDirectory(dir); + // Watchdog to check for lost processes + Executor executor = new DefaultExecutor(); + executor.setWatchdog(new ExecuteWatchdog(watchdogTimeout)); - // Command line to use - final CommandLine commandLine = createCommandLine(); - if (logCommand) - log.info("Execute command:\n" + commandLine + "\n"); + if (redirectStreams) { + // Redirect standard streams + executor.setStreamHandler(createExecuteStreamHandler(stdOutWriter, + stdErrWriter)); + } else { + // Dummy stream handler (otherwise pump is used) + executor.setStreamHandler(new DummyexecuteStreamHandler()); + } - // Env variables - Map environmentVariablesToUse = environmentVariables - .size() > 0 ? environmentVariables : null; + executor.setProcessDestroyer(new ShutdownHookProcessDestroyer()); + executor.setWorkingDirectory(dir); + + // Command line to use + final CommandLine commandLine = createCommandLine(); + if (logCommand) + log.info("Execute command:\n" + commandLine + + "\n in working directory: \n" + dir + "\n"); + + // Env variables + Map environmentVariablesToUse = null; + if (environmentVariables.size() > 0) { + environmentVariablesToUse = new HashMap(); + if (mergeEnvironmentVariables) + environmentVariablesToUse.putAll(System.getenv()); + environmentVariablesToUse.putAll(environmentVariables); + } - // Execute - ExecuteResultHandler executeResultHandler = createExecuteResultHandler(commandLine); + // Execute + ExecuteResultHandler executeResultHandler = createExecuteResultHandler(commandLine); + try { if (synchronous) try { int exitValue = executor.execute(commandLine, @@ -143,8 +172,11 @@ public class SystemCall extends TreeSRelatedHelper implements Runnable, else executor.execute(commandLine, environmentVariablesToUse, executeResultHandler); + } catch (SlcException e) { + throw e; } catch (Exception e) { - throw new SlcException("Could not execute command " + cmd, e); + throw new SlcException("Could not execute command " + commandLine, + e); } finally { IOUtils.closeQuietly(stdOutWriter); IOUtils.closeQuietly(stdErrWriter); @@ -152,7 +184,10 @@ public class SystemCall extends TreeSRelatedHelper implements Runnable, } - /** Can be overridden by specific command wrapper */ + /** + * Build a command line based on the properties. Can be overridden by + * specific command wrappers. + */ protected CommandLine createCommandLine() { // Check if an OS specific command overrides String osName = System.getProperty("os.name"); @@ -214,6 +249,10 @@ public class SystemCall extends TreeSRelatedHelper implements Runnable, return commandLine; } + /** + * Creates a {@link PumpStreamHandler} which redirects streams to the custom + * logging mechanism. + */ protected ExecuteStreamHandler createExecuteStreamHandler( final Writer stdOutWriter, final Writer stdErrWriter) { // Log writers @@ -235,6 +274,7 @@ public class SystemCall extends TreeSRelatedHelper implements Runnable, return pumpStreamHandler; } + /** Creates the default {@link ExecuteResultHandler}. */ protected ExecuteResultHandler createExecuteResultHandler( final CommandLine commandLine) { return new ExecuteResultHandler() { @@ -253,14 +293,16 @@ public class SystemCall extends TreeSRelatedHelper implements Runnable, } public void onProcessFailed(ExecuteException e) { + String msg = "Process " + commandLine + " failed."; if (testResult != null) { forwardPath(testResult, null); testResult.addResultPart(new SimpleResultPart( - TestStatus.ERROR, "Process " + commandLine - + " failed.", e)); + TestStatus.ERROR, msg, e)); } else { - throw new SlcException("Process " + commandLine - + " failed.", e); + if (exceptionOnFailed) + throw new SlcException(msg, e); + else + log.error(msg, e); } } }; @@ -287,6 +329,7 @@ public class SystemCall extends TreeSRelatedHelper implements Runnable, } } + /** Log from the underlying streams. */ protected void log(String logLevel, String line) { if ("ERROR".equals(logLevel)) log.error(line); @@ -298,10 +341,15 @@ public class SystemCall extends TreeSRelatedHelper implements Runnable, log.debug(line); else if ("TRACE".equals(logLevel)) log.trace(line); + else if ("System.out".equals(logLevel)) + System.out.println(line); + else if ("System.err".equals(logLevel)) + System.err.println(line); else throw new SlcException("Unknown log level " + logLevel); } + /** Append line to a log file. */ protected void appendLineToFile(Writer writer, String line) { try { writer.append(line).append('\n'); @@ -310,6 +358,7 @@ public class SystemCall extends TreeSRelatedHelper implements Runnable, } } + /** Creates the writer for the log files. */ protected Writer createWriter(Resource target) { FileWriter writer = null; try { @@ -322,10 +371,28 @@ public class SystemCall extends TreeSRelatedHelper implements Runnable, return writer; } + /** Append the argument (for chaining) */ + public SystemCall arg(String arg) { + command.add(arg); + return this; + } + + /** Append the argument (for chaining) */ + public SystemCall arg(String arg, String value) { + command.add(arg); + command.add(value); + return this; + } + + /** */ public void setCmd(String command) { this.cmd = command; } + public void setCommand(List command) { + this.command = command; + } + public void setExecDir(String execdir) { this.execDir = execdir; } @@ -342,10 +409,6 @@ public class SystemCall extends TreeSRelatedHelper implements Runnable, this.synchronous = synchronous; } - public void setCommand(List command) { - this.command = command; - } - public void setOsCommands(Map> osCommands) { this.osCommands = osCommands; } @@ -382,6 +445,14 @@ public class SystemCall extends TreeSRelatedHelper implements Runnable, this.redirectStreams = redirectStreams; } + public void setExceptionOnFailed(Boolean exceptionOnFailed) { + this.exceptionOnFailed = exceptionOnFailed; + } + + public void setMergeEnvironmentVariables(Boolean mergeEnvironmentVariables) { + this.mergeEnvironmentVariables = mergeEnvironmentVariables; + } + public void setOsConsole(String osConsole) { this.osConsole = osConsole; }