/* * Copyright 2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.wamblee.io; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintStream; import java.io.StringWriter; import java.io.Writer; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class SimpleProcess { private static final Log LOG = LogFactory.getLog(SimpleProcess.class); private File directory; private String[] cmd; private String stdout; private String stderr; public SimpleProcess(File aDirectory, String[] aCmd) { directory = aDirectory; cmd = aCmd; } /** * @return the stdout */ public String getStdout() { return stdout; } /** * @return the stderr */ public String getStderr() { return stderr; } /** * Runs the process and blocks until it is done. * * @return Exit status of the process. * @throws IOException * In case of problems. */ public int run() throws IOException { return runImpl(); } private int runImpl() throws IOException { try { String fullcmd = ""; for (String part: cmd) { fullcmd += " " + part; } LOG.debug("Executing '" + fullcmd + "' in directory '" + directory + "'"); java.lang.Process proc = Runtime.getRuntime().exec(cmd, null, directory); // Read standard output and error in separate threads to avoid // deadlock. StringWriter myStdout = new StringWriter(); StringWriter myStderr = new StringWriter(); Thread stdoutReader = readAndLogStream("STDOUT> ", proc .getInputStream(), myStdout); Thread stderrReader = readAndLogStream("STDERR> ", proc .getErrorStream(), myStderr); try { proc.waitFor(); } catch (InterruptedException e) { IOException exception = new IOException( "Process was terminated: " + this); exception.initCause(e); throw exception; } waitForReader(stdoutReader); waitForReader(stderrReader); stdout = myStdout.toString(); stderr = myStderr.toString(); if (proc.exitValue() != 0) { LOG.warn("Exit value was non-zero: " + this); } else { LOG.debug("Process finished"); } return proc.exitValue(); } catch (IOException e) { IOException exception = new IOException("Error executing process: " + this); exception.initCause(e); throw exception; } } private void waitForReader(Thread aReaderThread) { try { aReaderThread.join(); } catch (InterruptedException e) { LOG .warn(this + ": error waiting for output stream reader of process to finish"); } } private Thread readAndLogStream(final String aPrefix, final InputStream aStream, final Writer aOutput) { Thread inputReader = new Thread() { @Override public void run() { BufferedReader br = null; try { br = new BufferedReader(new InputStreamReader(aStream)); String str; while ((str = br.readLine()) != null) { LOG.debug(aPrefix + str); aOutput.write(str); } } catch (IOException e) { LOG.warn(SimpleProcess.this + ": error reading input stream", e); } finally { if (br != null) { try { br.close(); } catch (IOException e) { LOG.warn("Error closing stream " + aPrefix); } } } } }; inputReader.start(); return inputReader; } @Override public String toString() { String fullcmd = ""; for (String part: cmd) { fullcmd += part + " "; } return "process(dir = '" + directory + "', cmd = '" + fullcmd + "')"; } }