blob: f9e3a677dc0a4e61c594ba75d6b627916f9bd458 [file] [log] [blame]
package com.baulsupp.process;
import java.io.IOException;
import java.io.OutputStream;
public class JavaProcess implements AppProcess {
private String[] command;
private Process process;
private boolean errHandled = false;
private boolean outHandled = false;
private boolean inHandled = false;
private JavaProcess(String[] command) throws IOException {
this.command = command;
process = Runtime.getRuntime().exec(command);
}
public static JavaProcess createProcess(String command, String[] args) throws IOException {
String[] commandArgs = concat(command, args);
return new JavaProcess(commandArgs);
}
private static String[] concat(String command, String[] args) {
String[] commandArgs = new String[args.length + 1];
commandArgs[0] = command;
System.arraycopy(args, 0, commandArgs, 1, args.length);
return commandArgs;
}
public void start() throws IOException {
if (!inHandled) {
process.getOutputStream().close();
}
// Should we throw away, it would make it explicit to direct the output somewhere.
if (!outHandled)
IOUtil.pumpAsync(process.getInputStream(), StandardStreams.stderr().getStream());
if (!errHandled)
IOUtil.pumpAsync(process.getErrorStream(), StandardStreams.stderr().getStream());
}
public Sink getInput() {
return new InSink();
}
public Source getOutput() {
return new OutSource();
}
public Source getError() {
return new ErrSource();
}
public int result() {
try {
return process.waitFor();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
public boolean hadError() {
return result() != 0;
}
public class InSink extends Sink {
public OutputStream getStream() {
inHandled = true;
return process.getOutputStream();
}
public boolean providesStream() {
return true;
}
}
public class OutSource extends Source {
public void connect(Sink sink) {
if (sink.providesStream()) {
outHandled = true;
// TODO handle result
IOUtil.pumpAsync(process.getInputStream(), sink.getStream());
} else if (sink.receivesStream()) {
outHandled = true;
sink.setStream(process.getInputStream());
} else {
throw new UnsupportedOperationException("sink type unknown");
}
}
}
public class ErrSource extends Source {
public void connect(Sink sink) {
if (sink.providesStream()) {
errHandled = true;
// TODO handle result
IOUtil.pumpAsync(process.getInputStream(), sink.getStream());
} else if (sink.receivesStream()) {
errHandled = true;
sink.setStream(process.getInputStream());
} else {
throw new UnsupportedOperationException("sink type unknown");
}
}
}
}