/** * Pumps stdout and stderr the running process into a String. * * @param process Process to pump. * @return Output from process. * @throws IOException If an I/O error occurs. */ public static OutputBuffer getOutput(Process process) throws IOException { ByteArrayOutputStream stderrBuffer = new ByteArrayOutputStream(); ByteArrayOutputStream stdoutBuffer = new ByteArrayOutputStream(); StreamPumper outPumper = new StreamPumper(process.getInputStream(), stdoutBuffer); StreamPumper errPumper = new StreamPumper(process.getErrorStream(), stderrBuffer); Future<Void> outTask = outPumper.process(); Future<Void> errTask = errPumper.process(); try { process.waitFor(); outTask.get(); errTask.get(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return null; } catch (ExecutionException e) { throw new IOException(e); } return new OutputBuffer(stdoutBuffer.toString(), stderrBuffer.toString()); }
/** * Starts a process from its builder. <span>The default redirects of STDOUT and STDERR are * started</span> * * <p>It is possible to wait for the process to get to a warmed-up state via {@linkplain * Predicate} condition on the STDOUT * * @param name The process name * @param processBuilder The process builder * @param linePredicate The {@linkplain Predicate} to use on the STDOUT Used to determine the * moment the target app is properly warmed-up. It can be null - in that case the warmup is * skipped. * @param timeout The timeout for the warmup waiting * @param unit The timeout {@linkplain TimeUnit} * @return Returns the initialized {@linkplain Process} * @throws IOException * @throws InterruptedException * @throws TimeoutException */ public static Process startProcess( String name, ProcessBuilder processBuilder, final Predicate<String> linePredicate, long timeout, TimeUnit unit) throws IOException, InterruptedException, TimeoutException { Process p = processBuilder.start(); StreamPumper stdout = new StreamPumper(p.getInputStream()); StreamPumper stderr = new StreamPumper(p.getErrorStream()); stdout.addPump(new LineForwarder(name, System.out)); stderr.addPump(new LineForwarder(name, System.err)); CountDownLatch latch = new CountDownLatch(1); if (linePredicate != null) { StreamPumper.LinePump pump = new StreamPumper.LinePump() { @Override protected void processLine(String line) { if (latch.getCount() > 0 && linePredicate.test(line)) { latch.countDown(); } } }; stdout.addPump(pump); stderr.addPump(pump); } Future<Void> stdoutTask = stdout.process(); Future<Void> stderrTask = stderr.process(); try { if (timeout > -1) { long realTimeout = Math.round(timeout * Utils.TIMEOUT_FACTOR); if (!latch.await(realTimeout, unit)) { throw new TimeoutException(); } } } catch (TimeoutException | InterruptedException e) { System.err.println("Failed to start a process (thread dump follows)"); for (Map.Entry<Thread, StackTraceElement[]> s : Thread.getAllStackTraces().entrySet()) { printStack(s.getKey(), s.getValue()); } stdoutTask.cancel(true); stderrTask.cancel(true); throw e; } return p; }