KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > xml > xmlc > misc > ProcessRunner


1 /*
2  * Enhydra Java Application Server Project
3  *
4  * The contents of this file are subject to the Enhydra Public License
5  * Version 1.1 (the "License"); you may not use this file except in
6  * compliance with the License. You may obtain a copy of the License on
7  * the Enhydra web site ( http://www.enhydra.org/ ).
8  *
9  * Software distributed under the License is distributed on an "AS IS"
10  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
11  * the License for the specific terms governing rights and limitations
12  * under the License.
13  *
14  * The Initial Developer of the Enhydra Application Server is Lutris
15  * Technologies, Inc. The Enhydra Application Server and portions created
16  * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
17  * All Rights Reserved.
18  *
19  * Contributor(s):
20  *
21  * $Id: ProcessRunner.java,v 1.2 2005/01/26 08:29:24 jkjome Exp $
22  */

23
24 package org.enhydra.xml.xmlc.misc;
25
26 import java.io.BufferedReader JavaDoc;
27 import java.io.IOException JavaDoc;
28 import java.io.InputStream JavaDoc;
29 import java.io.InputStreamReader JavaDoc;
30 import java.io.OutputStream JavaDoc;
31 import java.io.OutputStreamWriter JavaDoc;
32 import java.io.PrintWriter JavaDoc;
33
34 import org.enhydra.xml.io.ErrorReporter;
35 import org.enhydra.xml.xmlc.XMLCException;
36
37 /**
38  * Run a process, optionally collecting stdout/stderr.
39  */

40 public class ProcessRunner {
41     /**
42      * Options to enable passing or collecting of output.
43      */

44     public static final int PASS_STDOUT = 0x01;
45     public static final int PASS_STDERR = 0x02;
46     public static final int COLLECT_STDOUT = 0x04;
47     public static final int COLLECT_STDERR = 0x08;
48     public static final int STDERR_TO_REPORTER = 0x10;
49     public static final int DUMP_STDERR_ON_FAIL = 0x20;
50     public static final int NO_EXCEPTION_ON_ERR_EXIT = 0x40;
51
52     /*
53      * Output streams; maybe null.
54      */

55     private OutputStream JavaDoc stdoutStream;
56     private OutputStream JavaDoc stderrStream;
57
58     /*
59      * Collection buffers; maybe null.
60      */

61     private StringBuffer JavaDoc stdoutBuf;
62     private StringBuffer JavaDoc stderrBuf;
63
64     /**
65      * Options.
66      */

67     private int options;
68     
69     /**
70      * Exit code of last process.
71      */

72     int exitCode;
73
74     /**
75      * Output monitoring thread.
76      */

77     private class OutputMonitorThread extends Thread JavaDoc {
78         private BufferedReader JavaDoc input;
79         private PrintWriter JavaDoc output;
80         private StringBuffer JavaDoc outputBuf;
81         private IOException JavaDoc ioException = null;
82         private boolean terminateRequested;
83
84         /**
85          * Construct an output monitor thread object.
86          * @param in Stream to read from.
87          * @param out Stream to write to. If null, don't copy to an
88          * output stream.
89          * @param outBuf Buffer to collect output in. If null, don't collect.
90          */

91         OutputMonitorThread(InputStream JavaDoc in,
92                             OutputStream JavaDoc out,
93                             StringBuffer JavaDoc outBuf) {
94             input = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(in));
95             if (out != null) {
96                 output = new PrintWriter JavaDoc(new OutputStreamWriter JavaDoc(out), true);
97             }
98             outputBuf = outBuf;
99         }
100         
101         /**
102          * Terminate the monitor thread.
103          */

104         public void terminate() {
105             interrupt();
106             terminateRequested = true;
107         }
108
109         /**
110          * Get an exception, if one terminated the thread, otherwise
111          * null indicates no errors.
112          */

113         public IOException JavaDoc getException() {
114             return ioException;
115         }
116
117
118         /**
119          * Copy the stream until eof.
120          */

121         private void copyStream() throws IOException JavaDoc {
122             String JavaDoc line;
123             while ((line = input.readLine()) != null) {
124                 if (output != null) {
125                     output.println(line);
126                 }
127                 if (outputBuf != null) {
128                     outputBuf.append(line);
129                     outputBuf.append('\n');
130                 }
131             }
132         }
133
134         /**
135          * Run the copy thread.
136          */

137         public void run() {
138             try {
139                 copyStream();
140             } catch (IOException JavaDoc except) {
141                 ioException = except;
142             }
143             if (output != null) {
144                 output.flush();
145             }
146         }
147     }
148
149     /**
150      * Constructor.
151      */

152     public ProcessRunner(int opts) {
153         setOptions(opts);
154     }
155
156     /**
157      * Set the options
158      */

159     public void setOptions(int opts) {
160         options = opts;
161         if ((options & PASS_STDOUT) != 0) {
162             stdoutStream = System.out;
163         } else {
164             stdoutStream = null;
165         }
166         if ((options & PASS_STDERR) != 0) {
167             stderrStream = System.err;
168         } else {
169             stderrStream = null;
170         }
171         if ((options & DUMP_STDERR_ON_FAIL) != 0) {
172             options |= COLLECT_STDERR;
173         }
174     }
175
176     /**
177      * Get the options
178      */

179     public int getOptions() {
180         return options;
181     }
182
183     /*
184      * Get exit code of process.
185      */

186     public int getExitCode() {
187         return exitCode;
188     }
189
190     /*
191      * Dump stderr if requested on a failure.
192      */

193     private void dumpStderr(ErrorReporter errorReporter) {
194         if ((options & DUMP_STDERR_ON_FAIL) != 0) {
195             errorReporter.error(stderrBuf.toString());
196         }
197     }
198
199     /**
200      * Monitor the running process.
201      */

202     private void monProc(Process JavaDoc proc)
203         throws IOException JavaDoc, InterruptedException JavaDoc {
204
205         // Don't wipe out old buffer in case it was saved.
206
if ((options & COLLECT_STDOUT) != 0) {
207             stdoutBuf = new StringBuffer JavaDoc();
208         } else {
209             stdoutBuf = null;
210         }
211         if ((options & COLLECT_STDERR) != 0) {
212             stderrBuf = new StringBuffer JavaDoc();
213         } else {
214             stderrBuf = null;
215         }
216
217         OutputMonitorThread outMon =
218             new OutputMonitorThread(proc.getInputStream(),
219                                     stdoutStream,
220                                     stdoutBuf);
221         OutputMonitorThread errMon =
222             new OutputMonitorThread(proc.getErrorStream(),
223                                     stderrStream,
224                                     stderrBuf);
225         try {
226             outMon.start();
227             errMon.start();
228             proc.waitFor();
229         } catch (InterruptedException JavaDoc except) {
230             try {
231                 // Last ditch effort to clean up proc
232
proc.destroy();
233                 proc.waitFor();
234             } catch (InterruptedException JavaDoc drop) {
235                 // Already have an error...
236
}
237             outMon.terminate();
238             errMon.terminate();
239         } finally {
240             outMon.join();
241             errMon.join();
242         }
243         if (outMon.getException() != null) {
244             throw outMon.getException();
245         }
246         if (errMon.getException() != null) {
247             throw errMon.getException();
248         }
249     }
250
251     /**
252      * Run a process. Stdout/stderr are optionally copied to the standard
253      * descriptors and/or collected.
254      *
255      * @param cmd Program to run and arguments.
256      * @param verboseOut Write verbose message to this file if not null.
257      * @param failMsg Message to use in exception if process fails.
258      */

259     public void run(String JavaDoc[] cmd,
260                     ErrorReporter errorReporter,
261                     PrintWriter JavaDoc verboseOut,
262                     String JavaDoc failMsg) throws XMLCException {
263         if (verboseOut != null) {
264             for (int i = 0; i < cmd.length; i++) {
265                 if (i > 0) {
266                     verboseOut.print(" ");
267                 }
268                 verboseOut.print(cmd[i]);
269             }
270             verboseOut.println();
271         }
272         
273         Process JavaDoc proc;
274         exitCode = 0;
275         try {
276             proc = Runtime.getRuntime().exec(cmd);
277             monProc(proc);
278         } catch (IOException JavaDoc except) {
279             dumpStderr(errorReporter);
280             throw new XMLCException(except);
281         } catch (InterruptedException JavaDoc except) {
282             dumpStderr(errorReporter);
283             throw new XMLCException(except);
284         }
285         exitCode = proc.exitValue();
286         if (exitCode != 0) {
287             dumpStderr(errorReporter);
288             if ((options & NO_EXCEPTION_ON_ERR_EXIT) == 0) {
289                 throw new XMLCException(failMsg);
290             }
291         }
292     }
293
294     /**
295      * Get accumulated stdout, or null if it was not collected.
296      */

297     public String JavaDoc getStdout() {
298         return stdoutBuf.toString();
299     }
300
301     /**
302      * Get accumulated stderr, or null if it was not collected.
303      */

304     public String JavaDoc getStderr() {
305         return stderrBuf.toString();
306     }
307 }
308
Popular Tags