From 4fa028eb5f09ce0609e496732fe6f4a90d6decfe Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Tue, 9 Jun 2009 10:22:40 +0000 Subject: [PATCH] @update:81; Use commons-exec git-svn-id: https://svn.argeo.org/slc/trunk@2518 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- runtime/org.argeo.slc.support.simple/pom.xml | 4 + .../slc/core/execution/tasks/SystemCall.java | 289 +++++++++++------- 2 files changed, 187 insertions(+), 106 deletions(-) diff --git a/runtime/org.argeo.slc.support.simple/pom.xml b/runtime/org.argeo.slc.support.simple/pom.xml index f508410e1..98dddc130 100644 --- a/runtime/org.argeo.slc.support.simple/pom.xml +++ b/runtime/org.argeo.slc.support.simple/pom.xml @@ -72,6 +72,10 @@ com.springsource.org.aspectj.weaver + + org.argeo.dep.osgi + org.argeo.dep.osgi.commons.exec + org.apache.commons com.springsource.org.apache.commons.logging diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/tasks/SystemCall.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/tasks/SystemCall.java index 574e21d9e..988b6b853 100644 --- a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/tasks/SystemCall.java +++ b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/tasks/SystemCall.java @@ -12,7 +12,19 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +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.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.exec.launcher.CommandLauncher; +import org.apache.commons.exec.launcher.CommandLauncherFactory; import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.NotImplementedException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.slc.SlcException; @@ -28,13 +40,16 @@ public class SystemCall implements Runnable { private List command = null; private Boolean synchronous = true; - private Boolean captureStdIn = false; + // private Boolean captureStdIn = false; private String stdErrLogLevel = "ERROR"; private String stdOutLogLevel = "INFO"; private Map> osCommands = new HashMap>(); private Map osCmds = new HashMap(); + private Map environmentVariables = new HashMap(); + + private Long watchdogTimeout = 24 * 60 * 60 * 1000l; public void run() { try { @@ -52,7 +67,7 @@ public class SystemCall implements Runnable { dir = new File(execDir).getCanonicalFile(); } - Process process = null; + // Process process = null; // Check if an OS specific command overrides String osName = System.getProperty("os.name"); @@ -67,6 +82,29 @@ public class SystemCall implements Runnable { else cmdToUse = cmd; + // Prepare executor + if (dir == null) + dir = new File(getUsedDir(dir)); + if (!dir.exists()) + dir.mkdirs(); + + Executor executor = new DefaultExecutor(); + executor.setWatchdog(new ExecuteWatchdog(watchdogTimeout)); + PumpStreamHandler pumpStreamHandler = new PumpStreamHandler( + new LogOutputStream() { + protected void processLine(String line, int level) { + log(stdOutLogLevel, line); + } + }, new LogOutputStream() { + protected void processLine(String line, int level) { + log(stdErrLogLevel, line); + } + }, null); + executor.setStreamHandler(pumpStreamHandler); + executor.setProcessDestroyer(new ShutdownHookProcessDestroyer()); + executor.setWorkingDirectory(dir); + final CommandLine commandLine; + // Which command definition to use if (commandToUse == null && cmdToUse == null) throw new SlcException("Please specify a command."); @@ -77,46 +115,85 @@ public class SystemCall implements Runnable { if (log.isTraceEnabled()) log.trace("Execute '" + cmdToUse + "' in " + getUsedDir(dir)); - process = Runtime.getRuntime().exec(cmdToUse, null, dir); + + commandLine = CommandLine.parse(cmdToUse); + // process = Runtime.getRuntime().exec(cmdToUse, null, dir); } else if (commandToUse != null) { if (log.isTraceEnabled()) log.trace("Execute '" + commandToUse + "' in " + getUsedDir(dir)); - ProcessBuilder processBuilder = new ProcessBuilder(commandToUse); - processBuilder.directory(dir); - process = processBuilder.start(); + if (commandToUse.size() == 0) + throw new SlcException("Command line is empty."); + + commandLine = new CommandLine(commandToUse.get(0)); + for (int i = 1; i < commandToUse.size(); i++) + commandLine.addArgument(commandToUse.get(i)); + // ProcessBuilder processBuilder = new + // ProcessBuilder(commandToUse); + // processBuilder.directory(dir); + // process = processBuilder.start(); } else { // all cases covered previously + throw new NotImplementedException(); } - // Manage standard streams - StreamReaderThread stdOutThread = new StreamReaderThread(process - .getInputStream()) { - protected void callback(String line) { - stdOutCallback(line); + // Env variables + Map environmentVariablesToUse = environmentVariables + .size() > 0 ? environmentVariables : null; + + // Execute + ExecuteResultHandler executeResultHandler = new ExecuteResultHandler() { + + public void onProcessComplete(int exitValue) { + log.info("Process " + commandLine + " properly completed."); } - }; - stdOutThread.start(); - StreamReaderThread stdErrThread = new StreamReaderThread(process - .getErrorStream()) { - protected void callback(String line) { - stdErrCallback(line); + + public void onProcessFailed(ExecuteException e) { + throw new SlcException("Process " + commandLine + + " failed.", e); } }; - stdErrThread.start(); - if (captureStdIn) - new StdInThread(process.getOutputStream()).start(); - - // Wait for the end of the process - if (synchronous) { - Integer exitCode = process.waitFor(); - if (exitCode != 0) { - Thread.sleep(5000);// leave the process a chance to log - log.warn("Process return exit code " + exitCode); + + if (synchronous) + try { + int exitValue = executor.execute(commandLine, + environmentVariablesToUse); + executeResultHandler.onProcessComplete(exitValue); + } catch (ExecuteException e1) { + executeResultHandler.onProcessFailed(e1); } - } else { - // asynchronous: return - } + else + executor.execute(commandLine, environmentVariablesToUse, + executeResultHandler); + + // Manage standard streams + // StreamReaderThread stdOutThread = new StreamReaderThread(process + // .getInputStream()) { + // protected void callback(String line) { + // stdOutCallback(line); + // } + // }; + // stdOutThread.start(); + // StreamReaderThread stdErrThread = new StreamReaderThread(process + // .getErrorStream()) { + // protected void callback(String line) { + // stdErrCallback(line); + // } + // }; + // stdErrThread.start(); + // if (captureStdIn) + // new StdInThread(process.getOutputStream()).start(); + // + // // Wait for the end of the process + // if (synchronous) { + // Integer exitCode = process.waitFor(); + // if (exitCode != 0) { + // Thread.sleep(5000);// leave the process a chance to log + // log.warn("Process return exit code " + exitCode); + // } + // } else { + // // asynchronous: return + // } } catch (Exception e) { throw new SlcException("Could not execute command " + cmd, e); } @@ -134,14 +211,14 @@ public class SystemCall implements Runnable { return dir.getPath(); } - protected void stdOutCallback(String line) { - log(stdOutLogLevel, line); - } - - protected void stdErrCallback(String line) { - log(stdErrLogLevel, line); - } - + // protected void stdOutCallback(String line) { + // log(stdOutLogLevel, line); + // } + // + // protected void stdErrCallback(String line) { + // log(stdErrLogLevel, line); + // } + // protected void log(String logLevel, String line) { if ("ERROR".equals(logLevel)) log.error(line); @@ -177,9 +254,9 @@ public class SystemCall implements Runnable { this.synchronous = synchronous; } - public void setCaptureStdIn(Boolean captureStdIn) { - this.captureStdIn = captureStdIn; - } + // public void setCaptureStdIn(Boolean captureStdIn) { + // this.captureStdIn = captureStdIn; + // } public void setCommand(List command) { this.command = command; @@ -193,69 +270,69 @@ public class SystemCall implements Runnable { this.osCmds = osCmds; } - protected abstract class StreamReaderThread extends Thread { - private final InputStream stream; - - public StreamReaderThread(InputStream stream) { - this.stream = stream; - } - - @Override - public void run() { - BufferedReader in = null; - try { - in = new BufferedReader(new InputStreamReader(stream)); - String line = null; - while ((line = in.readLine()) != null) { - stdOutCallback(line); - } - } catch (IOException e) { - if (log.isTraceEnabled()) { - log.trace("Could not read stream", e); - // catch silently - // because the other methods - // to check whether the stream - // is closed would probably - // be to costly - } - } finally { - if (synchronous) - IOUtils.closeQuietly(in); - } - } - - protected abstract void callback(String line); - } - - protected class StdInThread extends Thread { - private final OutputStream stream; - - public StdInThread(OutputStream stream) { - this.stream = stream; - } - - @Override - public void run() { - BufferedReader in = null; - Writer out = null; - try { - out = new OutputStreamWriter(stream); - in = new BufferedReader(new InputStreamReader(System.in)); - String line = null; - while ((line = in.readLine()) != null) { - out.write(line); - out.write("\n"); - out.flush(); - } - } catch (IOException e) { - throw new SlcException("Could not write to stdin stream", e); - } finally { - if (synchronous) { - IOUtils.closeQuietly(in); - IOUtils.closeQuietly(out); - } - } - } - - } + // protected abstract class StreamReaderThread extends Thread { + // private final InputStream stream; + // + // public StreamReaderThread(InputStream stream) { + // this.stream = stream; + // } + // + // @Override + // public void run() { + // BufferedReader in = null; + // try { + // in = new BufferedReader(new InputStreamReader(stream)); + // String line = null; + // while ((line = in.readLine()) != null) { + // stdOutCallback(line); + // } + // } catch (IOException e) { + // if (log.isTraceEnabled()) { + // log.trace("Could not read stream", e); + // // catch silently + // // because the other methods + // // to check whether the stream + // // is closed would probably + // // be to costly + // } + // } finally { + // if (synchronous) + // IOUtils.closeQuietly(in); + // } + // } + // + // protected abstract void callback(String line); + // } + // + // protected class StdInThread extends Thread { + // private final OutputStream stream; + // + // public StdInThread(OutputStream stream) { + // this.stream = stream; + // } + // + // @Override + // public void run() { + // BufferedReader in = null; + // Writer out = null; + // try { + // out = new OutputStreamWriter(stream); + // in = new BufferedReader(new InputStreamReader(System.in)); + // String line = null; + // while ((line = in.readLine()) != null) { + // out.write(line); + // out.write("\n"); + // out.flush(); + // } + // } catch (IOException e) { + // throw new SlcException("Could not write to stdin stream", e); + // } finally { + // if (synchronous) { + // IOUtils.closeQuietly(in); + // IOUtils.closeQuietly(out); + // } + // } + // } + // + // } } -- 2.39.5