// Copyright © 2010, Esko Luontola <www.orfjackal.net>
// This software is released under the Apache License 2.0.
// The license text is at http://www.apache.org/licenses/LICENSE-2.0
package net.orfjackal.sbt.runner;
import java.io.*;
public class ProcessRunner {
private final ProcessBuilder builder;
private Process process;
private Thread shutdownHook;
private final MulticastPipe outputMulticast = new MulticastPipe();
private Writer input;
public ProcessRunner(File workingDir, String... command) {
builder = new ProcessBuilder(command);
builder.directory(workingDir);
builder.redirectErrorStream(true);
}
public OutputReader subscribeToOutput() {
return new OutputReader(outputMulticast.subscribe());
}
public void start() throws IOException {
process = builder.start();
shutdownHook = new Thread(new DestroyProcessRunner(process));
InputStreamReader output = new InputStreamReader(new BufferedInputStream(process.getInputStream()));
Thread t = new Thread(new ReaderToWriterCopier(output, outputMulticast));
t.setDaemon(true);
t.start();
input = new OutputStreamWriter(new BufferedOutputStream(process.getOutputStream()));
}
public void destroyOnShutdown() {
Runtime.getRuntime().addShutdownHook(shutdownHook);
}
public void destroy() {
process.destroy();
try {
process.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
Runtime.getRuntime().removeShutdownHook(shutdownHook);
}
public boolean isAlive() {
if (process == null) {
return false;
}
try {
process.exitValue();
return false;
} catch (IllegalThreadStateException e) {
return true;
}
}
public void writeInput(String s) throws IOException {
input.write(s);
input.flush();
}
private static class DestroyProcessRunner implements Runnable {
private final Process process;
public DestroyProcessRunner(Process process) {
this.process = process;
}
public void run() {
process.destroy();
}
}
}