
org.enhydra.xml.xmlc.misc.ProcessRunner Maven / Gradle / Ivy
The newest version!
/*
* Enhydra Java Application Server Project
*
* The contents of this file are subject to the Enhydra Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License on
* the Enhydra web site ( http://www.enhydra.org/ ).
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific terms governing rights and limitations
* under the License.
*
* The Initial Developer of the Enhydra Application Server is Lutris
* Technologies, Inc. The Enhydra Application Server and portions created
* by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
* All Rights Reserved.
*
* Contributor(s):
*
* $Id: ProcessRunner.java,v 1.2 2005/01/26 08:29:24 jkjome Exp $
*/
package org.enhydra.xml.xmlc.misc;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import org.enhydra.xml.io.ErrorReporter;
import org.enhydra.xml.xmlc.XMLCException;
/**
* Run a process, optionally collecting stdout/stderr.
*/
public class ProcessRunner {
/**
* Options to enable passing or collecting of output.
*/
public static final int PASS_STDOUT = 0x01;
public static final int PASS_STDERR = 0x02;
public static final int COLLECT_STDOUT = 0x04;
public static final int COLLECT_STDERR = 0x08;
public static final int STDERR_TO_REPORTER = 0x10;
public static final int DUMP_STDERR_ON_FAIL = 0x20;
public static final int NO_EXCEPTION_ON_ERR_EXIT = 0x40;
/*
* Output streams; maybe null.
*/
private OutputStream stdoutStream;
private OutputStream stderrStream;
/*
* Collection buffers; maybe null.
*/
private StringBuffer stdoutBuf;
private StringBuffer stderrBuf;
/**
* Options.
*/
private int options;
/**
* Exit code of last process.
*/
int exitCode;
/**
* Output monitoring thread.
*/
private class OutputMonitorThread extends Thread {
private BufferedReader input;
private PrintWriter output;
private StringBuffer outputBuf;
private IOException ioException = null;
private boolean terminateRequested;
/**
* Construct an output monitor thread object.
* @param in Stream to read from.
* @param out Stream to write to. If null, don't copy to an
* output stream.
* @param outBuf Buffer to collect output in. If null, don't collect.
*/
OutputMonitorThread(InputStream in,
OutputStream out,
StringBuffer outBuf) {
input = new BufferedReader(new InputStreamReader(in));
if (out != null) {
output = new PrintWriter(new OutputStreamWriter(out), true);
}
outputBuf = outBuf;
}
/**
* Terminate the monitor thread.
*/
public void terminate() {
interrupt();
terminateRequested = true;
}
/**
* Get an exception, if one terminated the thread, otherwise
* null indicates no errors.
*/
public IOException getException() {
return ioException;
}
/**
* Copy the stream until eof.
*/
private void copyStream() throws IOException {
String line;
while ((line = input.readLine()) != null) {
if (output != null) {
output.println(line);
}
if (outputBuf != null) {
outputBuf.append(line);
outputBuf.append('\n');
}
}
}
/**
* Run the copy thread.
*/
public void run() {
try {
copyStream();
} catch (IOException except) {
ioException = except;
}
if (output != null) {
output.flush();
}
}
}
/**
* Constructor.
*/
public ProcessRunner(int opts) {
setOptions(opts);
}
/**
* Set the options
*/
public void setOptions(int opts) {
options = opts;
if ((options & PASS_STDOUT) != 0) {
stdoutStream = System.out;
} else {
stdoutStream = null;
}
if ((options & PASS_STDERR) != 0) {
stderrStream = System.err;
} else {
stderrStream = null;
}
if ((options & DUMP_STDERR_ON_FAIL) != 0) {
options |= COLLECT_STDERR;
}
}
/**
* Get the options
*/
public int getOptions() {
return options;
}
/*
* Get exit code of process.
*/
public int getExitCode() {
return exitCode;
}
/*
* Dump stderr if requested on a failure.
*/
private void dumpStderr(ErrorReporter errorReporter) {
if ((options & DUMP_STDERR_ON_FAIL) != 0) {
errorReporter.error(stderrBuf.toString());
}
}
/**
* Monitor the running process.
*/
private void monProc(Process proc)
throws IOException, InterruptedException {
// Don't wipe out old buffer in case it was saved.
if ((options & COLLECT_STDOUT) != 0) {
stdoutBuf = new StringBuffer();
} else {
stdoutBuf = null;
}
if ((options & COLLECT_STDERR) != 0) {
stderrBuf = new StringBuffer();
} else {
stderrBuf = null;
}
OutputMonitorThread outMon =
new OutputMonitorThread(proc.getInputStream(),
stdoutStream,
stdoutBuf);
OutputMonitorThread errMon =
new OutputMonitorThread(proc.getErrorStream(),
stderrStream,
stderrBuf);
try {
outMon.start();
errMon.start();
proc.waitFor();
} catch (InterruptedException except) {
try {
// Last ditch effort to clean up proc
proc.destroy();
proc.waitFor();
} catch (InterruptedException drop) {
// Already have an error...
}
outMon.terminate();
errMon.terminate();
} finally {
outMon.join();
errMon.join();
}
if (outMon.getException() != null) {
throw outMon.getException();
}
if (errMon.getException() != null) {
throw errMon.getException();
}
}
/**
* Run a process. Stdout/stderr are optionally copied to the standard
* descriptors and/or collected.
*
* @param cmd Program to run and arguments.
* @param verboseOut Write verbose message to this file if not null.
* @param failMsg Message to use in exception if process fails.
*/
public void run(String[] cmd,
ErrorReporter errorReporter,
PrintWriter verboseOut,
String failMsg) throws XMLCException {
if (verboseOut != null) {
for (int i = 0; i < cmd.length; i++) {
if (i > 0) {
verboseOut.print(" ");
}
verboseOut.print(cmd[i]);
}
verboseOut.println();
}
Process proc;
exitCode = 0;
try {
proc = Runtime.getRuntime().exec(cmd);
monProc(proc);
} catch (IOException except) {
dumpStderr(errorReporter);
throw new XMLCException(except);
} catch (InterruptedException except) {
dumpStderr(errorReporter);
throw new XMLCException(except);
}
exitCode = proc.exitValue();
if (exitCode != 0) {
dumpStderr(errorReporter);
if ((options & NO_EXCEPTION_ON_ERR_EXIT) == 0) {
throw new XMLCException(failMsg);
}
}
}
/**
* Get accumulated stdout, or null if it was not collected.
*/
public String getStdout() {
return stdoutBuf.toString();
}
/**
* Get accumulated stderr, or null if it was not collected.
*/
public String getStderr() {
return stderrBuf.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy