001package org.biojava.utils; 002 003 004/////////////////////////////////////////////////////////////////////////////// 005// Copyright (C) 2002 Scott McCrory 006// 007// This program is free software; you can redistribute it and/or 008// modify it under the terms of the GNU Lesser General Public License 009// as published by the Free Software Foundation; either version 2 010// of the License, or (at your option) any later version. 011// 012// This program is distributed in the hope that it will be useful, 013// but WITHOUT ANY WARRANTY; without even the implied warranty of 014// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 015// GNU Lesser General Public License for more details. 016// 017// You should have received a copy of the GNU Lesser General Public License 018// along with this program; if not, write to the Free Software 019// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 020/////////////////////////////////////////////////////////////////////////////// 021 022import java.io.BufferedReader; 023import java.io.IOException; 024import java.io.InputStream; 025import java.io.InputStreamReader; 026import java.io.ObjectInputStream; 027import java.io.ObjectOutputStream; 028import java.io.OutputStream; 029import java.io.PrintWriter; 030import java.io.StringWriter; 031import java.util.Date; 032import java.util.StringTokenizer; 033 034 /** 035 * <P>Makes running external executables easier, optionally under a watched thread. 036 * 037 * In addition, probably the most useful feature of ExecRunner is using it to 038 * run a command-line program and obtain its stdout and stderr results in two 039 * strings. This is done with exec(String) - see that method for an example. 040 * 041 * With acknowledgements to Michael C. Daconta, author of "Java Pitfalls, 042 * Time Saving Solutions, and Workarounds to Improve Programs." and his 043 * article in JavaWorld "When Runtime.exec() Won't".</P> 044 * 045 * @author <a href="mailto:smccrory@users.sourceforge.net">Scott McCrory</a>. 046 * @author Francois Pepin 047 * @author Andreas Dräger 048 * @version CVS $Id$ 049 */ 050 public class ExecRunner { 051 052 /** Win NT/2K/MEPro require cmd.exe to run programs **/ 053 private static final String WINDOWS_NT_2000_COMMAND_1 = "cmd.exe"; 054 055 /** Win NT/2K/MEPro require the /C to specify what to run **/ 056 private static final String WINDOWS_NT_2000_COMMAND_2 = "/C"; 057 058 /** Win 9X/MEHome require cmd.exe to run programs **/ 059 private static final String WINDOWS_9X_ME_COMMAND_1 = "command.exe"; 060 061 /** Win 9X/MEHome require the /C to specify what to run **/ 062 private static final String WINDOWS_9X_ME_COMMAND_2 = "/C"; 063 064 /** String to send to STDERR if program exceeds max run time **/ 065 private static final String MAX_RUN_TIME_EXCEEDED_STRING = 066 "MAX_RUN_TIME_EXCEEDED"; 067 068 /** String to capture STDOUT **/ 069 private String out = new String(); 070 071 /** String to capture STDERR **/ 072 private String err = new String(); 073 074 /** Default max run time (in seconds) **/ 075 private int maxRunTimeSecs = 0; 076 077 /** Flag to indicate if we've exceeded max run time **/ 078 private boolean maxRunTimeExceeded = false; 079 080 /** 081 * Basic ExecRunner constructor. 082 * 083 */ 084 public ExecRunner() { 085 super(); 086 } 087 088 /** 089 * ExecRunner constructor which also conveniently runs exec(String). 090 * 091 * @param command The program or command to run 092 * @throws ExceptionInInitializerError thrown if a problem occurs 093 */ 094 public ExecRunner(String command) throws ExceptionInInitializerError { 095 this(); 096 try { 097 exec(command); 098 } 099 catch (IOException ioe) { 100 throw new ExceptionInInitializerError(ioe.getMessage()); 101 } 102 catch (InterruptedException inte) { 103 throw new ExceptionInInitializerError(inte.getMessage()); 104 } 105 106 } 107 108 /** 109 * ExecRunner constructor which also conveniently runs exec(String). 110 * 111 * @param command The program or command to run 112 * @param arguments An array of Strings in which every single String 113 * is exactly one of the program's arguments. So these arguments are 114 * allowed to contain white spaces and are marked as Strings by the 115 * system. 116 * @throws ExceptionInInitializerError thrown if a problem occurs 117 * @since 1.5 118 */ 119 public ExecRunner(String command, String[] arguments) 120 throws ExceptionInInitializerError { 121 this(); 122 try { 123 exec(command, arguments); 124 } catch (IOException ioe) { 125 throw new ExceptionInInitializerError(ioe.getMessage()); 126 } catch (InterruptedException inte) { 127 throw new ExceptionInInitializerError(inte.getMessage()); 128 } 129 } 130 131 132 /** 133 * We override the <code>clone</code> method here to prevent cloning of our class. 134 * 135 * @throws CloneNotSupportedException To indicate cloning is not allowed 136 * @return Nothing ever really returned since we throw a CloneNotSupportedException 137 **/ 138 public final Object clone() throws CloneNotSupportedException { 139 140 throw new java.lang.CloneNotSupportedException(); 141 142 } 143 144 /** 145 * The <B>exec(String)</B> method runs a process inside of a watched thread. 146 * It returns the client's exit code and feeds its STDOUT and STDERR to 147 * ExecRunner's out and err strings, where you then use getOutString() 148 * and getErrString() to obtain these values. 149 * If the command String contains arguments which are Strings containing white 150 * spaces, the method <pre>exec(program, arguments)</pre> should be used 151 * instead, where <code>arguments</code> is a <code>String[]</code> array 152 * containing the arguments of the program. 153 * 154 * Example: 155 * 156 * <pre> 157 * // Execute the program and grab the results 158 * String out = ""; 159 * String err = ""; 160 * try { 161 * 162 * ExecRunner er = new ExecRunner(); 163 * er.setMaxRunTimeSecs(maxRunTime); 164 * er.exec(program); 165 * if (!er.getMaxRunTimeExceeded()) { 166 * out = er.getOutString(); 167 * err = er.getErrString(); 168 * } 169 * else { 170 * log.error("Maximum run time exceeded!"); 171 * continue; 172 * } 173 * 174 * } 175 * catch (Exception e) { 176 * log.error("Error executing " + program + ": " + e.getMessage()); 177 * continue; 178 * } 179 * </pre> 180 * 181 * @return The command's return code 182 * @param command The program or command to run 183 * @throws IOException thrown if a problem occurs 184 * @throws InterruptedException thrown if a problem occurs 185 */ 186 public int exec(String command) throws IOException, InterruptedException { 187 188 StringWriter swOut = new StringWriter(); 189 PrintWriter pwOut = new PrintWriter(swOut, true); 190 191 StringWriter swErr = new StringWriter(); 192 PrintWriter pwErr = new PrintWriter(swErr, true); 193 194 int rc = exec(command, pwOut, pwErr); 195 196 out = swOut.toString(); 197 err = swErr.toString(); 198 199 return rc; 200 201 } 202 203 204 /** Sometimes special cases may occur that the arguments of an external program 205 * are Strings containing white spaces. Another example are external processes 206 * needing the String arguments to be characterized in a special way. 207 * In this cases it is sensefull to write every single argument in an String 208 * array. The system itselfe will mark these arguments as Strings so that these 209 * special encoding can be omitted. 210 * @param command The external program to be executed. 211 * @param arguments An array of Strings. Every entry of this array is an argument 212 * of the external program to be executed. 213 * @return The command's return code 214 * @throws IOException thrown if a problem occurs 215 * @throws InterruptedException thrown if a problem occurs 216 * @since 1.5 217 */ 218 public int exec(String command, String[] arguments) 219 throws IOException, InterruptedException { 220 221 StringWriter swOut = new StringWriter(); 222 PrintWriter pwOut = new PrintWriter(swOut, true); 223 224 StringWriter swErr = new StringWriter(); 225 PrintWriter pwErr = new PrintWriter(swErr, true); 226 227 int rc = exec(command, arguments, pwOut, pwErr); 228 229 out = swOut.toString(); 230 err = swErr.toString(); 231 232 return rc; 233 } 234 235 /** 236 * Convenience method for calling exec with OutputStreams. 237 * 238 * @return The command's return code 239 * @param command The program or command to run 240 * @param stdoutStream java.io.OutputStream 241 * @param stderrStream java.io.OutputStream 242 * @throws IOException thrown if a problem occurs 243 * @throws InterruptedException thrown if a problem occurs 244 **/ 245 public int exec( 246 String command, 247 OutputStream stdoutStream, 248 OutputStream stderrStream) 249 throws IOException, InterruptedException { 250 251 PrintWriter pwOut = new PrintWriter(stdoutStream, true); 252 PrintWriter pwErr = new PrintWriter(stderrStream, true); 253 254 return exec(command, pwOut, pwErr); 255 } 256 257 258 /** 259 * Convenience method for calling exec with OutputStreams. 260 * 261 * @return The command's return code 262 * @param command The program or command to run 263 * @param arguments An array of Strings containing the program's arguments. 264 * @param stdoutStream java.io.OutputStream 265 * @param stderrStream java.io.OutputStream 266 * @throws IOException thrown if a problem occurs 267 * @throws InterruptedException thrown if a problem occurs 268 * @since 1.5 269 **/ 270 public int exec( 271 String command, 272 String[] arguments, 273 OutputStream stdoutStream, 274 OutputStream stderrStream) 275 throws IOException, InterruptedException { 276 277 PrintWriter pwOut = new PrintWriter(stdoutStream, true); 278 PrintWriter pwErr = new PrintWriter(stderrStream, true); 279 280 return exec(command, arguments, pwOut, pwErr); 281 } 282 283 /** 284 * The <code>exec(String, PrintWriter, PrintWriter)</code> method runs 285 * a process inside of a watched thread. It returns the client's exit code 286 * and feeds its STDOUT and STDERR to the passed-in streams. 287 * 288 * @return The command's return code 289 * @param command The program or command to run 290 * @param stdoutWriter java.io.PrintWriter 291 * @param stderrWriter java.io.PrintWriter 292 * @throws IOException thrown if a problem occurs 293 * @throws InterruptedException thrown if a problem occurs 294 **/ 295 public int exec( 296 String command, 297 PrintWriter stdoutWriter, 298 PrintWriter stderrWriter) 299 throws IOException, InterruptedException { 300 301 // Default exit value is non-zero to indicate a problem. 302 int exitVal = 1; 303 304 //////////////////////////////////////////////////////////////// 305 Runtime rt = Runtime.getRuntime(); 306 Process proc; 307 String[] cmd = null; 308 309 // First get the start time & calculate comparison numbers 310 Date startTime = new Date(); 311 long startTimeMs = startTime.getTime(); 312 long maxTimeMs = startTimeMs + (maxRunTimeSecs * 1000); 313 314 //////////////////////////////////////////////////////////////// 315 // First determine the OS to build the right command string 316 String osName = System.getProperty("os.name"); 317 if (osName.equals("Windows NT") || osName.equals("Windows 2000")) { 318 cmd = new String[3]; 319 cmd[0] = WINDOWS_NT_2000_COMMAND_1; 320 cmd[1] = WINDOWS_NT_2000_COMMAND_2; 321 cmd[2] = command; 322 } 323 else if ( 324 osName.equals("Windows 95") 325 || osName.equals("Windows 98") 326 || osName.equals("Windows ME")) { 327 cmd = new String[3]; 328 cmd[0] = WINDOWS_9X_ME_COMMAND_1; 329 cmd[1] = WINDOWS_9X_ME_COMMAND_2; 330 cmd[2] = command; 331 } 332 else { 333 // Linux (and probably other *nixes) prefers to be called 334 // with each argument supplied separately, so we first 335 // Tokenize it across spaces as the boundary. 336 StringTokenizer st = new StringTokenizer(command, " "); 337 cmd = new String[st.countTokens()]; 338 int token = 0; 339 while (st.hasMoreTokens()) { 340 String tokenString = st.nextToken(); 341 //System.out.println(tokenString); 342 cmd[token++] = tokenString; 343 } 344 } 345 346 // Execute the command and start the two output gobblers 347 if (cmd != null && cmd.length > 0) { 348 //System.out.println("**Checkpoint** :" + cmd.length); 349 proc = rt.exec(cmd); 350 } 351 else throw new IOException("Insufficient commands!"); 352 353 StreamGobbler outputGobbler = 354 new StreamGobbler(proc.getInputStream(), stdoutWriter); 355 StreamGobbler errorGobbler = 356 new StreamGobbler(proc.getErrorStream(), stderrWriter); 357 outputGobbler.start(); 358 errorGobbler.start(); 359 360 // Wait for the program to finish running and return the 361 // exit value obtained from the executable 362 while (true) { 363 try { 364 exitVal = proc.exitValue(); 365 break; 366 } 367 catch (IllegalThreadStateException e) { 368 // If we get this exception, then the process isn't 369 // done executing and we determine if our time is up. 370 if (maxRunTimeSecs > 0) { 371 Date endTime = new Date(); 372 long endTimeMs = endTime.getTime(); 373 if (endTimeMs > maxTimeMs) { 374 // Time's up - kill the process and the gobblers and return 375 proc.destroy(); 376 maxRunTimeExceeded = true; 377 stderrWriter.println(MAX_RUN_TIME_EXCEEDED_STRING); 378 outputGobbler.quit(); 379 errorGobbler.quit(); 380 stdoutWriter.close(); 381 stderrWriter.close(); 382 proc.getOutputStream().close(); 383 return exitVal; 384 } else { 385 // Time is not up yet so wait 100 ms before testing again 386 Thread.sleep(100); 387 } 388 } 389 } 390 } 391 392 //////////////////////////////////////////////////////////////// 393 // Wait for output gobblers to finish forwarding the output 394 while (outputGobbler.isAlive() || errorGobbler.isAlive()) { 395 } 396 397 //////////////////////////////////////////////////////////////// 398 // All done, flush the streams and return the exit value 399 stdoutWriter.flush(); 400 stderrWriter.flush(); 401 stdoutWriter.close(); 402 stderrWriter.close(); 403 proc.getOutputStream().close(); 404 return exitVal; 405 406 } 407 408 409 /** 410 * The <code>exec(String, PrintWriter, PrintWriter)</code> method runs 411 * a process inside of a watched thread. It returns the client's exit code 412 * and feeds its STDOUT and STDERR to the passed-in streams. 413 * The arguments for the external program or command are passed as an array 414 * of Strings. This has the advantage that the arguments are allowed to 415 * contain white spaces and are marked to be Strings by the System itselfe, 416 * which is sometimes important. Every single argument has to be exactly one 417 * dimension of the arguments array. 418 * 419 * @return The command's return code 420 * @param command The program or command to run 421 * @param arguments An array of Strings containing the program's arguments/options. 422 * @param stdoutWriter java.io.PrintWriter 423 * @param stderrWriter java.io.PrintWriter 424 * @throws IOException thrown if a problem occurs 425 * @throws InterruptedException thrown if a problem occurs 426 * @since 1.5 427 **/ 428 public int exec( 429 String command, 430 String[] arguments, 431 PrintWriter stdoutWriter, 432 PrintWriter stderrWriter) 433 throws IOException, InterruptedException { 434 435 // Default exit value is non-zero to indicate a problem. 436 int exitVal = 1; 437 438 //////////////////////////////////////////////////////////////// 439 Runtime rt = Runtime.getRuntime(); 440 Process proc; 441 String[] cmd = null; 442 443 // First get the start time & calculate comparison numbers 444 Date startTime = new Date(); 445 long startTimeMs = startTime.getTime(); 446 long maxTimeMs = startTimeMs + (maxRunTimeSecs * 1000); 447 int i = 0; 448 449 //////////////////////////////////////////////////////////////// 450 // First determine the OS to build the right command string 451 String osName = System.getProperty("os.name"); 452 if (osName.startsWith("Windows")) { 453 cmd = new String[3+arguments.length]; 454 if (osName.endsWith("NT") || osName.endsWith("2000")) { 455 cmd[0] = WINDOWS_NT_2000_COMMAND_1; 456 cmd[1] = WINDOWS_NT_2000_COMMAND_2; 457 } else if (osName.endsWith("95") || osName.endsWith("98") || osName.endsWith("ME")) { 458 cmd[0] = WINDOWS_9X_ME_COMMAND_1; 459 cmd[1] = WINDOWS_9X_ME_COMMAND_2; 460 } 461 cmd[2] = command; 462 for (i = 3; i<arguments.length; i++) 463 cmd[i] = arguments[i-3]; 464 } else { 465 // Linux (and probably other *nixes) prefers to be called 466 // with each argument supplied separately. 467 cmd = new String[arguments.length+1]; 468 cmd[0] = command; 469 for (i=1; i<cmd.length; i++) 470 cmd[i] = arguments[i-1]; 471 } 472 473 // Execute the command and start the two output gobblers 474 if (cmd != null && cmd.length > 0) { 475 //System.out.println("**Checkpoint** :" + cmd.length); 476 proc = rt.exec(cmd); 477 } else { 478 throw new IOException("Insufficient commands!"); 479 } 480 481 StreamGobbler outputGobbler = 482 new StreamGobbler(proc.getInputStream(), stdoutWriter); 483 StreamGobbler errorGobbler = 484 new StreamGobbler(proc.getErrorStream(), stderrWriter); 485 outputGobbler.start(); 486 errorGobbler.start(); 487 488 // Wait for the program to finish running and return the 489 // exit value obtained from the executable 490 while (true) { 491 try { 492 exitVal = proc.exitValue(); 493 break; 494 } catch (IllegalThreadStateException e) { 495 // If we get this exception, then the process isn't 496 // done executing and we determine if our time is up. 497 if (maxRunTimeSecs > 0) { 498 Date endTime = new Date(); 499 long endTimeMs = endTime.getTime(); 500 if (endTimeMs > maxTimeMs) { 501 // Time's up - kill the process and the gobblers and return 502 proc.destroy(); 503 maxRunTimeExceeded = true; 504 stderrWriter.println(MAX_RUN_TIME_EXCEEDED_STRING); 505 outputGobbler.quit(); 506 errorGobbler.quit(); 507 stdoutWriter.close(); 508 proc.getOutputStream().close(); 509 stderrWriter.close(); 510 return exitVal; 511 } else { 512 // Time is not up yet so wait 100 ms before testing again 513 Thread.sleep(100); 514 } 515 } 516 } 517 } 518 519 //////////////////////////////////////////////////////////////// 520 // Wait for output gobblers to finish forwarding the output 521 while (outputGobbler.isAlive() || errorGobbler.isAlive()) { 522 } 523 524 //////////////////////////////////////////////////////////////// 525 // All done, flush the streams and return the exit value 526 stdoutWriter.flush(); 527 stderrWriter.flush(); 528 stdoutWriter.close(); 529 stderrWriter.close(); 530 proc.getOutputStream().close(); 531 return exitVal; 532 533 } 534 535 /** 536 * Returns the error string if exec(String) was invoked. 537 * 538 * @return The error string if exec(String) was invoked. 539 */ 540 public String getErrString() { 541 return err; 542 } 543 544 /** 545 * Returns whether the maximum runtime was exceeded or not. 546 * 547 * @return boolean indicating whether the maximum runtime was exceeded or not. 548 */ 549 public boolean getMaxRunTimeExceeded() { 550 return maxRunTimeExceeded; 551 } 552 553 /** 554 * Returns the maximum run time in seconds for this object. 555 * 556 * @return the maximum run time in seconds for this object. 557 */ 558 public int getMaxRunTimeSecs() { 559 return maxRunTimeSecs; 560 } 561 562 /** 563 * Returns the output string if exec(String) was invoked. 564 * 565 * @return The output string if exec(String) was invoked. 566 */ 567 public String getOutString() { 568 return out; 569 } 570 571 /** 572 * This is for unit testing of the class. 573 * 574 * @param args an array of command-line arguments 575 * @throws IOException thrown if a problem occurs 576 **/ 577 public static void main(String[] args) throws IOException { 578 579 try { 580 581 ExecRunner er = new ExecRunner(); 582 583 ///////////////////////////////////////////////////////////////////// 584 // Linux: Test the exec operation with just STDOUT and STDERR 585 //System.out.println("Testing ExecRunner with STDOUT and STDERR..."); 586 //er.exec("ls -l", System.out, System.err); 587 //System.out.println("Complete"); 588 589 ///////////////////////////////////////////////////////////////////// 590 // Windows: Test the exec operation with just STDOUT and STDERR 591 System.out.println("Testing ExecRunner with StringWriter..."); 592 593 er = new ExecRunner(); 594 er.setMaxRunTimeSecs(1); 595 er.exec("dir /s c:\\"); 596 //er.exec("ls -l"); 597 598 System.out.println("<STDOUT>\n" + er.getOutString() + "</STDOUT>"); 599 System.out.println("<STDERR>\n" + er.getErrString() + "</STDERR>"); 600 System.out.println("Testing Done"); 601 602 ///////////////////////////////////////////////////////////////////// 603 // Exit nicely 604 System.exit(0); 605 606 } 607 catch (Exception e) { 608 609 e.printStackTrace(); 610 System.exit(1); 611 612 } 613 } 614 615 /** 616 * We override the <code>readObject</code> method here to prevent 617 * deserialization of our class for security reasons. 618 * 619 * @param in java.io.ObjectInputStream 620 * @throws IOException thrown if a problem occurs 621 **/ 622 private final void readObject(ObjectInputStream in) throws IOException { 623 624 throw new IOException("Object cannot be deserialized"); 625 626 } 627 628 /** 629 * Sets the maximum run time in seconds. 630 * If you do not want to limit the executable's run time, simply pass in 631 * a 0 (which is also the default). 632 * 633 * @param max Maximim number of seconds to let program run 634 */ 635 public void setMaxRunTimeSecs(int max) { 636 637 maxRunTimeSecs = max; 638 639 } 640 641 /** 642 * We override the <code>writeObject</code> method here to prevent 643 * serialization of our class for security reasons. 644 * 645 * @param out java.io.ObjectOutputStream 646 * @throws IOException thrown if a problem occurs 647 **/ 648 private final void writeObject(ObjectOutputStream out) throws IOException { 649 650 throw new IOException("Object cannot be serialized"); 651 652 } 653 654 } 655 656 /** 657 * <P>Captures the output of an InputStream.</P> 658 * 659 * With acknowledgements to Michael C. Daconta, author of "Java Pitfalls, 660 * Time Saving Solutions, and Workarounds to Improve Programs." and his 661 * article in JavaWorld "When Runtime.exec() Won't". 662 * 663 * See the ExecRunner class for a reference implementation. 664 * 665 * @author <a href="mailto:smccrory@users.sourceforge.net">Scott McCrory</a>. 666 * @version CVS $Id$ 667 */ 668 class StreamGobbler extends Thread { 669 670 /** The input stream we're gobbling **/ 671 private InputStream in = null; 672 673 /** The printwriter we'll send the gobbled characters to if asked**/ 674 private PrintWriter pwOut = null; 675 676 /** Our flag to allow us to safely terminate the monitoring thread **/ 677 private boolean quit = false; 678 679 680 /** 681 * A simpler constructor for StreamGobbler - defaults to stdout. 682 * 683 * @param in InputStream 684 */ 685 public StreamGobbler(InputStream in) { 686 687 this.in = in; 688 this.pwOut = new PrintWriter(System.out, true); 689 690 } 691 692 /** 693 * A more explicit constructor for StreamGobbler where you can tell 694 * it exactly where to relay the output to. 695 * Creation date: (9/23/2001 8:48:01 PM) 696 * 697 * @param in InputStream 698 * @param out OutputStream 699 */ 700 public StreamGobbler(InputStream in, OutputStream out) { 701 702 this.in = in; 703 this.pwOut = new PrintWriter(out, true); 704 705 } 706 707 /** 708 * A more explicit constructor for StreamGobbler where you can tell 709 * it exactly where to relay the output to. 710 * Creation date: (9/23/2001 8:48:01 PM) 711 * 712 * @param in InputStream 713 * @param pwOut PrintWriter 714 */ 715 public StreamGobbler(InputStream in, PrintWriter pwOut) { 716 717 this.in = in; 718 this.pwOut = pwOut; 719 720 } 721 722 /** 723 * We override the <code>clone</code> method here to prevent cloning of our class. 724 * 725 * @throws CloneNotSupportedException To indicate cloning is not allowed 726 * @return Nothing ever really returned since we throw a CloneNotSupportedException 727 **/ 728 public final Object clone() throws CloneNotSupportedException { 729 730 throw new CloneNotSupportedException(); 731 732 } 733 734 /** 735 * Tells the StreamGobbler to quit it's operation. 736 * This is safer than using stop() since it uses a semophore checked in the 737 * main wait loop instead of possibly forcing semaphores to untimely unlock. 738 */ 739 public void quit() { 740 741 quit = true; 742 743 } 744 745 /** 746 * We override the <code>readObject</code> method here to prevent 747 * deserialization of our class for security reasons. 748 * 749 * @param in java.io.ObjectInputStream 750 * @throws IOException thrown if a problem occurs 751 **/ 752 private final void readObject(ObjectInputStream in) throws IOException { 753 754 throw new IOException("Object cannot be deserialized"); 755 756 } 757 758 /** 759 * Gobbles up all the stuff coming from the InputStream and 760 * sends it to the OutputStream specified during object construction. 761 **/ 762 public void run() { 763 764 try { 765 // Set up the input stream 766 BufferedReader br = new BufferedReader(new InputStreamReader(in)); 767 768 // Initialize the temporary results containers 769 String line = null; 770 771 // Main processing loop which captures the output 772 while ((line = br.readLine()) != null) { 773 if (quit) 774 break; 775 else 776 pwOut.println(line); 777 } 778 this.in.close(); 779 } 780 catch (Exception e) { 781 e.printStackTrace(); 782 } 783 784 } 785 786 /** 787 * We override the <code>writeObject</code> method here to prevent 788 * serialization of our class for security reasons. 789 * 790 * @param out java.io.ObjectOutputStream 791 * @throws IOException thrown if a problem occurs 792 **/ 793 private final void writeObject(ObjectOutputStream out) throws IOException { 794 795 throw new IOException("Object cannot be serialized"); 796 797 } 798 799 }