001: package abbot.util;
002:
003: import java.io.*;
004: import java.util.*;
005: import abbot.Log;
006:
007: /** Provides handling of process output/error streams. */
008:
009: public class ProcessOutputHandler {
010:
011: public static class ProcessAbnormalExitException extends
012: IOException {
013: private int code;
014:
015: private ProcessAbnormalExitException(String msg, int code) {
016: super (msg);
017: this .code = code;
018: }
019:
020: public int getExitValue() {
021: return code;
022: }
023: }
024:
025: private InputStreamHandler stderr;
026: private InputStreamHandler stdout;
027: private StringBuffer err = new StringBuffer();
028:
029: public ProcessOutputHandler() {
030: }
031:
032: public ProcessOutputHandler(Process p) {
033: setProcess(p);
034: }
035:
036: public String getError() {
037: return err.toString();
038: }
039:
040: public synchronized void setProcess(Process p) {
041: stdout = new InputStreamHandler(p.getInputStream()) {
042: public void handleBytes(byte[] buf, int count) {
043: handleOutput(buf, count);
044: }
045: };
046: stdout.start();
047: stderr = new InputStreamHandler(p.getErrorStream()) {
048: public void handleBytes(byte[] buf, int count) {
049: err.append(new String(buf, 0, count));
050: handleError(buf, count);
051: }
052: };
053: stderr.start();
054: }
055:
056: /** Override this method to handle stdout output. The default
057: implementation does nothing. */
058: protected void handleOutput(byte[] buf, int count) {
059: }
060:
061: /** Override this method to handle stderr output. The default
062: implementation does nothing. */
063: protected void handleError(byte[] buf, int count) {
064: }
065:
066: public synchronized void waitFor() throws InterruptedException {
067: if (stderr != null)
068: stderr.join();
069: if (stdout != null)
070: stdout.join();
071: }
072:
073: /** Returns the output of the given command as a String. */
074: public static String exec(String[] command) throws IOException {
075: return exec(command, null);
076: }
077:
078: /** Returns the output of the given command as a String. */
079: public static String exec(String[] command, String[] environment)
080: throws IOException {
081: return exec(command, environment, null);
082: }
083:
084: /** Returns the output of the given command as a String. */
085: public static String exec(String[] command, String[] environment,
086: File dir) throws IOException {
087: final StringBuffer output = new StringBuffer();
088: Log.debug("Running " + Arrays.asList(command));
089: Process p = Runtime.getRuntime()
090: .exec(command, environment, dir);
091: ProcessOutputHandler handler = new ProcessOutputHandler(p) {
092: public void handleOutput(byte[] buf, int count) {
093: output.append(new String(buf, 0, count));
094: }
095: };
096: try {
097: p.waitFor();
098: } catch (InterruptedException e) {
099: Log.debug(e);
100: }
101: try {
102: handler.waitFor();
103: } catch (InterruptedException e) {
104: }
105: int code = p.exitValue();
106: if (code != 0) {
107: String msg = "Process " + Arrays.asList(command)
108: + " exited with " + code;
109: String err = handler.getError();
110: if (!"".equals(err))
111: msg += ":\n" + err;
112: Log.debug(msg);
113: throw new ProcessAbnormalExitException(msg, code);
114: }
115: Log.debug("output=" + output.toString());
116: return output.toString();
117: }
118: }
|