// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. package org.chromium.sdk.tests.system.runner; import java.io.IOException; import java.io.InputStream; /** * Utility class for running external processes with reading their output and * additionally dumping it on console. */ public class ProcessRunner { interface ProcessFactory { Process create(Runtime runtime) throws IOException; } static ProcessWrapper startProcess(ProcessFactory processFactory, boolean dump) { Process process; try { process = processFactory.create(Runtime.getRuntime()); } catch (IOException e) { throw new RuntimeException(e); } ProcessWrapper wrapper = new ProcessWrapper(process, dump); wrapper.startThreads(); return wrapper; } static ProcessOutput executeProcess(ProcessFactory processFactory, boolean dump) { return startProcess(processFactory, dump).getResult(); } static class ProcessWrapper { private final Process process; private final ProcessRunner.StreamReading outputReading; private final ProcessRunner.StreamReading errorReading; ProcessWrapper(Process process, boolean dump) { this.process = process; outputReading = new ProcessRunner.StreamReading(process.getInputStream(), dump); errorReading = new ProcessRunner.StreamReading(process.getErrorStream(), dump); } void startThreads() { outputReading.start(); errorReading.start(); } ProcessOutput getResult() { final String outputString = outputReading.getResult(); final String errorString = errorReading.getResult(); final int exitCode; try { exitCode = process.waitFor(); } catch (InterruptedException e) { throw new RuntimeException(e); } return new ProcessOutput() { @Override public int getReturnCode() { return exitCode; } @Override public String getOutput() { return outputString; } @Override public String getError() { return errorString; } }; } public void kill() { process.destroy(); } } private static class StreamReading { private final StringBuilder builder = new StringBuilder(); private final InputStream stream; private final Thread thread; StreamReading(InputStream streamParam, final boolean dump) { this.stream = streamParam; thread = new Thread(new Runnable() { @Override public void run() { byte[] buffer = new byte[1024]; while (true) { int res; try { res = stream.read(buffer); } catch (IOException e) { // Probably the process terminated and the stream was closed. break; } if (res == -1) { break; } String str = new String(buffer, 0, res); if (dump) { System.out.print(str); } builder.append(str); } } }, StreamReading.class.getName()); } void start() { thread.start(); } String getResult() { try { thread.join(); } catch (InterruptedException e) { throw new RuntimeException(e); } return builder.toString(); } } interface ProcessOutput { String getOutput(); String getError(); int getReturnCode(); } }