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