X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;ds=sidebyside;f=runtime%2Forg.argeo.slc.core%2Fsrc%2Fmain%2Fjava%2Forg%2Fargeo%2Fslc%2Fcore%2Fexecution%2Ftasks%2FSystemCall.java;h=4d7e5d05dbc8013d7b8d829787bec8cc0b7f3ded;hb=d97c350e280087a06a5add83055a752143f2b3ab;hp=f3314ac7f46616b9b84334e1a60e4dec6410d335;hpb=09ab1aca27488e1feef6c8f46b34b7d27284be9a;p=gpl%2Fargeo-slc.git 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 f3314ac7f..4d7e5d05d 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 @@ -3,6 +3,8 @@ package org.argeo.slc.core.execution.tasks; import java.io.File; import java.io.FileWriter; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.io.Writer; import java.util.HashMap; import java.util.List; @@ -12,15 +14,18 @@ import org.apache.commons.exec.CommandLine; import org.apache.commons.exec.DefaultExecutor; import org.apache.commons.exec.ExecuteException; import org.apache.commons.exec.ExecuteResultHandler; +import org.apache.commons.exec.ExecuteStreamHandler; import org.apache.commons.exec.ExecuteWatchdog; import org.apache.commons.exec.Executor; import org.apache.commons.exec.LogOutputStream; import org.apache.commons.exec.PumpStreamHandler; import org.apache.commons.exec.ShutdownHookProcessDestroyer; +import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; 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; @@ -51,10 +56,17 @@ public class SystemCall extends TreeSRelatedHelper implements Runnable, private Map osCmds = new HashMap(); private Map environmentVariables = new HashMap(); + private Boolean logCommand = false; + private Boolean redirectStreams = true; + private String osConsole = null; + private String generateScript = null; + private Long watchdogTimeout = 24 * 60 * 60 * 1000l; private TestResult testResult; + // Internal use + public SystemCall() { } @@ -65,7 +77,6 @@ public class SystemCall extends TreeSRelatedHelper implements Runnable, } public void run() { - // Log writers final Writer stdOutWriter; final Writer stdErrWriter; if (stdOutFile != null) { @@ -89,16 +100,7 @@ public class SystemCall extends TreeSRelatedHelper implements Runnable, } // Execution directory - File dir = null; - if (execDir != null) { - // Replace '/' by local file separator, for portability - execDir.replace('/', File.separatorChar); - dir = new File(execDir).getCanonicalFile(); - } - - // Prepare executor - if (dir == null) - dir = new File(getUsedDir(dir)); + File dir = new File(getExecDirToUse()); if (!dir.exists()) dir.mkdirs(); @@ -106,59 +108,29 @@ public class SystemCall extends TreeSRelatedHelper implements Runnable, Executor executor = new DefaultExecutor(); executor.setWatchdog(new ExecuteWatchdog(watchdogTimeout)); - // Redirect standard streams - PumpStreamHandler pumpStreamHandler = new PumpStreamHandler( - new LogOutputStream() { - protected void processLine(String line, int level) { - log(stdOutLogLevel, line); - if (stdOutWriter != null) - appendLineToFile(stdOutWriter, line); - } - }, new LogOutputStream() { - protected void processLine(String line, int level) { - log(stdErrLogLevel, line); - if (stdErrWriter != null) - appendLineToFile(stdErrWriter, line); - } - }, null); - executor.setStreamHandler(pumpStreamHandler); + if (redirectStreams) { + // Redirect standard streams + executor.setStreamHandler(createExecuteStreamHandler( + stdOutWriter, stdErrWriter)); + } else { + // Dummy stream handler (otherwise pump is used) + executor.setStreamHandler(new DummyexecuteStreamHandler()); + } + executor.setProcessDestroyer(new ShutdownHookProcessDestroyer()); executor.setWorkingDirectory(dir); // Command line to use final CommandLine commandLine = createCommandLine(); + if (logCommand) + log.info("Execute command:\n" + commandLine + "\n"); // Env variables Map environmentVariablesToUse = environmentVariables .size() > 0 ? environmentVariables : null; // Execute - ExecuteResultHandler executeResultHandler = new ExecuteResultHandler() { - - public void onProcessComplete(int exitValue) { - if (log.isDebugEnabled()) - log.debug("Process " + commandLine - + " properly completed."); - if (testResult != null) { - forwardPath(testResult, null); - testResult.addResultPart(new SimpleResultPart( - TestStatus.PASSED, "Process " + commandLine - + " properly completed.")); - } - } - - public void onProcessFailed(ExecuteException e) { - if (testResult != null) { - forwardPath(testResult, null); - testResult.addResultPart(new SimpleResultPart( - TestStatus.ERROR, "Process " + commandLine - + " failed.", e)); - } else { - throw new SlcException("Process " + commandLine - + " failed.", e); - } - } - }; + ExecuteResultHandler executeResultHandler = createExecuteResultHandler(commandLine); if (synchronous) try { @@ -180,7 +152,7 @@ public class SystemCall extends TreeSRelatedHelper implements Runnable, } - /** Can be overridden by specific command wrapper*/ + /** Can be overridden by specific command wrapper */ protected CommandLine createCommandLine() { // Check if an OS specific command overrides String osName = System.getProperty("os.name"); @@ -195,7 +167,7 @@ public class SystemCall extends TreeSRelatedHelper implements Runnable, else cmdToUse = cmd; - final CommandLine commandLine; + CommandLine commandLine = null; // Which command definition to use if (commandToUse == null && cmdToUse == null) @@ -210,24 +182,109 @@ public class SystemCall extends TreeSRelatedHelper implements Runnable, throw new SlcException("Command line is empty."); commandLine = new CommandLine(commandToUse.get(0).toString()); - for (int i = 1; i < commandToUse.size(); i++) + + for (int i = 1; i < commandToUse.size(); i++) { + if (log.isTraceEnabled()) + log.debug(commandToUse.get(i)); commandLine.addArgument(commandToUse.get(i).toString()); + } } else { // all cases covered previously - throw new UnsupportedOperationException(); + throw new UnsupportedException(); } + + if (generateScript != null) { + File scriptFile = new File(getExecDirToUse() + File.separator + + generateScript); + try { + FileUtils.writeStringToFile(scriptFile, + (osConsole != null ? osConsole + " " : "") + + commandLine.toString()); + } catch (IOException e) { + throw new SlcException("Could not generate script " + + scriptFile, e); + } + commandLine = new CommandLine(scriptFile); + } else { + if (osConsole != null) + commandLine = CommandLine.parse(osConsole + " " + + commandLine.toString()); + } + return commandLine; } + protected ExecuteStreamHandler createExecuteStreamHandler( + final Writer stdOutWriter, final Writer stdErrWriter) { + // Log writers + + PumpStreamHandler pumpStreamHandler = new PumpStreamHandler( + new LogOutputStream() { + protected void processLine(String line, int level) { + log(stdOutLogLevel, line); + if (stdOutWriter != null) + appendLineToFile(stdOutWriter, line); + } + }, new LogOutputStream() { + protected void processLine(String line, int level) { + log(stdErrLogLevel, line); + if (stdErrWriter != null) + appendLineToFile(stdErrWriter, line); + } + }, null); + return pumpStreamHandler; + } + + protected ExecuteResultHandler createExecuteResultHandler( + final CommandLine commandLine) { + return new ExecuteResultHandler() { + + public void onProcessComplete(int exitValue) { + if (log.isDebugEnabled()) + log + .debug("Process " + commandLine + + " properly completed."); + if (testResult != null) { + forwardPath(testResult, null); + testResult.addResultPart(new SimpleResultPart( + TestStatus.PASSED, "Process " + commandLine + + " properly completed.")); + } + } + + public void onProcessFailed(ExecuteException e) { + if (testResult != null) { + forwardPath(testResult, null); + testResult.addResultPart(new SimpleResultPart( + TestStatus.ERROR, "Process " + commandLine + + " failed.", e)); + } else { + throw new SlcException("Process " + commandLine + + " failed.", e); + } + } + }; + } + /** - * Shortcut method returning the current exec dir if the specified one is - * null. + * Shortcut method getting the execDir to use */ - private String getUsedDir(File dir) { - if (dir == null) - return System.getProperty("user.dir"); - else - return dir.getPath(); + protected String getExecDirToUse() { + try { + File dir = null; + if (execDir != null) { + // Replace '/' by local file separator, for portability + execDir.replace('/', File.separatorChar); + dir = new File(execDir).getCanonicalFile(); + } + + if (dir == null) + return System.getProperty("user.dir"); + else + return dir.getPath(); + } catch (Exception e) { + throw new SlcException("Cannot find exec dir", e); + } } protected void log(String logLevel, String line) { @@ -317,4 +374,39 @@ public class SystemCall extends TreeSRelatedHelper implements Runnable, this.testResult = testResult; } + public void setLogCommand(Boolean logCommand) { + this.logCommand = logCommand; + } + + public void setRedirectStreams(Boolean redirectStreams) { + this.redirectStreams = redirectStreams; + } + + public void setOsConsole(String osConsole) { + this.osConsole = osConsole; + } + + public void setGenerateScript(String generateScript) { + this.generateScript = generateScript; + } + + private class DummyexecuteStreamHandler implements ExecuteStreamHandler { + + public void setProcessErrorStream(InputStream is) throws IOException { + } + + public void setProcessInputStream(OutputStream os) throws IOException { + } + + public void setProcessOutputStream(InputStream is) throws IOException { + } + + public void start() throws IOException { + } + + public void stop() { + } + + } + }