Source code: com/klavergne/process/SmartProcess.java
1 /*
2 * 12/13/2001 - 15:41:35
3 *
4 * ClearCasePlugin.java - Plugin for Jext to integrate ClearCase
5 * Copyright (C) 2001 Kevin LaVergne
6 * klavergne@earthling.net
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22 package com.klavergne.process;
23
24 import java.io.*;
25 import java.util.*;
26
27 /**
28 * <p>This class uses the <code>Runtime</code> and <code>Process</code> classes to
29 * execute the given command from inside the VM.</p>
30 * <p>While testing this I found that the <code>Runtime</code> class works a little
31 * differently than Sun's API documentation says. Their documentation says that
32 * <code>Runtime.exec()</code> creates a subprocess without a console window. This
33 * is true if using java.exe, but if you use javaw.exe it does create a console
34 * window.</p>
35 * @author Kevin LaVergne
36 * @version 1.0
37 */
38 public class SmartProcess {
39
40 /**
41 * The command to execute.
42 */
43 private String command;
44
45 /**
46 * A boolean value indicating whether the process should handle exceptions.
47 */
48 private boolean handleExceptions;
49
50 /**
51 * A boolean value indicating whether the process should wait until complete before returning.
52 */
53 private boolean wait;
54
55 /**
56 * The exit status code of the process.
57 */
58 private int exitStatus = -999;
59
60 /**
61 * The standard output of the command that is executed.
62 */
63 private StreamReader stdout;
64
65 /**
66 * The standard error of the command that is executed.
67 */
68 private StreamReader stderr;
69
70 /**
71 * Creates a new <code>SmartProcess</code> object with the given String as the command.
72 * @param command the command to execute
73 */
74 public SmartProcess(String command) {
75 this(command, true, true);
76 }
77
78 /**
79 * Creates a new <code>SmartProcess</code> object with the given String as the command.
80 * @param aCommand the command to execute
81 * @param aWait a boolean value indicating whether the process should wait to return until execution is completed
82 */
83 public SmartProcess(String aCommand, boolean aWait) {
84 this(aCommand, aWait, true);
85 }
86
87 /**
88 * Creates a new <code>SmartProcess</code> object with the given String as the command.
89 * @param aCommand the command to execute
90 * @param aWait a boolean value indicating whether the process should wait to return until execution is completed
91 * @param aHandleExceptions a boolan value indicating whether the process should handle exceptions
92 */
93 public SmartProcess(String aCommand, boolean aWait, boolean aHandleExceptions) {
94 command = aCommand;
95 wait = aWait;
96 handleExceptions = aHandleExceptions;
97 }
98
99 /**
100 * Returns the command that this process will execute.
101 * @return the command that this process will execute
102 */
103 public String getCommand() {
104 return command;
105 }
106
107 /**
108 * Sets the command that this process will execute.
109 * @param aCommand the command that this process will execute
110 */
111 public void setCommand(String aCommand) {
112 command = aCommand;
113 }
114
115 /**
116 * Sets the command that this process will execute.
117 * @param parameters an array of Strings containing the command and all parameters for the command
118 */
119 public void setCommand(String[] parameters) {
120 setCommand(Arrays.asList(parameters));
121 }
122
123 /**
124 * Sets the command that this process will execute.
125 * @param parameters a List containing the command and all parameters for the command
126 */
127 public void setCommand(List parameters) {
128 StringBuffer sb = new StringBuffer();
129 for (Iterator i = parameters.iterator(); i.hasNext(); )
130 sb.append(' ').append(i.next());
131 command = sb.toString().trim();
132 }
133
134 /**
135 * Returns a boolean value indicating whether the process should wait to finish
136 * before returning.
137 * @return a boolean value indicating whether the process should wait to finish before returning.
138 */
139 public boolean getWait() {
140 return wait;
141 }
142
143 /**
144 * Sets the boolean value indicating whether the process should wait to finish
145 * before returning.
146 * @param aWait a boolean value indicating whether the process should wait to finish before returning
147 */
148 public void setWait(boolean aWait) {
149 wait = aWait;
150 }
151
152 /**
153 * Returns a boolean value indicating whether the process should handle exceptions.
154 * @return a boolean value indicating whether the process should handle exceptions
155 */
156 public boolean getHandleExceptions() {
157 return handleExceptions;
158 }
159
160 /**
161 * Sets a boolean value indicating whether the process should handle exceptions.
162 * @param aHandleExceptions a boolean value indicating whether the process should handle exceptions
163 */
164 public void setHandleExceptions(boolean aHandleExceptions) {
165 handleExceptions = aHandleExceptions;
166 }
167
168 /**
169 * Returns the exit status of the process.
170 * @return the exit status of the process
171 */
172 public int getExitStatus() {
173 return exitStatus;
174 }
175
176 /**
177 * Returns a String containing the text of the standard error from the process.
178 * @return a String containing the text of the standard error from the process
179 */
180 public String getStandardError() {
181 return stderr.flushStream();
182 }
183
184 /**
185 * Returns a String containing the text of the standard output from the process.
186 * @return a String containing the text of the standard output from the process
187 */
188 public String getStandardOut() {
189 return stdout.flushStream();
190 }
191
192 /**
193 * Executes the command in a new process.
194 */
195 public void go() {
196 Runtime runtime = Runtime.getRuntime();
197 try {
198 Process process = runtime.exec(command);
199 stdout = new StreamReader(process.getInputStream());
200 stderr = new StreamReader(process.getErrorStream());
201 stdout.start();
202 stderr.start();
203 if (wait) exitStatus = process.waitFor();
204 } catch (Exception ex) {
205 exitStatus = -999;
206 if (handleExceptions) ex.printStackTrace();
207 }
208 }
209
210 /**
211 * Executes this class with the given commands in separate processes.
212 * @param args command line arguments
213 */
214 public static void main(String[] args) {
215 for (int i = 0; i < args.length; i++) {
216 String cmd = args[i];
217 try {
218 SmartProcess sp = new SmartProcess(cmd);
219 sp.go();
220 System.out.println("exit=" + sp.getExitStatus());
221 System.out.println("stdout:" + sp.getStandardOut());
222 System.out.println("stderr:" + sp.getStandardError());
223 } catch (Exception ex) {
224 ex.printStackTrace();
225 System.exit(-1);
226 }
227 }
228 }
229
230 /**
231 * This class handles reading the standard out and standard error streams.
232 */
233 private class StreamReader extends Thread {
234
235 /**
236 * The Reader that this StreamReader will read from.
237 */
238 private BufferedReader inputReader;
239
240 /**
241 * A StringBuffer that holds the contents of the stream.
242 */
243 private StringBuffer data = new StringBuffer();
244
245 /**
246 * Creates a new SreamReader object using the given InputStream.
247 * @param inputStream the InputStream to read
248 */
249 public StreamReader(InputStream inputStream) {
250 data = new StringBuffer();
251 inputReader = new BufferedReader(new InputStreamReader(inputStream));
252 data.setLength(0);
253 }
254
255 /**
256 * Returns the contents of the stream.
257 * @return the contents of the stream
258 */
259 public synchronized String getStream(boolean flush) {
260 String result = "";
261 result = data.toString();
262 if (flush) data.setLength(0);
263 return result;
264 }
265
266 /**
267 * Executes the reader thread.
268 */
269 public synchronized void run() {
270 String line;
271 try {
272 while ((line = inputReader.readLine()) != null)
273 data.append(line).append("\n");
274 } catch (IOException ex) {
275 if (handleExceptions)
276 ex.printStackTrace();
277 }
278 }
279
280 /**
281 * Returns the contents of the stream and flushes it.
282 * @return the contents of the stream
283 */
284 public String flushStream() {
285 return getStream(true);
286 }
287 }
288 }