revamp JavaLauncher sequence to avoid problems with spaces on MacOS

This commit is contained in:
sjfink 2012-11-27 14:47:09 -08:00
parent f2a14ecb52
commit 1448f506eb
1 changed files with 72 additions and 28 deletions

View File

@ -25,21 +25,31 @@ import com.ibm.wala.util.PlatformUtil;
public class JavaLauncher extends Launcher {
/**
* @param programArgs arguments to be passed to the Java program
* @param mainClass Declaring class of the main() method to run.
* @param classpathEntries Paths that will be added to the default classpath
* @param programArgs
* arguments to be passed to the Java program
* @param mainClass
* Declaring class of the main() method to run.
* @param classpathEntries
* Paths that will be added to the default classpath
*/
public static JavaLauncher make(String programArgs, String mainClass, List<String> classpathEntries, Logger logger) {
return new JavaLauncher(programArgs, mainClass, true, classpathEntries, false, false, logger);
}
/**
* @param programArgs arguments to be passed to the Java program
* @param mainClass Declaring class of the main() method to run.
* @param inheritClasspath Should the spawned process inherit all classpath entries of the currently running process?
* @param classpathEntries Paths that will be added to the default classpath
* @param captureOutput should the launcher capture the stdout from the subprocess?
* @param captureErr should the launcher capture the stderr from the subprocess?
* @param programArgs
* arguments to be passed to the Java program
* @param mainClass
* Declaring class of the main() method to run.
* @param inheritClasspath
* Should the spawned process inherit all classpath entries of the
* currently running process?
* @param classpathEntries
* Paths that will be added to the default classpath
* @param captureOutput
* should the launcher capture the stdout from the subprocess?
* @param captureErr
* should the launcher capture the stderr from the subprocess?
*/
public static JavaLauncher make(String programArgs, String mainClass, boolean inheritClasspath, List<String> classpathEntries,
boolean captureOutput, boolean captureErr, Logger logger) {
@ -60,7 +70,8 @@ public class JavaLauncher extends Launcher {
private final String mainClass;
/**
* Should the spawned process inherit all classpath entries of the currently running process?
* Should the spawned process inherit all classpath entries of the currently
* running process?
*/
private final boolean inheritClasspath;
@ -83,17 +94,17 @@ public class JavaLauncher extends Launcher {
* A {@link Thread} which spins and drains stderr of the running process.
*/
private Thread stdErrDrain;
/**
* Absolute path of the 'java' executable to use.
*/
private String javaExe;
/**
* Extra args to pass to the JVM
*/
private String vmArgs;
/**
* The last process returned by a call to start() on this object.
*/
@ -110,7 +121,7 @@ public class JavaLauncher extends Launcher {
}
this.javaExe = defaultJavaExe();
}
public String getJavaExe() {
return javaExe;
}
@ -162,24 +173,54 @@ public class JavaLauncher extends Launcher {
public Process start() throws IllegalArgumentException, IOException {
String cp = makeClasspath();
String heap = " -Xmx800M ";
String heap = "-Xmx800M";
// on Mac, need to pass an extra parameter so we can cleanly kill child
// Java process
String signalParam = PlatformUtil.onMacOSX() ? " -Xrs " : "";
String signalParam = PlatformUtil.onMacOSX() ? "-Xrs" : null;
String ea = enableAssertions ? " -ea " : "";
String vmArgs = getVmArgs() == null ? "" : getVmArgs();
List<String> cmd = new ArrayList<String>();
String cmd = javaExe + heap + signalParam + cp + " " + makeLibPath() + " " + ea + " " + vmArgs + " " + getMainClass() + " " + getProgramArgs();
cmd.add(javaExe);
cmd.add(heap);
if (signalParam != null) {
cmd.add(signalParam);
}
cmd.add("-classpath");
cmd.add(cp);
String libPath = makeLibPath();
if (libPath != null) {
cmd.add(libPath);
}
if (enableAssertions) {
cmd.add("-ea");
}
if (vmArgs != null) {
String[] vmArgs = getVmArgs().split(" +");
for (String s : vmArgs) {
if (s.length() > 0) {
cmd.add(s);
}
}
}
cmd.add(getMainClass());
if (getProgramArgs() != null) {
String[] pa = getProgramArgs().split(" ");
for (String s : pa) {
cmd.add(s);
}
}
Process p = spawnProcess(cmd);
String[] cmds = new String[cmd.size()];
cmd.toArray(cmds);
Process p = spawnProcess(cmds);
stdErrDrain = isCaptureErr() ? captureStdErr(p) : drainStdErr(p);
stdOutDrain = isCaptureOutput() ? captureStdOut(p) : drainStdOut(p);
lastProcess = p;
return p;
}
public Process getLastProcess() {
return lastProcess;
}
@ -187,7 +228,7 @@ public class JavaLauncher extends Launcher {
private String makeLibPath() {
String libPath = System.getProperty("java.library.path");
if (libPath == null) {
return "";
return null;
} else {
return "-Djava.library.path=" + quoteStringIfNeeded(libPath);
}
@ -195,7 +236,9 @@ public class JavaLauncher extends Launcher {
/**
* Wait for the spawned process to terminate.
* @throws IllegalStateException if the process has not been started
*
* @throws IllegalStateException
* if the process has not been started
*/
public void join() {
if (stdOutDrain == null || stdErrDrain == null) {
@ -224,20 +267,21 @@ public class JavaLauncher extends Launcher {
private String makeClasspath() {
String cp = inheritClasspath ? System.getProperty("java.class.path") : "";
if (getXtraClassPath() == null || getXtraClassPath().isEmpty()) {
return " -classpath " + quoteStringIfNeeded(cp);
return quoteStringIfNeeded(cp);
} else {
for (Iterator<String> it = getXtraClassPath().iterator(); it.hasNext();) {
cp += File.pathSeparatorChar;
cp += (String) it.next();
}
return " -classpath " + quoteStringIfNeeded(cp);
return quoteStringIfNeeded(cp);
}
}
/**
* If the input string contains a space, quote it (for use as a classpath). TODO: Figure out how to make a Mac happy with quotes.
* Trailing separators are unsafe, so we have to escape the last backslash (if present and unescaped), so it doesn't escape the
* closing quote.
* If the input string contains a space, quote it (for use as a classpath).
* TODO: Figure out how to make a Mac happy with quotes. Trailing separators
* are unsafe, so we have to escape the last backslash (if present and
* unescaped), so it doesn't escape the closing quote.
*/
public static String quoteStringIfNeeded(String s) {
s = s.trim();