import java.util.Map;
import java.util.Properties;
-import org.apache.commons.exec.CommandLine;
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.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
-public class JvmProcess extends SystemCall {
- private final static Log log = LogFactory.getLog(JvmProcess.class);
-
+public class JvmProcess extends SystemCall implements InitializingBean {
private Properties systemProperties = new Properties();
private List<Resource> classpath = new ArrayList<Resource>();
private List<Resource> pBootClasspath = new ArrayList<Resource>();
private List<String> jvmArgs = new ArrayList<String>();
private List<String> args = new ArrayList<String>();
- @Override
- protected CommandLine createCommandLine() {
- final CommandLine cl;
+ private String systemPropertiesFileProperty = null;
+ private String systemPropertiesFileDir = null;
+ private String systemPropertiesFileName = null;
+
+ public void afterPropertiesSet() throws Exception {
+ List<Object> command = new ArrayList<Object>();
if (jvm != null)
- cl = new CommandLine(asFile(jvm));
+ command.add(asFile(jvm).getAbsolutePath());
else
- cl = new CommandLine("java");
+ command.add("java");
if (pBootClasspath.size() > 0) {
StringBuffer buf = new StringBuffer("-Xbootclasspath/p:");
buf.append(asFile(res));
}
- cl.addArgument(buf.toString());
+ command.add(buf.toString());
}
for (String jvmArg : jvmArgs) {
- cl.addArgument(jvmArg);
+ command.add(jvmArg);
}
- cl.addArgument("-cp");
+ command.add("-cp");
StringBuffer buf = new StringBuffer("");
for (Resource res : classpath) {
if (buf.length() != 0)
buf.append(File.pathSeparatorChar);
buf.append(asFile(res));
}
- cl.addArgument(buf.toString());
+ command.add(buf.toString());
- for (Map.Entry<Object, Object> entry : systemProperties.entrySet()) {
- cl.addArgument("-D" + entry.getKey() + "=" + entry.getValue());
+ if (systemPropertiesFileProperty == null) {
+ // pass system properties as argument
+ for (Map.Entry<Object, Object> entry : systemProperties.entrySet()) {
+ command.add("-D" + entry.getKey() + "=" + entry.getValue());
+ }
+ } else {
+ // write system properties in a file to work around OS limitations
+ // with command line (e.g. Win XP)
+ String dir = systemPropertiesFileDir;
+ if (dir == null)
+ dir = getExecDirToUse();
+ String fileName = systemPropertiesFileName;
+ if (fileName == null)
+ fileName = systemPropertiesFileProperty + ".properties";
+
+ // Write file
+ FileOutputStream fos = null;
+ File file = new File(dir + File.separator + fileName);
+ try {
+
+ if (!file.getParentFile().exists())
+ file.getParentFile().mkdirs();
+ fos = new FileOutputStream(file);
+ systemProperties.store(fos, "Automatically generated by "
+ + getClass());
+ command.add("-D" + systemPropertiesFileProperty + "="
+ + file.getCanonicalPath());
+ } catch (IOException e) {
+ throw new SlcException("Cannot write to system properties to "
+ + file, e);
+ } finally {
+ IOUtils.closeQuietly(fos);
+ }
}
// Program
- cl.addArgument(mainClass);
+ command.add(mainClass);
for (String arg : args) {
- cl.addArgument(arg);
+ command.add(arg);
}
- if (log.isTraceEnabled())
- log.debug("Command line:\n" + cl.toString() + "\n");
-
- return cl;
+ setCommand(command);
}
protected File asFile(Resource res) {
this.args = args;
}
+ public void setSystemPropertiesFileProperty(
+ String systemPropertiesFilePropertyName) {
+ this.systemPropertiesFileProperty = systemPropertiesFilePropertyName;
+ }
+
+ public void setSystemPropertiesFileDir(String systemPropertiesFileDir) {
+ this.systemPropertiesFileDir = systemPropertiesFileDir;
+ }
+
+ public void setSystemPropertiesFileName(String systemPropertiesFileName) {
+ this.systemPropertiesFileName = systemPropertiesFileName;
+ }
+
}
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;
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.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;
private Map<String, String> osCmds = new HashMap<String, String>();
private Map<String, String> environmentVariables = new HashMap<String, String>();
+ private Boolean logCommand = false;
+ private Boolean redirectStreams = true;
+ private String osConsole = null;
+
private Long watchdogTimeout = 24 * 60 * 60 * 1000l;
private TestResult testResult;
+ // Internal use
+
public SystemCall() {
}
}
public void run() {
- // Log writers
final Writer stdOutWriter;
final Writer stdErrWriter;
if (stdOutFile != null) {
}
// 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();
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<String, String> 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 {
}
- /** 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");
throw new SlcException(
"Specify the command either as a line or as a list.");
else if (cmdToUse != null) {
+ if (osConsole != null)
+ cmdToUse = osConsole + " " + cmdToUse;
commandLine = CommandLine.parse(cmdToUse);
} else if (commandToUse != null) {
if (commandToUse.size() == 0)
throw new SlcException("Command line is empty.");
- commandLine = new CommandLine(commandToUse.get(0).toString());
- for (int i = 1; i < commandToUse.size(); i++)
+ if (osConsole != null) {
+ commandLine = CommandLine.parse(osConsole);
+ } else {
+ commandLine = new CommandLine(commandToUse.get(0).toString());
+ }
+
+ for (int i = (osConsole != null ? 0 : 1); i < commandToUse.size(); i++) {
+ log.debug(commandToUse.get(i));
commandLine.addArgument(commandToUse.get(i).toString());
+ }
} else {
// all cases covered previously
- throw new UnsupportedOperationException();
+ throw new UnsupportedException();
}
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) {
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;
+ }
+
+ 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() {
+ }
+
+ }
+
}