KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > celtix > common > commands > ForkedCommand


1 package org.objectweb.celtix.common.commands;
2
3 import java.io.*;
4 import java.util.StringTokenizer JavaDoc;
5 import java.util.logging.Level JavaDoc;
6 import java.util.logging.Logger JavaDoc;
7
8 import org.objectweb.celtix.common.i18n.Message;
9
10
11 public class ForkedCommand extends Thread JavaDoc {
12     public static final String JavaDoc EXE_SUFFIX;
13     public static final int DEFAULT_TIMEOUT = 0;
14     private static final Logger JavaDoc LOG = Logger.getLogger(ForkedCommand.class.getName());
15     private String JavaDoc[] arguments;
16     private String JavaDoc[] environment;
17     private PrintStream outputStream;
18     private PrintStream errorStream;
19     private java.lang.Process JavaDoc proc;
20     private boolean completed;
21     private boolean killed;
22     private boolean joinErrOut = true;
23
24     static {
25         if (System.getProperty("os.name").startsWith("Windows")) {
26             EXE_SUFFIX = ".exe";
27         } else {
28             EXE_SUFFIX = "";
29         }
30     }
31     public ForkedCommand() {
32     }
33
34     public ForkedCommand(String JavaDoc[] args) {
35         arguments = args;
36     }
37
38     protected void setArgs(String JavaDoc[] args) {
39         arguments = args;
40     }
41
42     public void setEnvironment(String JavaDoc[] env) {
43         environment = env;
44     }
45
46     public String JavaDoc toString() {
47         if (null == arguments) {
48             return null;
49         }
50         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
51         for (int i = 0; i < arguments.length; i++) {
52             if (i > 0) {
53                 buf.append(" ");
54             }
55             boolean quotesNeeded = false;
56             if (arguments[i] != null) {
57                 StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(arguments[i]);
58                 quotesNeeded = st.countTokens() > 1;
59             }
60             if (quotesNeeded) {
61                 buf.append("\"");
62             }
63             buf.append(arguments[i]);
64             if (quotesNeeded) {
65                 buf.append("\"");
66             }
67         }
68         return buf.length() > 0 ? buf.toString() : "";
69     }
70
71     /**
72      * Determines if the threads collecting the forked process' stdout/stderr
73      * should be joined.
74      *
75      * @param flag boolean indicating if threads should be joined
76      */

77     public void joinErrOut(boolean flag) {
78         this.joinErrOut = flag;
79     }
80
81     public int execute() {
82         return execute(DEFAULT_TIMEOUT);
83     }
84
85     /**
86      * Executes the process. If the process has not completed after the
87      * specified amount of seconds, it is killed.
88      *
89      * @param timeout the timeout in seconds
90      * @throws ForkedCommandException if process execution fails for some reason
91      * or if the timeout has expired and the process was killed
92      */

93     public int execute(int timeout) {
94         if (null == arguments || arguments.length == 0) {
95             throw new ForkedCommandException(new Message("NO_ARGUMENTS_EXC", LOG));
96         }
97         if (LOG.isLoggable(Level.FINE)) {
98             LOG.fine("Executing command: " + this);
99         }
100         try {
101             Runtime JavaDoc rt = Runtime.getRuntime();
102             if (environment == null) {
103                 proc = rt.exec(arguments);
104             } else {
105                 StringBuffer JavaDoc msg = null;
106                 if (LOG.isLoggable(Level.FINE)) {
107                     msg = new StringBuffer JavaDoc();
108                     msg.append("Process environment: ");
109
110                     for (int i = 0; i < environment.length; i++) {
111                         msg.append(environment[i]);
112                         msg.append(" ");
113                     }
114                     LOG.fine(msg.toString());
115                 }
116
117                 proc = rt.exec(arguments, environment);
118             }
119         } catch (IOException ex) {
120             throw new ForkedCommandException(new Message("EXECUTE_EXC", LOG, this), ex);
121         }
122
123         // catch process stderr/stdout
124
ForkedCommandStreamHandler cmdOut = new ForkedCommandStreamHandler(proc.getInputStream(),
125                                                                            outputStream == null
126                                                                                ? System.out : outputStream);
127         ForkedCommandStreamHandler cmdErr = new ForkedCommandStreamHandler(proc.getErrorStream(),
128                                                                            errorStream == null
129                                                                                ? System.err : errorStream);
130         cmdErr.start();
131         cmdOut.start();
132
133         // now wait for the process on our own thread
134
start();
135
136         // kill process after timeout
137
try {
138             if (timeout > 0) {
139                 if (LOG.isLoggable(Level.FINE)) {
140                     LOG.fine("Waiting " + timeout + " seconds for process to complete");
141                 }
142                 join(timeout * 1000);
143             } else {
144                 if (LOG.isLoggable(Level.FINE)) {
145                     LOG.fine("Waiting for process to complete");
146                 }
147                 join();
148             }
149         } catch (InterruptedException JavaDoc ex) {
150             ex.printStackTrace();
151         } finally {
152             if (completed) {
153                 if (LOG.isLoggable(Level.FINE)) {
154                     LOG.fine("Process completed in time");
155                 }
156             } else {
157                 proc.destroy();
158                 killed = true;
159                 LOG.fine("Process timed out and was killed");
160             }
161
162             // wait for the streams threads to finish if necessary
163
if (joinErrOut) {
164                 if (LOG.isLoggable(Level.FINE)) {
165                     LOG.info("Waiting a further 10 seconds for process "
166                                  + " stdout/stderr streams to be flushed");
167                 }
168                 try {
169                     cmdErr.join(10 * 1000);
170                     cmdOut.join(10 * 1000);
171                 } catch (InterruptedException JavaDoc ex) {
172                     // silently ignore
173
}
174             }
175         }
176
177         if (killed) {
178             throw new ForkedCommandException(new Message("TIMEOUT_EXC", LOG, timeout));
179         }
180         int exitVal = proc.exitValue();
181         if (LOG.isLoggable(Level.FINE)) {
182             LOG.fine("Process exited with value: " + exitVal);
183         }
184
185         return exitVal;
186     }
187
188     /**
189      * Implements the run method for the thread on which the process is
190      * executed.
191      */

192     public void run() {
193         try {
194             proc.waitFor();
195             completed = true;
196         } catch (InterruptedException JavaDoc ex) {
197             // ignore this one
198
ex.printStackTrace();
199         }
200     }
201
202     public void setOutputStream(PrintStream os) {
203         outputStream = os;
204     }
205
206     public void setErrorStream(PrintStream es) {
207         errorStream = es;
208     }
209 }
210
211 class ForkedCommandStreamHandler extends Thread JavaDoc {
212
213     private final InputStream is;
214     private final PrintStream ps;
215
216     ForkedCommandStreamHandler(InputStream i, PrintStream p) {
217         is = i;
218         ps = p;
219     }
220
221     public void run() {
222         try {
223             InputStreamReader isr = new InputStreamReader(is);
224             BufferedReader br = new BufferedReader(isr);
225             String JavaDoc line = br.readLine();
226             while (line != null) {
227                 ps.println(line);
228                 line = br.readLine();
229             }
230         } catch (IOException ioe) {
231             // ignore
232
}
233     }
234 }
235
Popular Tags