KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > Ostermiller > util > ExecHelper


1 /*
2  * Convenience methods for executing non-Java processes.
3  * Copyright (C) 2005 Stephen Ostermiller
4  * http://ostermiller.org/contact.pl?regarding=Java+Utilities
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * See COPYING.TXT for details.
17  */

18
19 package com.Ostermiller.util;
20
21 import java.io.*;
22
23 /**
24  * Convenience methods for executing non-Java processes.
25  * More information about this class is available from <a target="_top" HREF=
26  * "http://ostermiller.org/utils/ExecHelper.html">ostermiller.org</a>.
27  *
28  * @author Stephen Ostermiller http://ostermiller.org/contact.pl?regarding=Java+Utilities
29  * @since ostermillerutils 1.06.00
30  */

31 public final class ExecHelper {
32
33     /**
34      * Executes the specified command and arguments in a separate process, and waits for the
35      * process to finish.
36      * <p>
37      * Output from the process is expected to be text in the system's default character set.
38      * <p>
39      * No input is passed to the process on STDIN.
40      *
41      * @param cmdarray array containing the command to call and its arguments.
42      * @return The results of the execution in an ExecHelper object.
43      * @throws SecurityException if a security manager exists and its checkExec method doesn't allow creation of a subprocess.
44      * @throws IOException - if an I/O error occurs
45      * @throws NullPointerException - if cmdarray is null
46      * @throws IndexOutOfBoundsException - if cmdarray is an empty array (has length 0).
47      *
48      * @since ostermillerutils 1.06.00
49      */

50     public static ExecHelper exec(String JavaDoc[] cmdarray) throws IOException {
51         return new ExecHelper(Runtime.getRuntime().exec(cmdarray), null);
52     }
53
54     /**
55      * Executes the specified command and arguments in a separate process, and waits for the
56      * process to finish.
57      * <p>
58      * Output from the process is expected to be text in the system's default character set.
59      * <p>
60      * No input is passed to the process on STDIN.
61      *
62      * @param cmdarray array containing the command to call and its arguments.
63      * @param envp array of strings, each element of which has environment variable settings in format name=value.
64      * @return The results of the execution in an ExecHelper object.
65      * @throws SecurityException if a security manager exists and its checkExec method doesn't allow creation of a subprocess.
66      * @throws IOException - if an I/O error occurs
67      * @throws NullPointerException - if cmdarray is null
68      * @throws IndexOutOfBoundsException - if cmdarray is an empty array (has length 0).
69      *
70      * @since ostermillerutils 1.06.00
71      */

72     public static ExecHelper exec(String JavaDoc[] cmdarray, String JavaDoc[] envp) throws IOException {
73         return new ExecHelper(Runtime.getRuntime().exec(cmdarray, envp), null);
74     }
75
76     /**
77      * Executes the specified command and arguments in a separate process, and waits for the
78      * process to finish.
79      * <p>
80      * Output from the process is expected to be text in the system's default character set.
81      * <p>
82      * No input is passed to the process on STDIN.
83      *
84      * @param cmdarray array containing the command to call and its arguments.
85      * @param envp array of strings, each element of which has environment variable settings in format name=value.
86      * @param dir the working directory of the subprocess, or null if the subprocess should inherit the working directory of the current process.
87      * @return The results of the execution in an ExecHelper object.
88      * @throws SecurityException if a security manager exists and its checkExec method doesn't allow creation of a subprocess.
89      * @throws IOException - if an I/O error occurs
90      * @throws NullPointerException - if cmdarray is null
91      * @throws IndexOutOfBoundsException - if cmdarray is an empty array (has length 0).
92      *
93      * @since ostermillerutils 1.06.00
94      */

95     public static ExecHelper exec(String JavaDoc[] cmdarray, String JavaDoc[] envp, File dir) throws IOException {
96         return new ExecHelper(Runtime.getRuntime().exec(cmdarray, envp), null);
97     }
98
99     /**
100      * Executes the specified command and arguments in a separate process, and waits for the
101      * process to finish.
102      * <p>
103      * No input is passed to the process on STDIN.
104      *
105      * @param cmdarray array containing the command to call and its arguments.
106      * @param charset Output from the executed command is expected to be in this character set.
107      * @return The results of the execution in an ExecHelper object.
108      * @throws SecurityException if a security manager exists and its checkExec method doesn't allow creation of a subprocess.
109      * @throws IOException - if an I/O error occurs
110      * @throws NullPointerException - if cmdarray is null
111      * @throws IndexOutOfBoundsException - if cmdarray is an empty array (has length 0).
112      *
113      * @since ostermillerutils 1.06.00
114      */

115     public static ExecHelper exec(String JavaDoc[] cmdarray, String JavaDoc charset) throws IOException {
116         return new ExecHelper(Runtime.getRuntime().exec(cmdarray), charset);
117     }
118
119     /**
120      * Executes the specified command and arguments in a separate process, and waits for the
121      * process to finish.
122      * <p>
123      * No input is passed to the process on STDIN.
124      *
125      * @param cmdarray array containing the command to call and its arguments.
126      * @param envp array of strings, each element of which has environment variable settings in format name=value.
127      * @param charset Output from the executed command is expected to be in this character set.
128      * @return The results of the execution in an ExecHelper object.
129      * @throws SecurityException if a security manager exists and its checkExec method doesn't allow creation of a subprocess.
130      * @throws IOException - if an I/O error occurs
131      * @throws NullPointerException - if cmdarray is null
132      * @throws IndexOutOfBoundsException - if cmdarray is an empty array (has length 0).
133      *
134      * @since ostermillerutils 1.06.00
135      */

136     public static ExecHelper exec(String JavaDoc[] cmdarray, String JavaDoc[] envp, String JavaDoc charset) throws IOException {
137         return new ExecHelper(Runtime.getRuntime().exec(cmdarray, envp), charset);
138     }
139
140     /**
141      * Executes the specified command and arguments in a separate process, and waits for the
142      * process to finish.
143      * <p>
144      * No input is passed to the process on STDIN.
145      *
146      * @param cmdarray array containing the command to call and its arguments.
147      * @param envp array of strings, each element of which has environment variable settings in format name=value.
148      * @param dir the working directory of the subprocess, or null if the subprocess should inherit the working directory of the current process.
149      * @param charset Output from the executed command is expected to be in this character set.
150      * @return The results of the execution in an ExecHelper object.
151      * @throws SecurityException if a security manager exists and its checkExec method doesn't allow creation of a subprocess.
152      * @throws IOException - if an I/O error occurs
153      * @throws NullPointerException - if cmdarray is null
154      * @throws IndexOutOfBoundsException - if cmdarray is an empty array (has length 0).
155      *
156      * @since ostermillerutils 1.06.00
157      */

158     public static ExecHelper exec(String JavaDoc[] cmdarray, String JavaDoc[] envp, File dir, String JavaDoc charset) throws IOException {
159         return new ExecHelper(Runtime.getRuntime().exec(cmdarray, envp), charset);
160     }
161
162     /**
163      * Executes the specified command using a shell. On windows uses cmd.exe or command.exe.
164      * On other platforms it uses /bin/sh.
165      * <p>
166      * A shell should be used to execute commands when features such as file redirection, pipes,
167      * argument parsing are desired.
168      * <p>
169      * Output from the process is expected to be text in the system's default character set.
170      * <p>
171      * No input is passed to the process on STDIN.
172      *
173      * @param command String containing a command to be parsed by the shell and executed.
174      * @return The results of the execution in an ExecHelper object.
175      * @throws SecurityException if a security manager exists and its checkExec method doesn't allow creation of a subprocess.
176      * @throws IOException - if an I/O error occurs
177      * @throws NullPointerException - if command is null
178      *
179      * @since ostermillerutils 1.06.00
180      */

181     public static ExecHelper execUsingShell(String JavaDoc command) throws IOException {
182         return execUsingShell(command, null);
183     }
184
185     /**
186      * Executes the specified command using a shell. On windows uses cmd.exe or command.exe.
187      * On other platforms it uses /bin/sh.
188      * <p>
189      * A shell should be used to execute commands when features such as file redirection, pipes,
190      * argument parsing are desired.
191      * <p>
192      * No input is passed to the process on STDIN.
193      *
194      * @param command String containing a command to be parsed by the shell and executed.
195      * @param charset Output from the executed command is expected to be in this character set.
196      * @return The results of the execution in an ExecHelper object.
197      * @throws SecurityException if a security manager exists and its checkExec method doesn't allow creation of a subprocess.
198      * @throws IOException - if an I/O error occurs
199      * @throws NullPointerException - if command is null
200      *
201      * @since ostermillerutils 1.06.00
202      */

203     public static ExecHelper execUsingShell(String JavaDoc command, String JavaDoc charset) throws IOException {
204         if (command == null) throw new NullPointerException JavaDoc();
205         String JavaDoc[] cmdarray;
206         String JavaDoc os = System.getProperty("os.name");
207         if (os.equals("Windows 95") || os.equals("Windows 98") || os.equals("Windows ME")){
208             cmdarray = new String JavaDoc[]{"command.exe", "/C", command};
209         } else if (os.startsWith("Windows")){
210             cmdarray = new String JavaDoc[]{"cmd.exe", "/C", command};
211         } else {
212             cmdarray = new String JavaDoc[]{"/bin/sh", "-c", command};
213         }
214         return new ExecHelper(Runtime.getRuntime().exec(cmdarray), charset);
215     }
216
217     /**
218      * Take a process, record its standard error and standard out streams, wait for it to finish
219      *
220      * @param process process to watch
221      * @throws SecurityException if a security manager exists and its checkExec method doesn't allow creation of a subprocess.
222      * @throws IOException - if an I/O error occurs
223      * @throws NullPointerException - if cmdarray is null
224      * @throws IndexOutOfBoundsException - if cmdarray is an empty array (has length 0).
225      *
226      * @since ostermillerutils 1.06.00
227      */

228     private ExecHelper(Process JavaDoc process, String JavaDoc charset) throws IOException {
229         StringBuffer JavaDoc output = new StringBuffer JavaDoc();
230         StringBuffer JavaDoc error = new StringBuffer JavaDoc();
231
232         Reader stdout;
233         Reader stderr;
234
235         if (charset == null){
236             // This is one time that the system charset is appropriate,
237
// don't specify a character set.
238
stdout = new InputStreamReader(process.getInputStream());
239             stderr = new InputStreamReader(process.getErrorStream());
240         } else {
241             stdout = new InputStreamReader(process.getInputStream(), charset);
242             stderr = new InputStreamReader(process.getErrorStream(), charset);
243         }
244         char[] buffer = new char[1024];
245
246         boolean done = false;
247         boolean stdoutclosed = false;
248         boolean stderrclosed = false;
249         while (!done){
250             boolean readSomething = false;
251             // read from the process's standard output
252
if (!stdoutclosed && stdout.ready()){
253                 readSomething = true;
254                 int read = stdout.read(buffer, 0, buffer.length);
255                 if (read < 0){
256                     readSomething = true;
257                     stdoutclosed = true;
258                 } else if (read > 0){
259                     readSomething = true;
260                     output.append(buffer, 0, read);
261                 }
262             }
263             // read from the process's standard error
264
if (!stderrclosed && stderr.ready()){
265                 int read = stderr.read(buffer, 0, buffer.length);
266                 if (read < 0){
267                     readSomething = true;
268                     stderrclosed = true;
269                 } else if (read > 0){
270                     readSomething = true;
271                     error.append(buffer, 0, read);
272                 }
273             }
274             // Check the exit status only we haven't read anything,
275
// if something has been read, the process is obviously not dead yet.
276
if (!readSomething){
277                 try {
278                     this.status = process.exitValue();
279                     done = true;
280                 } catch (IllegalThreadStateException JavaDoc itx){
281                     // Exit status not ready yet.
282
// Give the process a little breathing room.
283
try {
284                         Thread.sleep(100);
285                     } catch (InterruptedException JavaDoc ix){
286                         process.destroy();
287                         throw new IOException("Interrupted - processes killed");
288                     }
289                 }
290             }
291         }
292
293         this.output = output.toString();
294         this.error = error.toString();
295     }
296
297     /**
298      * The output of the job that ran.
299      *
300      * @since ostermillerutils 1.06.00
301      */

302     private String JavaDoc output;
303
304     /**
305      * Get the output of the job that ran.
306      *
307      * @return Everything the executed process wrote to its standard output as a String.
308      *
309      * @since ostermillerutils 1.06.00
310      */

311     public String JavaDoc getOutput(){
312         return output;
313     }
314
315     /**
316      * The error output of the job that ran.
317      *
318      * @since ostermillerutils 1.06.00
319      */

320     private String JavaDoc error;
321
322     /**
323      * Get the error output of the job that ran.
324      *
325      * @return Everything the executed process wrote to its standard error as a String.
326      *
327      * @since ostermillerutils 1.06.00
328      */

329     public String JavaDoc getError(){
330         return error;
331     }
332
333     /**
334      * The status of the job that ran.
335      *
336      * @since ostermillerutils 1.06.00
337      */

338     private int status;
339
340     /**
341      * Get the status of the job that ran.
342      *
343      * @return exit status of the executed process, by convention, the value 0 indicates normal termination.
344      *
345      * @since ostermillerutils 1.06.00
346      */

347     public int getStatus(){
348         return status;
349     }
350 }
351
Popular Tags