package org.argeo.slc.runtime.tasks; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Properties; import org.apache.commons.io.IOUtils; import org.argeo.slc.SlcException; /** A Java Virtual Machine process. */ public class JvmProcess extends SystemCall { private Properties systemProperties = new Properties(); private List classpath = new ArrayList(); private List pBootClasspath = new ArrayList(); private Path jvm = null; private String mainClass; private String mainJar; private List jvmArgs = new ArrayList(); private List args = new ArrayList(); private String systemPropertiesFileProperty = null; private String systemPropertiesFileDir = null; private String systemPropertiesFileName = null; public void init() throws Exception { List command = new ArrayList(); if (jvm != null) command.add(asFile(jvm).getPath()); else command.add("java"); if (pBootClasspath.size() > 0) { StringBuffer buf = new StringBuffer("-Xbootclasspath/p:"); Boolean first = true; for (Path res : pBootClasspath) { if (first) first = false; else buf.append(File.pathSeparatorChar); buf.append(asFile(res)); } command.add(buf.toString()); } for (String jvmArg : jvmArgs) { command.add(jvmArg); } if (classpath.size() > 0) { command.add("-cp"); StringBuffer buf = new StringBuffer(""); for (Path res : classpath) { if (buf.length() != 0) buf.append(File.pathSeparatorChar); buf.append(asFile(res)); } command.add(buf.toString()); } if (systemPropertiesFileProperty == null) { // pass system properties as argument for (Map.Entry 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 if (mainClass != null) { command.add(mainClass); } else if (mainJar != null) { command.add("-jar"); command.add(mainJar); } else { throw new SlcException("No main class or jar defined"); } for (String arg : args) { command.add(arg); } setCommand(command); } protected File asFile(Path res) { File file = res.toFile(); if (!file.exists()) return copyToTempFile(res); else return res.toFile(); } protected File copyToTempFile(Path res) { File tempFile; FileOutputStream fos; try { tempFile = File.createTempFile("slcJvmProcess-", res.getFileName().toString()); tempFile.deleteOnExit(); fos = new FileOutputStream(tempFile); IOUtils.copy(Files.newInputStream(res), fos); } catch (IOException e) { throw new SlcException("Cannot copy " + res + " to temp file.", e); } IOUtils.closeQuietly(fos); return tempFile; } /** Append the argument (for chaining) */ @Override public SystemCall arg(String arg) { args.add(arg); return this; } /** Append the argument (for chaining) */ @Override public SystemCall arg(String arg, String value) { args.add(arg); args.add(value); return this; } public Properties getSystemProperties() { return systemProperties; } public void setSystemProperties(Properties systemProperties) { this.systemProperties = systemProperties; } public List getClasspath() { return classpath; } public void setClasspath(List classpath) { this.classpath = classpath; } public List getPBootClasspath() { return pBootClasspath; } public void setPBootClasspath(List bootClasspath) { pBootClasspath = bootClasspath; } public Path getJvm() { return jvm; } public void setJvm(Path jvm) { this.jvm = jvm; } public String getMainClass() { return mainClass; } public void setMainClass(String mainClass) { this.mainClass = mainClass; } public String getMainJar() { return mainJar; } public void setMainJar(String mainJar) { this.mainJar = mainJar; } public List getJvmArgs() { return jvmArgs; } public void setJvmArgs(List jvmArgs) { this.jvmArgs = jvmArgs; } public List getArgs() { return args; } public void setArgs(List args) { 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; } }