Having considered a rather messy solution involving threads, joins, etc, I stumbled across the Executor framework that appeared in Java 1.5. Although the concepts seemed a little abstract at first, it provided a fairly elegant way of doing it:
public void executeCommand(String command, long timeoutInSeconds) throws IOException,
InterruptedException, ProcessException {
ExecutorService service = Executors.newSingleThreadExecutor();
Process process = Runtime.getRuntime().exec(command);
try {
Callablecall = new CallableProcess(process);
Futurefuture = service.submit(call);
int exitValue = future.get(timeoutInSeconds, TimeUnit.SECONDS);
if (exitValue != 0) {
throw new ProcessException("Process did not exit correctly");
}
}
catch (ExecutionException e) {
throw new ProcessException("Process failed to execute", e);
}
catch (TimeoutException e) {
process.destroy();
throw new ProcessException("Process timed out", e);
}
finally {
service.shutdown();
}
}
private class CallableProcess implements Callable{
private Process p;
public CallableProcess(Process process) {
p = process;
}
public Integer call() throws Exception {
return p.waitFor();
}
}
Best of all, it actually works. :-)
