org.wamblee.io.SimpleProcess Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2005-2010 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.StringWriter;
import java.io.Writer;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author $author$
* @version $Revision$
*/
public class SimpleProcess {
private static final Logger LOG = Logger.getLogger(SimpleProcess.class
.getName());
private File directory;
private String[] cmd;
private String stdout;
private String stderr;
/**
* Creates a new SimpleProcess object.
*
*/
public SimpleProcess(File aDirectory, String[] aCmd) {
directory = aDirectory;
cmd = Arrays.copyOf(aCmd, aCmd.length);
}
/**
*
* @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 {
StringBuffer fullcmd = new StringBuffer();
for (String part : cmd) {
fullcmd.append(" " + part);
}
LOG.fine("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.warning("Exit value was non-zero: " + this);
} else {
LOG.fine("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
.log(
Level.WARNING,
this +
": error waiting for output stream reader of process to finish",
e);
}
}
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.fine(aPrefix + str);
aOutput.write(str);
}
} catch (IOException e) {
LOG.log(Level.FINE, SimpleProcess.this +
": error reading input stream", e);
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
LOG.log(Level.WARNING, "Error closing stream " +
aPrefix, e);
}
}
}
}
};
inputReader.start();
return inputReader;
}
@Override
public String toString() {
StringBuffer fullcmd = new StringBuffer();
for (String part : cmd) {
fullcmd.append(part + " ");
}
return "process(dir = '" + directory + "', cmd = '" + fullcmd + "')";
}
}