1 /***
2 * Redistribution and use of this software and associated documentation
3 * ("Software"), with or without modification, are permitted provided
4 * that the following conditions are met:
5 *
6 * 1. Redistributions of source code must retain copyright
7 * statements and notices. Redistributions must also contain a
8 * copy of this document.
9 *
10 * 2. Redistributions in binary form must reproduce the
11 * above copyright notice, this list of conditions and the
12 * following disclaimer in the documentation and/or other
13 * materials provided with the distribution.
14 *
15 * 3. The name "Exolab" must not be used to endorse or promote
16 * products derived from this Software without prior written
17 * permission of Exoffice Technologies. For written permission,
18 * please contact tma@netspace.net.au.
19 *
20 * 4. Products derived from this Software may not be called "Exolab"
21 * nor may "Exolab" appear in their names without prior written
22 * permission of Exoffice Technologies. Exolab is a registered
23 * trademark of Exoffice Technologies.
24 *
25 * 5. Due credit should be given to the Exolab Project
26 * (http://www.exolab.org/).
27 *
28 * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32 * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39 * OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Copyright 2001-2004 (C) Exoffice Technologies Inc. All Rights Reserved.
42 *
43 * $Id: Executor.java,v 1.3 2004/01/31 13:44:24 tanderson Exp $
44 */
45 package org.exolab.jmscts.core;
46
47 import java.io.BufferedReader;
48 import java.io.IOException;
49 import java.io.InputStream;
50 import java.io.InputStreamReader;
51 import java.io.OutputStream;
52 import java.io.PrintStream;
53
54
55 /***
56 * This class enables commands to be executed, with the output being
57 * captured, or echoed to System.out and System.err
58 *
59 * @version $Revision: 1.3 $ $Date: 2004/01/31 13:44:24 $
60 * @author <a href="mailto:tma@netspace.net.au">Tim Anderson</a>
61 */
62 public class Executor {
63
64 /***
65 * The command to execute
66 */
67 private final String _command;
68
69 /***
70 * The stream to direct standard out to
71 */
72 private final OutputStream _out;
73
74 /***
75 * The stream to direct standard err to
76 */
77 private final OutputStream _err;
78
79 /***
80 * Reference to the executing process
81 */
82 private volatile Process _process = null;
83
84 /***
85 * Constructor to execute a command, with output going to System.out and
86 * System.err
87 *
88 * @param command the command to execute
89 */
90 public Executor(String command) {
91 this(command, System.out, System.err);
92 }
93
94 /***
95 * Constructor to execute a command, with all output going to a stream
96 *
97 * @param command the command to execute
98 * @param log the stream to log output to
99 */
100 public Executor(String command, OutputStream log) {
101 this(command, log, log);
102 }
103
104 /***
105 * Constructor to execute a command with standard output and error output
106 * going to two separate streams
107 *
108 * @param command the command to execute
109 * @param out the stream to direct standard output to
110 * @param err the stream to direct standard error to
111 */
112 public Executor(String command, OutputStream out, OutputStream err) {
113 if (command == null) {
114 throw new IllegalArgumentException("Argument 'command' is null");
115 }
116 if (out == null) {
117 throw new IllegalArgumentException("Argument 'out' is null");
118 }
119 if (err == null) {
120 throw new IllegalArgumentException("Argument 'err' is null");
121 }
122 _command = command;
123 _out = out;
124 _err = err;
125 }
126
127 /***
128 * Execute the command
129 *
130 * @return the command exit status
131 * @throws Exception if the command cannot be executed
132 */
133 public int run() throws Exception {
134 Thread outStream = null;
135 Thread errStream = null;
136 boolean done = false;
137 int status = 1;
138
139 try {
140 _process = Runtime.getRuntime().exec(_command);
141 Reader out = new Reader(_process.getInputStream(), _out);
142 Reader err = new Reader(_process.getErrorStream(), _err);
143 outStream = new Thread(out);
144 errStream = new Thread(err);
145
146 outStream.start();
147 errStream.start();
148
149 while (!done) {
150 try {
151 status = _process.waitFor();
152 done = true;
153 } catch (InterruptedException ignore) {
154 // no-op
155 }
156 }
157 } catch (Exception error) {
158 if (_process != null && !done) {
159 _process.destroy();
160 }
161 if (outStream != null) {
162 boolean stopped = false;
163 while (!stopped) {
164 try {
165 outStream.join();
166 stopped = true;
167 } catch (InterruptedException ignore) {
168 // no-op
169 }
170 }
171 }
172 if (errStream != null) {
173 boolean stopped = false;
174 while (!stopped) {
175 try {
176 errStream.join();
177 stopped = true;
178 } catch (InterruptedException ignore) {
179 // no-op
180 }
181 }
182 }
183 throw error;
184 } finally {
185 outStream = null;
186 errStream = null;
187 _process = null;
188 }
189
190 return status;
191 }
192
193 /***
194 * Stop the process
195 */
196 public void stop() {
197 if (_process != null) {
198 _process.destroy();
199 }
200 }
201
202 } //-- Executor
203
204
205 /***
206 * Helper class that reads from one stream and writes to another, in a
207 * separate thread.
208 *
209 * @author <a href="mailto:tma@netspace.net.au">Tim Anderson</a>
210 */
211 class Reader implements Runnable {
212
213 /***
214 * The thread executing the reader instance
215 */
216 private volatile Thread _thread = null;
217
218 /***
219 * The input stream
220 */
221 private BufferedReader _input = null;
222
223 /***
224 * The output stream
225 */
226 private PrintStream _output = null;
227
228 /***
229 * The exception, if an exception was generated while performing I/O
230 */
231 private Exception _exception = null;
232
233
234 /***
235 * Construct a reader, reading from the input stream and writing to the
236 * output stream
237 *
238 * @param input the input stream
239 * @param output the output stream
240 */
241 public Reader(InputStream input, OutputStream output) {
242 _input = new BufferedReader(new InputStreamReader(input));
243 _output = new PrintStream(output);
244 }
245
246 /***
247 * Run the reader
248 */
249 public void run() {
250 _thread = Thread.currentThread();
251 String line;
252 try {
253 while (_thread != null && (line = _input.readLine()) != null) {
254 _output.println(line);
255 }
256 } catch (IOException error) {
257 // terminate this on an I/O error.
258 _exception = error;
259 _thread = null;
260 }
261 _input = null;
262 _output = null;
263 }
264
265 /***
266 * Stop the reader
267 */
268 public void stop() {
269 if (_thread != null) {
270 Thread interrupter = _thread;
271 _thread = null;
272 interrupter.interrupt();
273 }
274 }
275
276 /***
277 * Returns the exception if one was generated. If {@link #stop} was
278 * invoked then an exception is likely to have been generated.
279 *
280 * @return the exception, if one was thrown, otherwise <code>null</code>
281 */
282 public Exception getException() {
283 return _exception;
284 }
285
286 }
This page was automatically generated by Maven