1*ef39d40dSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*ef39d40dSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*ef39d40dSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*ef39d40dSAndrew Rist  * distributed with this work for additional information
6*ef39d40dSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*ef39d40dSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*ef39d40dSAndrew Rist  * "License"); you may not use this file except in compliance
9*ef39d40dSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*ef39d40dSAndrew Rist  *
11*ef39d40dSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*ef39d40dSAndrew Rist  *
13*ef39d40dSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*ef39d40dSAndrew Rist  * software distributed under the License is distributed on an
15*ef39d40dSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*ef39d40dSAndrew Rist  * KIND, either express or implied.  See the License for the
17*ef39d40dSAndrew Rist  * specific language governing permissions and limitations
18*ef39d40dSAndrew Rist  * under the License.
19*ef39d40dSAndrew Rist  *
20*ef39d40dSAndrew Rist  *************************************************************/
21*ef39d40dSAndrew Rist 
22*ef39d40dSAndrew Rist 
23cdf0e10cSrcweir package helper;
24cdf0e10cSrcweir 
25cdf0e10cSrcweir import java.io.BufferedReader;
26cdf0e10cSrcweir import java.io.InputStream;
27cdf0e10cSrcweir import java.io.File;
28cdf0e10cSrcweir import java.io.PrintWriter;
29cdf0e10cSrcweir import java.io.PrintStream;
30cdf0e10cSrcweir import java.io.LineNumberReader;
31cdf0e10cSrcweir import java.io.InputStreamReader;
32cdf0e10cSrcweir import java.io.OutputStreamWriter;
33cdf0e10cSrcweir import java.io.Writer;
34cdf0e10cSrcweir import java.util.Calendar;
35cdf0e10cSrcweir import java.util.Date;
36cdf0e10cSrcweir import java.util.GregorianCalendar;
37cdf0e10cSrcweir import lib.TestParameters;
38cdf0e10cSrcweir import share.LogWriter;
39cdf0e10cSrcweir import util.PropertyName;
40cdf0e10cSrcweir import util.utils;
41cdf0e10cSrcweir 
42cdf0e10cSrcweir /**
43cdf0e10cSrcweir  * Class collect information from input stream in
44cdf0e10cSrcweir  * background (sparate thread) and outputs it to
45cdf0e10cSrcweir  * some log stream. I helps to avoid buffer overflow
46cdf0e10cSrcweir  * when output stream has small buffer size (e.g.
47cdf0e10cSrcweir  * in case when handling stdout from external
48cdf0e10cSrcweir  * <code>Process</code>)
49cdf0e10cSrcweir  *
50cdf0e10cSrcweir  * This class is currently used by ProcesHandler
51cdf0e10cSrcweir  * internally only.
52cdf0e10cSrcweir  */
53cdf0e10cSrcweir class Pump extends Thread
54cdf0e10cSrcweir {
55cdf0e10cSrcweir 
56cdf0e10cSrcweir     private LineNumberReader reader;
57cdf0e10cSrcweir     private String pref;
58cdf0e10cSrcweir     private StringBuffer buf = new StringBuffer(256);
59cdf0e10cSrcweir     private PrintWriter log;
60cdf0e10cSrcweir     private boolean bOutput;
61cdf0e10cSrcweir 
62cdf0e10cSrcweir     /**
63cdf0e10cSrcweir      * Creates Pump for specified <code>InputStream</code>.
64cdf0e10cSrcweir      * This Pump also synchronously output text read to
65cdf0e10cSrcweir      * log by prefixed lines. Constructor immediately
66cdf0e10cSrcweir      * starts reading in a separate thread.
67cdf0e10cSrcweir      *
68cdf0e10cSrcweir      * @param is Stream which requires permanent reading.
69cdf0e10cSrcweir      * @param log Writer where prefixed text lines to be output
70cdf0e10cSrcweir      * @param outPrefix A prefix which is printed at the
71cdf0e10cSrcweir      *   beginning of each output line.
72cdf0e10cSrcweir      */
Pump(InputStream is, PrintWriter log, String outPrefix, boolean _bOutput)73cdf0e10cSrcweir     public Pump(InputStream is, PrintWriter log, String outPrefix, boolean _bOutput)
74cdf0e10cSrcweir     {
75cdf0e10cSrcweir         this.pref = (outPrefix == null) ? "" : outPrefix;
76cdf0e10cSrcweir         reader = new LineNumberReader(new InputStreamReader(is));
77cdf0e10cSrcweir         this.log = log;
78cdf0e10cSrcweir         this.bOutput = _bOutput;
79cdf0e10cSrcweir         start();
80cdf0e10cSrcweir     }
81cdf0e10cSrcweir 
run()82cdf0e10cSrcweir     public void run()
83cdf0e10cSrcweir     {
84cdf0e10cSrcweir         try
85cdf0e10cSrcweir         {
86cdf0e10cSrcweir             String line = reader.readLine();
87cdf0e10cSrcweir             while (line != null)
88cdf0e10cSrcweir             {
89cdf0e10cSrcweir                 if (bOutput)
90cdf0e10cSrcweir                 {
91cdf0e10cSrcweir                     log.println(pref + line);
92cdf0e10cSrcweir                     log.flush();
93cdf0e10cSrcweir                 }
94cdf0e10cSrcweir                 buf.append(line).append('\n');
95cdf0e10cSrcweir                 line = reader.readLine();
96cdf0e10cSrcweir             }
97cdf0e10cSrcweir         }
98cdf0e10cSrcweir         catch (java.io.IOException e)
99cdf0e10cSrcweir         {
100cdf0e10cSrcweir             log.println(pref + "Exception occured: " + e);
101cdf0e10cSrcweir         }
102cdf0e10cSrcweir     }
103cdf0e10cSrcweir 
104cdf0e10cSrcweir     /**
105cdf0e10cSrcweir      * Returns the text collected from input stream.
106cdf0e10cSrcweir      */
getStringBuffer()107cdf0e10cSrcweir     public String getStringBuffer()
108cdf0e10cSrcweir     {
109cdf0e10cSrcweir         return buf.toString();
110cdf0e10cSrcweir     }
111cdf0e10cSrcweir }
112cdf0e10cSrcweir 
113cdf0e10cSrcweir /**
114cdf0e10cSrcweir  * Class provides convenient way for running external program
115cdf0e10cSrcweir  * handle its standard streams, control execution and check results.
116cdf0e10cSrcweir  * Instance of this class must be created only for a single
117cdf0e10cSrcweir  * execution. If you need to execute the same command again you
118cdf0e10cSrcweir  * should create a new instance for this.
119cdf0e10cSrcweir  */
120cdf0e10cSrcweir public class ProcessHandler
121cdf0e10cSrcweir {
122cdf0e10cSrcweir 
123cdf0e10cSrcweir     private String cmdLine;
124cdf0e10cSrcweir     private String[] cmdLineArray;
125cdf0e10cSrcweir     private String[] envVars = null;
126cdf0e10cSrcweir     private File workDir = null;
127cdf0e10cSrcweir     private PrintWriter log;
128cdf0e10cSrcweir     private int exitValue = -1;
129cdf0e10cSrcweir     private boolean isFinished = false;
130cdf0e10cSrcweir     private boolean isStarted = false;
131cdf0e10cSrcweir     private boolean mbTimedOut = false;
132cdf0e10cSrcweir     private long mTimeOut = 0;
133cdf0e10cSrcweir     private String stdInBuff = "";
134cdf0e10cSrcweir     private Pump stdout = null;
135cdf0e10cSrcweir     private Pump stderr = null;
136cdf0e10cSrcweir     private PrintStream stdIn = null;
137cdf0e10cSrcweir     private Process m_aProcess = null;
138cdf0e10cSrcweir     private TestParameters param = null;
139cdf0e10cSrcweir     private boolean debug = false;
140cdf0e10cSrcweir     private boolean bUseOutput = true;
141cdf0e10cSrcweir 
142cdf0e10cSrcweir     private int m_nProcessTimeout = 0;
143cdf0e10cSrcweir     private String m_sProcessKiller;
144cdf0e10cSrcweir     private ProcessWatcher m_aWatcher;
145cdf0e10cSrcweir 
146cdf0e10cSrcweir     /**
147cdf0e10cSrcweir      * Creates instance with specified external command.
148cdf0e10cSrcweir      * Debug info and output
149cdf0e10cSrcweir      * of external command is printed to stdout.
150cdf0e10cSrcweir      * @param cmdLine
151cdf0e10cSrcweir      */
ProcessHandler(String cmdLine)152cdf0e10cSrcweir     public ProcessHandler(String cmdLine)
153cdf0e10cSrcweir     {
154cdf0e10cSrcweir         this(cmdLine, null, null, null, 0);
155cdf0e10cSrcweir     }
156cdf0e10cSrcweir 
157cdf0e10cSrcweir     /**
158cdf0e10cSrcweir      * Creates instance with specified external command
159cdf0e10cSrcweir      * including parameters as an array.
160cdf0e10cSrcweir      * Debug info and output
161cdf0e10cSrcweir      * of external command is printed to stdout.
162cdf0e10cSrcweir      * @param cmdLines
163cdf0e10cSrcweir      */
ProcessHandler(String[] cmdLines)164cdf0e10cSrcweir     public ProcessHandler(String[] cmdLines)
165cdf0e10cSrcweir     {
166cdf0e10cSrcweir         this(null, null, null, null, 0);
167cdf0e10cSrcweir         cmdLineArray = cmdLines;
168cdf0e10cSrcweir     }
169cdf0e10cSrcweir 
170cdf0e10cSrcweir     /**
171cdf0e10cSrcweir      * Creates instance with specified external command
172cdf0e10cSrcweir      * including parameters as an array, with environment
173cdf0e10cSrcweir      * variables.
174cdf0e10cSrcweir      * Debug info and output
175cdf0e10cSrcweir      * of external command is printed to stdout.
176cdf0e10cSrcweir      * @param cmdLines
177cdf0e10cSrcweir      * @param envVars
178cdf0e10cSrcweir      * @see java.lang.Runtime exec(String[], String[])
179cdf0e10cSrcweir      */
ProcessHandler(String[] cmdLines, String[] envVars)180cdf0e10cSrcweir     public ProcessHandler(String[] cmdLines, String[] envVars)
181cdf0e10cSrcweir     {
182cdf0e10cSrcweir         this(null, null, null, envVars, 0);
183cdf0e10cSrcweir         cmdLineArray = cmdLines;
184cdf0e10cSrcweir     }
185cdf0e10cSrcweir 
186cdf0e10cSrcweir     /**
187cdf0e10cSrcweir      * Creates instance with specified external command
188cdf0e10cSrcweir      * including parameters as an array, with environment
189cdf0e10cSrcweir      * variables. The command will be started in workDir.
190cdf0e10cSrcweir      * Debug info and output
191cdf0e10cSrcweir      * of external command is printed to stdout.
192cdf0e10cSrcweir      * @param cmdLines
193cdf0e10cSrcweir      * @param workDir
194cdf0e10cSrcweir      */
ProcessHandler(String[] cmdLines, File workDir)195cdf0e10cSrcweir     public ProcessHandler(String[] cmdLines, File workDir)
196cdf0e10cSrcweir     {
197cdf0e10cSrcweir         this(null, null, workDir, null, 0);
198cdf0e10cSrcweir         cmdLineArray = cmdLines;
199cdf0e10cSrcweir 
200cdf0e10cSrcweir     }
201cdf0e10cSrcweir 
202cdf0e10cSrcweir     /**
203cdf0e10cSrcweir      * Creates instance with specified external command and
204cdf0e10cSrcweir      * log stream where debug info and output
205cdf0e10cSrcweir      * of external command is printed out.  The command will be started in workDir.
206cdf0e10cSrcweir      * @param cmdLines
207cdf0e10cSrcweir      * @param log
208cdf0e10cSrcweir      * @param workDir
209cdf0e10cSrcweir      */
ProcessHandler(String[] cmdLines, PrintWriter log, File workDir)210cdf0e10cSrcweir     public ProcessHandler(String[] cmdLines, PrintWriter log, File workDir)
211cdf0e10cSrcweir     {
212cdf0e10cSrcweir         this(null, log, workDir, null, 0);
213cdf0e10cSrcweir         cmdLineArray = cmdLines;
214cdf0e10cSrcweir     }
215cdf0e10cSrcweir 
216cdf0e10cSrcweir     /**
217cdf0e10cSrcweir      * Creates instance with specified external command and
218cdf0e10cSrcweir      * log stream where debug info and output
219cdf0e10cSrcweir      * of external command is printed out.
220cdf0e10cSrcweir      * @param cmdLine
221cdf0e10cSrcweir      * @param log
222cdf0e10cSrcweir      */
ProcessHandler(String cmdLine, PrintWriter log)223cdf0e10cSrcweir     public ProcessHandler(String cmdLine, PrintWriter log)
224cdf0e10cSrcweir     {
225cdf0e10cSrcweir         this(cmdLine, log, null, null, 0);
226cdf0e10cSrcweir     }
227cdf0e10cSrcweir 
228cdf0e10cSrcweir     /**
229cdf0e10cSrcweir      * Creates instance with specified external command and set the time out for the command.
230cdf0e10cSrcweir      * @param cmdLine
231cdf0e10cSrcweir      * @param timeOut
232cdf0e10cSrcweir      */
ProcessHandler(String cmdLine, int timeOut)233cdf0e10cSrcweir     public ProcessHandler(String cmdLine, int timeOut)
234cdf0e10cSrcweir     {
235cdf0e10cSrcweir         this(cmdLine, null, null, null, timeOut);
236cdf0e10cSrcweir     }
237cdf0e10cSrcweir 
238cdf0e10cSrcweir     /**
239cdf0e10cSrcweir      * Creates instance with specified external command which
240cdf0e10cSrcweir      * will be executed in the some work directory.
241cdf0e10cSrcweir      * Debug info and output
242cdf0e10cSrcweir      * of external commandis printed to stdout.
243cdf0e10cSrcweir      * @param cmdLine
244cdf0e10cSrcweir      * @param workDir
245cdf0e10cSrcweir      */
ProcessHandler(String cmdLine, File workDir)246cdf0e10cSrcweir     public ProcessHandler(String cmdLine, File workDir)
247cdf0e10cSrcweir     {
248cdf0e10cSrcweir         this(cmdLine, null, workDir, null, 0);
249cdf0e10cSrcweir     }
250cdf0e10cSrcweir 
251cdf0e10cSrcweir     /**
252cdf0e10cSrcweir      * Creates instance with specified external command which
253cdf0e10cSrcweir      * will be executed in the some work directory.
254cdf0e10cSrcweir      * Debug info and output printed in log stream.
255cdf0e10cSrcweir      * @param cmdLine
256cdf0e10cSrcweir      * @param log
257cdf0e10cSrcweir      * @param workDir
258cdf0e10cSrcweir      */
ProcessHandler(String cmdLine, PrintWriter log, File workDir)259cdf0e10cSrcweir     public ProcessHandler(String cmdLine, PrintWriter log, File workDir)
260cdf0e10cSrcweir     {
261cdf0e10cSrcweir         this(cmdLine, log, workDir, null, 0);
262cdf0e10cSrcweir     }
263cdf0e10cSrcweir 
264cdf0e10cSrcweir     /**
265cdf0e10cSrcweir      * Creates instance with specified external command which
266cdf0e10cSrcweir      * will be executed in the some work directory  and
267cdf0e10cSrcweir      * log stream where debug info and output
268cdf0e10cSrcweir      * of external command is printed .
269cdf0e10cSrcweir      * The specified environment variables are set for the new process.
270cdf0e10cSrcweir      * If log stream is null, logging is printed to stdout.
271cdf0e10cSrcweir      * @param cmdLine
272cdf0e10cSrcweir      * @param log
273cdf0e10cSrcweir      * @param workDir
274cdf0e10cSrcweir      * @param envVars
275cdf0e10cSrcweir      */
ProcessHandler(String cmdLine, PrintWriter log, File workDir, String[] envVars)276cdf0e10cSrcweir     public ProcessHandler(String cmdLine, PrintWriter log, File workDir, String[] envVars)
277cdf0e10cSrcweir     {
278cdf0e10cSrcweir         this(cmdLine, log, workDir, envVars, 0);
279cdf0e10cSrcweir     }
280cdf0e10cSrcweir 
281cdf0e10cSrcweir     /**
282cdf0e10cSrcweir      * Creates instance with specified external command which
283cdf0e10cSrcweir      * will be executed in the some work directory  and
284cdf0e10cSrcweir      *
285cdf0e10cSrcweir      * @param cmdLine       the command to be executed
286cdf0e10cSrcweir      * @param log           log stream where debug info and output
287cdf0e10cSrcweir      *                      of external command is printed .
288cdf0e10cSrcweir      * @param workDir       The working directory of the new process
289cdf0e10cSrcweir      * @param envVars       The specified environment variables are
290cdf0e10cSrcweir      *                      set for the new process.
291cdf0e10cSrcweir      *                      If log stream is null, logging is printed to stdout.
292cdf0e10cSrcweir      * @param  timeOut      When started sychronisly, the maximum time the
293cdf0e10cSrcweir      *                      process will live. When the process being destroyed
294cdf0e10cSrcweir      *                      a log will be written out. It can be asked on
295cdf0e10cSrcweir      *                      <code>isTimedOut()</code> if it has been terminated.
296cdf0e10cSrcweir      *
297cdf0e10cSrcweir      *                      timeOut > 0
298cdf0e10cSrcweir      *                      Waits specified time in miliSeconds for
299cdf0e10cSrcweir      *                      process to exit and return its status.
300cdf0e10cSrcweir      *
301cdf0e10cSrcweir      *                      timeOut = 0
302cdf0e10cSrcweir      *                      Waits for the process to end regulary
303cdf0e10cSrcweir      *
304cdf0e10cSrcweir      *                      timeOut < 0
305cdf0e10cSrcweir      *                      Kills the process immediately
306cdf0e10cSrcweir      *
307cdf0e10cSrcweir      *
308cdf0e10cSrcweir      */
ProcessHandler(String cmdLine, PrintWriter log, File workDir, String[] envVars, long timeOut)309cdf0e10cSrcweir     public ProcessHandler(String cmdLine, PrintWriter log, File workDir, String[] envVars, long timeOut)
310cdf0e10cSrcweir     {
311cdf0e10cSrcweir         this.cmdLine = cmdLine;
312cdf0e10cSrcweir         this.workDir = workDir;
313cdf0e10cSrcweir         this.log = log;
314cdf0e10cSrcweir         this.cmdLine = cmdLine;
315cdf0e10cSrcweir         this.envVars = envVars;
316cdf0e10cSrcweir         if (log == null)
317cdf0e10cSrcweir         {
318cdf0e10cSrcweir             this.log = new PrintWriter(new OutputStreamWriter(System.out));
319cdf0e10cSrcweir         }
320cdf0e10cSrcweir         else
321cdf0e10cSrcweir         {
322cdf0e10cSrcweir             this.log = log;
323cdf0e10cSrcweir         }
324cdf0e10cSrcweir         this.mTimeOut = timeOut;
325cdf0e10cSrcweir     }
326cdf0e10cSrcweir 
327cdf0e10cSrcweir     /**
328cdf0e10cSrcweir      * Creates instance with specified external command which
329cdf0e10cSrcweir      * will be executed in the some work directory  and
330cdf0e10cSrcweir      * log stream where debug info and output of external command is printed.
331cdf0e10cSrcweir      * If log stream is null, logging is printed to stdout.
332cdf0e10cSrcweir      * From the <CODE>TestParameters</CODE> the <CODE>OfficeWachter</CODE> get a ping.
333cdf0e10cSrcweir      * @param commands
334cdf0e10cSrcweir      * @param log
335cdf0e10cSrcweir      * @param workDir
336cdf0e10cSrcweir      * @param shortWait If this parameter is ture the <CODE>mTimeOut</CODE> is set to 5000 ms, else it is set to
337cdf0e10cSrcweir      *        half of time out from parameter timeout.
338cdf0e10cSrcweir      * @param param the TestParameters
339cdf0e10cSrcweir      * @see lib.TestParameters
340cdf0e10cSrcweir      * @see helper.OfficeWatcher
341cdf0e10cSrcweir      */
ProcessHandler(String[] commands, PrintWriter log, File workDir, int shortWait, TestParameters param)342cdf0e10cSrcweir     public ProcessHandler(String[] commands, PrintWriter log, File workDir, int shortWait, TestParameters param)
343cdf0e10cSrcweir     {
344cdf0e10cSrcweir         this(null, log, workDir, null, 0);
345cdf0e10cSrcweir         this.cmdLineArray = commands;
346cdf0e10cSrcweir         this.param = param;
347cdf0e10cSrcweir         if (shortWait != 0)
348cdf0e10cSrcweir         {
349cdf0e10cSrcweir             this.mTimeOut = shortWait;
350cdf0e10cSrcweir         }
351cdf0e10cSrcweir         else
352cdf0e10cSrcweir         {
353cdf0e10cSrcweir             this.mTimeOut = (long) (param.getInt(PropertyName.TIME_OUT) / 1.3);
354cdf0e10cSrcweir         }
355cdf0e10cSrcweir         debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
356cdf0e10cSrcweir 
357cdf0e10cSrcweir     }
358cdf0e10cSrcweir 
359cdf0e10cSrcweir     /**
360cdf0e10cSrcweir      * If not equal 0, the time to maximal wait.
361cdf0e10cSrcweir      * @param _n
362cdf0e10cSrcweir      */
setProcessTimeout(int _n)363cdf0e10cSrcweir     public void setProcessTimeout(int _n)
364cdf0e10cSrcweir     {
365cdf0e10cSrcweir         m_nProcessTimeout = _n;
366cdf0e10cSrcweir     }
367cdf0e10cSrcweir 
368cdf0e10cSrcweir     /**
369cdf0e10cSrcweir      * This command will call after ProcessTimeout is arrived.
370cdf0e10cSrcweir      * @param _s
371cdf0e10cSrcweir      */
setProcessKiller(String _s)372cdf0e10cSrcweir     public void setProcessKiller(String _s)
373cdf0e10cSrcweir     {
374cdf0e10cSrcweir         m_sProcessKiller = _s;
375cdf0e10cSrcweir     }
376cdf0e10cSrcweir 
377cdf0e10cSrcweir     /**
378cdf0e10cSrcweir      * This method do an asynchronous execution of the commands. To avoid a interruption on long running processes
379cdf0e10cSrcweir      * caused by <CODE>OfficeWatcher</CODE>, the OfficeWatcher get frequently a ping.
380cdf0e10cSrcweir      * @see helper.OfficeWatcher
381cdf0e10cSrcweir      */
runCommand()382cdf0e10cSrcweir     public void runCommand()
383cdf0e10cSrcweir     {
384cdf0e10cSrcweir 
385cdf0e10cSrcweir         boolean changedText = true;
386cdf0e10cSrcweir         int count = 0;
387cdf0e10cSrcweir         String memText = "";
388cdf0e10cSrcweir 
389cdf0e10cSrcweir         this.executeAsynchronously();
390cdf0e10cSrcweir 
391cdf0e10cSrcweir         OfficeWatcher ow = null;
392cdf0e10cSrcweir         if (param != null)
393cdf0e10cSrcweir         {
394cdf0e10cSrcweir             ow = (OfficeWatcher) param.get(PropertyName.OFFICE_WATCHER);
395cdf0e10cSrcweir         }
396cdf0e10cSrcweir         if (ow != null)
397cdf0e10cSrcweir         {
398cdf0e10cSrcweir             ow.ping();
399cdf0e10cSrcweir         }
400cdf0e10cSrcweir 
401cdf0e10cSrcweir         int hangcheck = 10;
402cdf0e10cSrcweir         while (!this.isFinished() && changedText)
403cdf0e10cSrcweir         {
404cdf0e10cSrcweir             count++;
405cdf0e10cSrcweir             // dbg("runCommand: waiting " + mTimeOut / 1000 + " seconds while command execution is ongoing... " + count);
406cdf0e10cSrcweir             // shortWait(mTimeOut);
407cdf0e10cSrcweir             // shortWait(2000); // wait 2 seconds.
408cdf0e10cSrcweir             //waitFor(mTimeOut);
409cdf0e10cSrcweir             waitFor(2000, false); // wait but don't kill
410cdf0e10cSrcweir 
411cdf0e10cSrcweir             if (ow != null)
412cdf0e10cSrcweir             {
413cdf0e10cSrcweir                 ow.ping();
414cdf0e10cSrcweir             }
415cdf0e10cSrcweir             // check for changes in the output stream. If there are no changes, the process maybe hangs
416cdf0e10cSrcweir             if (!this.isFinished())
417cdf0e10cSrcweir             {
418cdf0e10cSrcweir                 hangcheck--;
419cdf0e10cSrcweir                 if (hangcheck < 0)
420cdf0e10cSrcweir                 {
421cdf0e10cSrcweir                     String sOutputText = getOutputText();
422cdf0e10cSrcweir                     if (sOutputText.length() == memText.length())
423cdf0e10cSrcweir                     {
424cdf0e10cSrcweir                         changedText = false;
425cdf0e10cSrcweir                         // dbg("runCommand Could not detect changes in output stream!!!");
426cdf0e10cSrcweir                     }
427cdf0e10cSrcweir                     hangcheck = 10;
428cdf0e10cSrcweir                     memText = this.getOutputText();
429cdf0e10cSrcweir                 }
430cdf0e10cSrcweir             }
431cdf0e10cSrcweir         }
432cdf0e10cSrcweir 
433cdf0e10cSrcweir         if (!this.isFinished())
434cdf0e10cSrcweir         {
435cdf0e10cSrcweir             dbg("runCommand Process ist not finished but there are no changes in output stream.");
436cdf0e10cSrcweir             this.kill();
437cdf0e10cSrcweir         }
438cdf0e10cSrcweir     }
439cdf0e10cSrcweir 
isTimedOut()440cdf0e10cSrcweir     public boolean isTimedOut()
441cdf0e10cSrcweir     {
442cdf0e10cSrcweir         return mbTimedOut;
443cdf0e10cSrcweir     }
444cdf0e10cSrcweir 
setTimedOut(boolean bTimedOut)445cdf0e10cSrcweir     private void setTimedOut(boolean bTimedOut)
446cdf0e10cSrcweir     {
447cdf0e10cSrcweir         mbTimedOut = bTimedOut;
448cdf0e10cSrcweir     }
449cdf0e10cSrcweir 
450cdf0e10cSrcweir     /**
451cdf0e10cSrcweir      * Executes the command and returns only when the process
452cdf0e10cSrcweir      * exits.
453cdf0e10cSrcweir      *
454cdf0e10cSrcweir      * @return <code>true</code> if process was successfully
455cdf0e10cSrcweir      * started and correcly exits (exit code doesn't affect
456cdf0e10cSrcweir      * to this result).
457cdf0e10cSrcweir      */
executeSynchronously()458cdf0e10cSrcweir     public boolean executeSynchronously()
459cdf0e10cSrcweir     {
460cdf0e10cSrcweir         execute();
461cdf0e10cSrcweir         return waitFor(mTimeOut);
462cdf0e10cSrcweir     }
463cdf0e10cSrcweir 
464cdf0e10cSrcweir     /**
465cdf0e10cSrcweir      * Executes the command immediately returns. The process
466cdf0e10cSrcweir      * remains in running state. Control of its state should
467cdf0e10cSrcweir      * be made by <code>waitFor</code> methods.
468cdf0e10cSrcweir      *
469cdf0e10cSrcweir      * @return <code>true</code> if process was successfully
470cdf0e10cSrcweir      * started.
471cdf0e10cSrcweir      */
executeAsynchronously()472cdf0e10cSrcweir     public boolean executeAsynchronously()
473cdf0e10cSrcweir     {
474cdf0e10cSrcweir         execute();
475cdf0e10cSrcweir         return isStarted();
476cdf0e10cSrcweir     }
477cdf0e10cSrcweir 
kill()478cdf0e10cSrcweir     public synchronized void kill()
479cdf0e10cSrcweir     {
480cdf0e10cSrcweir         if (!isStarted())
481cdf0e10cSrcweir         {
482cdf0e10cSrcweir             return;
483cdf0e10cSrcweir         }
484cdf0e10cSrcweir         boolean exit = false;
485cdf0e10cSrcweir         int counter = 1;
486cdf0e10cSrcweir         while (counter < 3 && !exit)
487cdf0e10cSrcweir         {
488cdf0e10cSrcweir             m_aProcess.destroy();
489cdf0e10cSrcweir 
490cdf0e10cSrcweir             try
491cdf0e10cSrcweir             {
492cdf0e10cSrcweir                 Thread.sleep(1000 * counter); // 5000
493cdf0e10cSrcweir             }
494cdf0e10cSrcweir             catch (java.lang.InterruptedException e)
495cdf0e10cSrcweir             {
496cdf0e10cSrcweir             }
497cdf0e10cSrcweir             try
498cdf0e10cSrcweir             {
499cdf0e10cSrcweir                 final int exit_Value = m_aProcess.exitValue();
500cdf0e10cSrcweir                 if (exit_Value < 1)
501cdf0e10cSrcweir                 {
502cdf0e10cSrcweir                     exit = true;
503cdf0e10cSrcweir                 }
504cdf0e10cSrcweir                 else
505cdf0e10cSrcweir                 {
506cdf0e10cSrcweir                     counter++;
507cdf0e10cSrcweir                 }
508cdf0e10cSrcweir                 dbg("kill: process closed with exit code " + exit_Value);
509cdf0e10cSrcweir             }
510cdf0e10cSrcweir             catch (java.lang.IllegalThreadStateException e)
511cdf0e10cSrcweir             {
512cdf0e10cSrcweir                 if (counter < 3)
513cdf0e10cSrcweir                 {
514cdf0e10cSrcweir                     dbg("kill: Couldn't close process after " + counter + " attempts, trying again");
515cdf0e10cSrcweir                 }
516cdf0e10cSrcweir                 counter++;
517cdf0e10cSrcweir             }
518cdf0e10cSrcweir         }
519cdf0e10cSrcweir         isStarted = false;
520cdf0e10cSrcweir     }
521cdf0e10cSrcweir 
522cdf0e10cSrcweir     /**
523cdf0e10cSrcweir      * Returns the time in seconds since 1st January 1970
524cdf0e10cSrcweir      * @return
525cdf0e10cSrcweir      */
getSystemTime()526cdf0e10cSrcweir     public static long getSystemTime()
527cdf0e10cSrcweir     {
528cdf0e10cSrcweir         // Calendar cal = new GregorianCalendar();
529cdf0e10cSrcweir         // final long nTime = cal.getTimeInMillis();
530cdf0e10cSrcweir         final long nTime = System.currentTimeMillis();
531cdf0e10cSrcweir         return nTime;
532cdf0e10cSrcweir     }
533cdf0e10cSrcweir     private long m_nExactStartTimeInMillisec;
534cdf0e10cSrcweir 
initialExactStartTime()535cdf0e10cSrcweir     private void initialExactStartTime()
536cdf0e10cSrcweir     {
537cdf0e10cSrcweir         m_nExactStartTimeInMillisec = getSystemTime();
538cdf0e10cSrcweir     }
539cdf0e10cSrcweir 
getProcessStartTime()540cdf0e10cSrcweir     public long getProcessStartTime()
541cdf0e10cSrcweir     {
542cdf0e10cSrcweir         return m_nExactStartTimeInMillisec;
543cdf0e10cSrcweir     }
544cdf0e10cSrcweir 
showEnvVars()545cdf0e10cSrcweir     private void showEnvVars()
546cdf0e10cSrcweir     {
547cdf0e10cSrcweir         if (envVars != null)
548cdf0e10cSrcweir         {
549cdf0e10cSrcweir             for (int i = 0; i < envVars.length; i++)
550cdf0e10cSrcweir             {
551cdf0e10cSrcweir                 log.println("env: " + envVars[i]);
552cdf0e10cSrcweir             }
553cdf0e10cSrcweir         }
554cdf0e10cSrcweir         else
555cdf0e10cSrcweir         {
556cdf0e10cSrcweir             log.println("env: null");
557cdf0e10cSrcweir         }
558cdf0e10cSrcweir     }
559cdf0e10cSrcweir 
execute()560cdf0e10cSrcweir     protected void execute()
561cdf0e10cSrcweir     {
562cdf0e10cSrcweir         if (isStarted())
563cdf0e10cSrcweir         {
564cdf0e10cSrcweir             throw new RuntimeException(
565cdf0e10cSrcweir                     "The process handler has already been executed.");
566cdf0e10cSrcweir         }
567cdf0e10cSrcweir         final Runtime runtime = Runtime.getRuntime();
568cdf0e10cSrcweir         try
569cdf0e10cSrcweir         {
570cdf0e10cSrcweir             if (cmdLine == null)
571cdf0e10cSrcweir             {
572cdf0e10cSrcweir                 log.println(utils.getDateTime() + "execute: Starting command from array: ");
573cdf0e10cSrcweir                 for (int i = 0; i < cmdLineArray.length; i++)
574cdf0e10cSrcweir                 {
575cdf0e10cSrcweir                     log.println(cmdLineArray[i]);
576cdf0e10cSrcweir                     // log.print(" ");
577cdf0e10cSrcweir                 }
578cdf0e10cSrcweir                 showEnvVars();
579cdf0e10cSrcweir                 log.println("");
580cdf0e10cSrcweir                 initialExactStartTime();
581cdf0e10cSrcweir                 initializeProcessKiller();
582cdf0e10cSrcweir                 m_aProcess = runtime.exec(cmdLineArray, envVars);
583cdf0e10cSrcweir             }
584cdf0e10cSrcweir             else
585cdf0e10cSrcweir             {
586cdf0e10cSrcweir                 if (workDir != null)
587cdf0e10cSrcweir                 {
588cdf0e10cSrcweir                     log.println(utils.getDateTime() + "execute: Starting command: ");
589cdf0e10cSrcweir                     log.println(cmdLine + " path=" + workDir.getAbsolutePath());
590cdf0e10cSrcweir                     showEnvVars();
591cdf0e10cSrcweir                     m_aProcess = runtime.exec(cmdLine, envVars, workDir);
592cdf0e10cSrcweir                 }
593cdf0e10cSrcweir                 else
594cdf0e10cSrcweir                 {
595cdf0e10cSrcweir                     log.println(utils.getDateTime() + "execute: Starting command: ");
596cdf0e10cSrcweir                     log.println(cmdLine);
597cdf0e10cSrcweir                     showEnvVars();
598cdf0e10cSrcweir                     m_aProcess = runtime.exec(cmdLine, envVars);
599cdf0e10cSrcweir                 }
600cdf0e10cSrcweir             }
601cdf0e10cSrcweir             isStarted = true;
602cdf0e10cSrcweir         }
603cdf0e10cSrcweir         catch (java.io.IOException e)
604cdf0e10cSrcweir         {
605cdf0e10cSrcweir             if (cmdLine == null)
606cdf0e10cSrcweir             {
607cdf0e10cSrcweir                 log.println(utils.getDateTime() + "execute: The command array can't be started: " + e);
608cdf0e10cSrcweir             }
609cdf0e10cSrcweir             else
610cdf0e10cSrcweir             {
611cdf0e10cSrcweir                 log.println(utils.getDateTime() + "execute: The command " + cmdLine + " can't be started: " + e);
612cdf0e10cSrcweir             }
613cdf0e10cSrcweir             return;
614cdf0e10cSrcweir         }
615cdf0e10cSrcweir         dbg("execute: pump io-streams");
616cdf0e10cSrcweir         stdout = new Pump(m_aProcess.getInputStream(), log, "out > ", bUseOutput);
617cdf0e10cSrcweir         stderr = new Pump(m_aProcess.getErrorStream(), log, "err > ", bUseOutput);
618cdf0e10cSrcweir         stdIn = new PrintStream(m_aProcess.getOutputStream());
619cdf0e10cSrcweir 
620cdf0e10cSrcweir         // int nExitValue = m_aProcess.exitValue();
621cdf0e10cSrcweir         // int dummy = 0;
622cdf0e10cSrcweir 
623cdf0e10cSrcweir         dbg("execute: flush io-streams");
624cdf0e10cSrcweir 
625cdf0e10cSrcweir         flushInput();
626cdf0e10cSrcweir     }
627cdf0e10cSrcweir 
628cdf0e10cSrcweir     /**
629cdf0e10cSrcweir      * This method is useful when the process was executed
630cdf0e10cSrcweir      * asynchronously. Waits for process to exit and return
631cdf0e10cSrcweir      * its result.
632cdf0e10cSrcweir      *
633cdf0e10cSrcweir      * @return <code>true</code> if process correctly exited
634cdf0e10cSrcweir      * (exit code doesn't affect to this result).
635cdf0e10cSrcweir      */
waitFor()636cdf0e10cSrcweir     public boolean waitFor()
637cdf0e10cSrcweir     {
638cdf0e10cSrcweir         return waitFor(0);
639cdf0e10cSrcweir     }
640cdf0e10cSrcweir 
641cdf0e10cSrcweir     /**
642cdf0e10cSrcweir      * This method is useful when the process was executed
643cdf0e10cSrcweir      * asynchronously. Waits during specified time for process
644cdf0e10cSrcweir      * to exit and return its status.
645cdf0e10cSrcweir      *
646cdf0e10cSrcweir      * @param timeout      > 0
647cdf0e10cSrcweir      *                      Waits specified time in miliSeconds for
648cdf0e10cSrcweir      *                      process to exit and return its status.
649cdf0e10cSrcweir      *
650cdf0e10cSrcweir      *                      = 0
651cdf0e10cSrcweir      *                      Waits for the process to end regulary
652cdf0e10cSrcweir      *
653cdf0e10cSrcweir      *                      < 0
654cdf0e10cSrcweir      *                      Kills the process immediately
655cdf0e10cSrcweir      *
656cdf0e10cSrcweir      * @return <code>true</code> if process correctly exited
657cdf0e10cSrcweir      * (exit code doesn't affect to this result).
658cdf0e10cSrcweir      */
waitFor(long timeout)659cdf0e10cSrcweir     public boolean waitFor(long timeout)
660cdf0e10cSrcweir     {
661cdf0e10cSrcweir         return waitFor(timeout, true);
662cdf0e10cSrcweir     }
663cdf0e10cSrcweir 
waitFor(long timeout, boolean bKillProcessAfterTimeout)664cdf0e10cSrcweir     private boolean waitFor(long timeout, boolean bKillProcessAfterTimeout)
665cdf0e10cSrcweir     {
666cdf0e10cSrcweir         if (isFinished())
667cdf0e10cSrcweir         {
668cdf0e10cSrcweir             return true;
669cdf0e10cSrcweir         }
670cdf0e10cSrcweir         if (!isStarted())
671cdf0e10cSrcweir         {
672cdf0e10cSrcweir             return false;
673cdf0e10cSrcweir         }
674cdf0e10cSrcweir 
675cdf0e10cSrcweir         if (timeout == 0)
676cdf0e10cSrcweir         {
677cdf0e10cSrcweir             try
678cdf0e10cSrcweir             {
679cdf0e10cSrcweir                 m_aProcess.waitFor();
680cdf0e10cSrcweir             }
681cdf0e10cSrcweir             catch (InterruptedException e)
682cdf0e10cSrcweir             {
683cdf0e10cSrcweir                 log.println("The process was interrupted: " + e);
684cdf0e10cSrcweir             }
685cdf0e10cSrcweir             isFinished = true;
686cdf0e10cSrcweir             try
687cdf0e10cSrcweir             {
688cdf0e10cSrcweir                 exitValue = m_aProcess.exitValue();
689cdf0e10cSrcweir             }
690cdf0e10cSrcweir             catch (IllegalThreadStateException e)
691cdf0e10cSrcweir             {
692cdf0e10cSrcweir             }
693cdf0e10cSrcweir         }
694cdf0e10cSrcweir         else
695cdf0e10cSrcweir         {
696cdf0e10cSrcweir             try
697cdf0e10cSrcweir             {
698cdf0e10cSrcweir                 while (!isFinished && timeout > 0)
699cdf0e10cSrcweir                 {
700cdf0e10cSrcweir                     isFinished = true;
701cdf0e10cSrcweir                     Thread.sleep(1000);
702cdf0e10cSrcweir                     timeout -= 1000;
703cdf0e10cSrcweir                     try
704cdf0e10cSrcweir                     {
705cdf0e10cSrcweir                         exitValue = m_aProcess.exitValue(); // throws exception if not finished
706cdf0e10cSrcweir                     }
707cdf0e10cSrcweir                     catch (IllegalThreadStateException e)
708cdf0e10cSrcweir                     {
709cdf0e10cSrcweir                         isFinished = false;
710cdf0e10cSrcweir                     }
711cdf0e10cSrcweir                 }
712cdf0e10cSrcweir                 if (timeout < 0)
713cdf0e10cSrcweir                 {
714cdf0e10cSrcweir                     setTimedOut(true);
715cdf0e10cSrcweir                     log.println("The process has timed out!");
716cdf0e10cSrcweir                 }
717cdf0e10cSrcweir             }
718cdf0e10cSrcweir             catch (InterruptedException ex)
719cdf0e10cSrcweir             {
720cdf0e10cSrcweir                 log.println("The process was interrupted: " + ex);
721cdf0e10cSrcweir             }
722cdf0e10cSrcweir         }
723cdf0e10cSrcweir 
724cdf0e10cSrcweir         if (bKillProcessAfterTimeout == true)
725cdf0e10cSrcweir         {
726cdf0e10cSrcweir             if (!isFinished)
727cdf0e10cSrcweir             {
728cdf0e10cSrcweir                 log.println("Going to destroy the process!!");
729cdf0e10cSrcweir                 m_aProcess.destroy();
730cdf0e10cSrcweir                 log.println("Process has been destroyed!");
731cdf0e10cSrcweir             }
732cdf0e10cSrcweir         }
733cdf0e10cSrcweir //  Removed as hung up in SDK test 'PathSettings'
734cdf0e10cSrcweir //        try {
735cdf0e10cSrcweir //            stdout.join();
736cdf0e10cSrcweir //            stderr.join();
737cdf0e10cSrcweir //        } catch (InterruptedException e) {}
738cdf0e10cSrcweir 
739cdf0e10cSrcweir         return isFinished();
740cdf0e10cSrcweir     }
741cdf0e10cSrcweir 
flushInput()742cdf0e10cSrcweir     protected void flushInput()
743cdf0e10cSrcweir     {
744cdf0e10cSrcweir         if (stdIn == null)
745cdf0e10cSrcweir         {
746cdf0e10cSrcweir             return;
747cdf0e10cSrcweir         }
748cdf0e10cSrcweir 
749cdf0e10cSrcweir         synchronized(stdInBuff)
750cdf0e10cSrcweir         {
751cdf0e10cSrcweir             stdIn.print(stdInBuff);
752cdf0e10cSrcweir             stdIn.flush();
753cdf0e10cSrcweir             stdInBuff = "";
754cdf0e10cSrcweir         }
755cdf0e10cSrcweir     }
756cdf0e10cSrcweir 
757cdf0e10cSrcweir     /**
758cdf0e10cSrcweir      * Returns the text output by external command to stdout.
759cdf0e10cSrcweir      * @return the text output by external command to stdout
760cdf0e10cSrcweir      */
getOutputText()761cdf0e10cSrcweir     public String getOutputText()
762cdf0e10cSrcweir     {
763cdf0e10cSrcweir         if (stdout == null)
764cdf0e10cSrcweir         {
765cdf0e10cSrcweir             return "";
766cdf0e10cSrcweir         }
767cdf0e10cSrcweir         else
768cdf0e10cSrcweir         {
769cdf0e10cSrcweir             return stdout.getStringBuffer();
770cdf0e10cSrcweir         }
771cdf0e10cSrcweir     }
772cdf0e10cSrcweir 
773cdf0e10cSrcweir     /**
774cdf0e10cSrcweir      * Returns the text output by external command to stderr.
775cdf0e10cSrcweir      * @return the text output by external command to stderr
776cdf0e10cSrcweir      */
getErrorText()777cdf0e10cSrcweir     public String getErrorText()
778cdf0e10cSrcweir     {
779cdf0e10cSrcweir         if (stderr == null)
780cdf0e10cSrcweir         {
781cdf0e10cSrcweir             return "";
782cdf0e10cSrcweir         }
783cdf0e10cSrcweir         else
784cdf0e10cSrcweir         {
785cdf0e10cSrcweir             return stderr.getStringBuffer();
786cdf0e10cSrcweir         }
787cdf0e10cSrcweir     }
788cdf0e10cSrcweir 
789cdf0e10cSrcweir     /**
790cdf0e10cSrcweir      * Prints the string specified to sdtin of external
791cdf0e10cSrcweir      * command. '\n' is not added so if you need you
792cdf0e10cSrcweir      * should terminate the string with '\n'. <p>
793cdf0e10cSrcweir      *
794cdf0e10cSrcweir      * The method can also be called before the command
795cdf0e10cSrcweir      * starts its execution. Then the text is buffered
796cdf0e10cSrcweir      * and transfered to command when it will be started.
797cdf0e10cSrcweir      * @param str
798cdf0e10cSrcweir      */
printInputText(String str)799cdf0e10cSrcweir     public void printInputText(String str)
800cdf0e10cSrcweir     {
801cdf0e10cSrcweir         stdInBuff += str;
802cdf0e10cSrcweir         flushInput();
803cdf0e10cSrcweir     }
804cdf0e10cSrcweir 
805cdf0e10cSrcweir     /**
806cdf0e10cSrcweir      * Returns information about was the command started or
807cdf0e10cSrcweir      * not.
808cdf0e10cSrcweir      *
809cdf0e10cSrcweir      * @return <code>true</code> if the external command was
810cdf0e10cSrcweir      * found and successfully started.
811cdf0e10cSrcweir      */
isStarted()812cdf0e10cSrcweir     public boolean isStarted()
813cdf0e10cSrcweir     {
814cdf0e10cSrcweir         return isStarted;
815cdf0e10cSrcweir     }
816cdf0e10cSrcweir 
817cdf0e10cSrcweir     /**
818cdf0e10cSrcweir      * Returns the information about the final state of command
819cdf0e10cSrcweir      * execution.
820cdf0e10cSrcweir      *
821cdf0e10cSrcweir      * @return <code>true</code> if the command correctly starts,
822cdf0e10cSrcweir      * exits and was not interrupted due to timeout.
823cdf0e10cSrcweir      */
isFinished()824cdf0e10cSrcweir     public boolean isFinished()
825cdf0e10cSrcweir     {
826cdf0e10cSrcweir         return isFinished;
827cdf0e10cSrcweir     }
828cdf0e10cSrcweir 
829cdf0e10cSrcweir     /**
830cdf0e10cSrcweir      * Returns exit code of the external command.
831cdf0e10cSrcweir      *
832cdf0e10cSrcweir      * @return exit code of command if it was finished,
833cdf0e10cSrcweir      * -1 if not.
834cdf0e10cSrcweir      */
getExitCode()835cdf0e10cSrcweir     public int getExitCode()
836cdf0e10cSrcweir     {
837cdf0e10cSrcweir         try
838cdf0e10cSrcweir         {
839cdf0e10cSrcweir             exitValue = m_aProcess.exitValue();
840cdf0e10cSrcweir         }
841cdf0e10cSrcweir         catch (Exception e)
842cdf0e10cSrcweir         {
843cdf0e10cSrcweir             //System.out.println("No ExitValue available");
844cdf0e10cSrcweir         }
845cdf0e10cSrcweir 
846cdf0e10cSrcweir         return exitValue;
847cdf0e10cSrcweir     }
848cdf0e10cSrcweir 
849cdf0e10cSrcweir     /** Causes the thread to sleep some time.
850cdf0e10cSrcweir      * @param milliseconds
851cdf0e10cSrcweir      */
shortWait(long milliseconds)852cdf0e10cSrcweir     public static void shortWait(long milliseconds)
853cdf0e10cSrcweir     {
854cdf0e10cSrcweir         try
855cdf0e10cSrcweir         {
856cdf0e10cSrcweir             Thread.sleep(milliseconds);
857cdf0e10cSrcweir         }
858cdf0e10cSrcweir         catch (InterruptedException e)
859cdf0e10cSrcweir         {
860cdf0e10cSrcweir             System.out.println("While waiting :" + e);
861cdf0e10cSrcweir         }
862cdf0e10cSrcweir     }
863cdf0e10cSrcweir 
dbg(String message)864cdf0e10cSrcweir     private void dbg(String message)
865cdf0e10cSrcweir     {
866cdf0e10cSrcweir         if (debug)
867cdf0e10cSrcweir         {
868cdf0e10cSrcweir             log.println(utils.getDateTime() + "PH." + message);
869cdf0e10cSrcweir         }
870cdf0e10cSrcweir     }
871cdf0e10cSrcweir 
noOutput()872cdf0e10cSrcweir     public void noOutput()
873cdf0e10cSrcweir     {
874cdf0e10cSrcweir         bUseOutput = false;
875cdf0e10cSrcweir     }
876cdf0e10cSrcweir     // -------------------------------------------------------------------------
877cdf0e10cSrcweir     class ProcessWatcher extends Thread
878cdf0e10cSrcweir     {
879cdf0e10cSrcweir 
880cdf0e10cSrcweir         private int m_nTimeoutInSec;
881cdf0e10cSrcweir         private String m_sProcessToStart;
882cdf0e10cSrcweir         private boolean m_bInterrupt;
883cdf0e10cSrcweir 
ProcessWatcher(int _nTimeOut, String _sProcess)884cdf0e10cSrcweir         public ProcessWatcher(int _nTimeOut, String _sProcess)
885cdf0e10cSrcweir         {
886cdf0e10cSrcweir             m_nTimeoutInSec = _nTimeOut;
887cdf0e10cSrcweir             m_sProcessToStart = _sProcess;
888cdf0e10cSrcweir             m_bInterrupt = false;
889cdf0e10cSrcweir         }
890cdf0e10cSrcweir 
891cdf0e10cSrcweir         /**
892cdf0e10cSrcweir          * returns true, if the thread should hold on
893cdf0e10cSrcweir          * @return
894cdf0e10cSrcweir          */
isInHoldOn()895cdf0e10cSrcweir         public synchronized boolean isInHoldOn()
896cdf0e10cSrcweir         {
897cdf0e10cSrcweir             return m_bInterrupt;
898cdf0e10cSrcweir         }
899cdf0e10cSrcweir         /**
900cdf0e10cSrcweir          * Marks the thread to hold on, next time
901cdf0e10cSrcweir          * STUPID: The thread must poll this flag itself.
902cdf0e10cSrcweir          *
903cdf0e10cSrcweir          * Reason: interrupt() seems not to work as expected.
904cdf0e10cSrcweir          */
holdOn()905cdf0e10cSrcweir         public synchronized void holdOn()
906cdf0e10cSrcweir         {
907cdf0e10cSrcweir             m_bInterrupt = true;
908cdf0e10cSrcweir             interrupt();
909cdf0e10cSrcweir         }
910cdf0e10cSrcweir 
run()911cdf0e10cSrcweir         public void run()
912cdf0e10cSrcweir         {
913cdf0e10cSrcweir             while (m_nTimeoutInSec > 0)
914cdf0e10cSrcweir             {
915cdf0e10cSrcweir                 m_nTimeoutInSec--;
916cdf0e10cSrcweir                 try
917cdf0e10cSrcweir                 {
918cdf0e10cSrcweir                     sleep(1000);
919cdf0e10cSrcweir                 }
920cdf0e10cSrcweir                 catch(java.lang.InterruptedException e)
921cdf0e10cSrcweir                 {
922cdf0e10cSrcweir                     // interrupt flag is set back to 'not interrupted' :-(
923cdf0e10cSrcweir                 }
924cdf0e10cSrcweir                 if (isInHoldOn())
925cdf0e10cSrcweir                 {
926cdf0e10cSrcweir                     break;
927cdf0e10cSrcweir                 }
928cdf0e10cSrcweir             }
929cdf0e10cSrcweir             if (m_nTimeoutInSec <= 0 && !isInHoldOn())       // not zero, so we are interrupted.
930cdf0e10cSrcweir             {
931cdf0e10cSrcweir                 system(m_sProcessToStart);
932cdf0e10cSrcweir             }
933cdf0e10cSrcweir         }
934cdf0e10cSrcweir 
935cdf0e10cSrcweir         /**
936cdf0e10cSrcweir          * Start an external Process
937cdf0e10cSrcweir          * @param _sProcess
938cdf0e10cSrcweir          */
system(String _sProcess)939cdf0e10cSrcweir         private void system(String _sProcess)
940cdf0e10cSrcweir         {
941cdf0e10cSrcweir             if (_sProcess == null)
942cdf0e10cSrcweir             {
943cdf0e10cSrcweir                 return;
944cdf0e10cSrcweir             }
945cdf0e10cSrcweir 
946cdf0e10cSrcweir             try
947cdf0e10cSrcweir             {
948cdf0e10cSrcweir 
949cdf0e10cSrcweir                 // run a _sProcess command
950cdf0e10cSrcweir                 // using the Runtime exec method:
951cdf0e10cSrcweir                 Process p = Runtime.getRuntime().exec(_sProcess);
952cdf0e10cSrcweir 
953cdf0e10cSrcweir                 BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
954cdf0e10cSrcweir 
955cdf0e10cSrcweir                 BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
956cdf0e10cSrcweir 
957cdf0e10cSrcweir                 // read the output from the command
958cdf0e10cSrcweir                 String s;
959cdf0e10cSrcweir                 while ((s = stdInput.readLine()) != null)
960cdf0e10cSrcweir                 {
961cdf0e10cSrcweir                     System.out.println("out:" + s);
962cdf0e10cSrcweir                 }
963cdf0e10cSrcweir 
964cdf0e10cSrcweir                 // read any errors from the attempted command
965cdf0e10cSrcweir                 while ((s = stdError.readLine()) != null)
966cdf0e10cSrcweir                 {
967cdf0e10cSrcweir                     System.out.println("err:" + s);
968cdf0e10cSrcweir                 }
969cdf0e10cSrcweir 
970cdf0e10cSrcweir             }
971cdf0e10cSrcweir             catch (java.io.IOException e)
972cdf0e10cSrcweir             {
973cdf0e10cSrcweir                 System.out.println("exception caught: ");
974cdf0e10cSrcweir                 e.printStackTrace();
975cdf0e10cSrcweir             }
976cdf0e10cSrcweir 
977cdf0e10cSrcweir         }
978cdf0e10cSrcweir     }
979cdf0e10cSrcweir 
980cdf0e10cSrcweir     /**
981cdf0e10cSrcweir      *  If the timeout only given by setProcessTimeout(int seconds) function is != 0,
982cdf0e10cSrcweir      *  a extra thread is created and after time has run out, the ProcessKiller string
983cdf0e10cSrcweir      *  given by function setProcessKiller(string) will execute.
984cdf0e10cSrcweir      *  So it is possible to kill a running office after a given time of seconds.
985cdf0e10cSrcweir      */
initializeProcessKiller()986cdf0e10cSrcweir     private void initializeProcessKiller()
987cdf0e10cSrcweir     {
988cdf0e10cSrcweir         if (m_nProcessTimeout != 0)
989cdf0e10cSrcweir         {
990cdf0e10cSrcweir             m_aWatcher = new ProcessWatcher(m_nProcessTimeout, m_sProcessKiller);
991cdf0e10cSrcweir             m_aWatcher.start();
992cdf0e10cSrcweir         }
993cdf0e10cSrcweir     }
994cdf0e10cSrcweir 
995cdf0e10cSrcweir     /**
996cdf0e10cSrcweir      * to stop the extra thread, before he will kill a running office. This will stop the thread.
997cdf0e10cSrcweir      */
stopWatcher()998cdf0e10cSrcweir     public void stopWatcher()
999cdf0e10cSrcweir     {
1000cdf0e10cSrcweir         if (m_aWatcher != null)
1001cdf0e10cSrcweir         {
1002cdf0e10cSrcweir             m_aWatcher.holdOn();
1003cdf0e10cSrcweir             shortWait(5000);
1004cdf0e10cSrcweir         }
1005cdf0e10cSrcweir     }
1006cdf0e10cSrcweir }
1007