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