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