Changeset 31591
- Timestamp:
- 2017-04-07T17:47:14+12:00 (7 years ago)
- Location:
- main/trunk/greenstone3/src/java/org/greenstone
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
main/trunk/greenstone3/src/java/org/greenstone/gsdl3/build/GS2PerlConstructor.java
r31590 r31591 18 18 import java.io.InputStreamReader; 19 19 import java.io.File; 20 import java.io.InputStream; 20 21 import java.io.IOException; 21 22 import java.util.ArrayList; … … 334 335 // http://www.cgi101.com/class/ch3/text.html 335 336 // setenv QUERY_STRING and REQUEST_METHOD = GET. 337 // Run the perl command as a simple process: no logging to the collection's build log 336 338 if (runPerlCommand(command_str, envvars, new File(cgi_directory))) 337 339 //new File(GlobalProperties.getGSDL3Home() + File.separator + "WEB-INF" + File.separator + "cgi"))) … … 372 374 } 373 375 374 /** returns true if completed correctly, false otherwise */ 375 protected boolean runPerlCommand(String[] command) { 376 return runPerlCommand(command, null, null); 377 } 378 379 380 protected boolean runPerlCommand(String[] command, String[] envvars, File dir) 381 { 382 boolean success = true; 383 376 protected SafeProcess createPerlProcess(String[] command, String[] envvars, File dir) { 384 377 int sepIndex = this.gsdl3home.lastIndexOf(File.separator); 385 378 String srcHome = this.gsdl3home.substring(0, sepIndex); … … 402 395 args.add(a + "=" + System.getenv(a)); 403 396 } 397 398 SafeProcess perlProcess 399 = new SafeProcess(command, args.toArray(new String[args.size()]), dir); // dir can be null 400 401 return perlProcess; 402 } 403 404 // ModifyMetadata operations call runSimplePerlCommand which produces no output in build log 405 protected boolean runSimplePerlCommand(String[] command) { 406 return runSimplePerlCommand(command, null, null); 407 } 408 409 protected boolean runSimplePerlCommand(String[] command, String[] envvars, File dir) { 410 boolean success = false; 404 411 405 412 String command_str = ""; … … 410 417 sendMessage(new ConstructionEvent(this, GSStatus.INFO, "command = " + command_str)); 411 418 412 //logger.info("### Runningcommand = " + command_str);419 logger.info("### Running simple command = " + command_str); 413 420 414 421 // This is where we create and run our perl process safely 415 SafeProcess perlProcess 416 = new SafeProcess(command, args.toArray(new String[args.size()]), dir); // dir can be null 417 422 SafeProcess perlProcess = createPerlProcess(command, envvars, dir); // dir can be null 423 424 perlProcess.setExceptionHandler(this); 425 426 sendProcessBegun(new ConstructionEvent(this, GSStatus.ACCEPTED, "starting")); 427 428 int exitVal = perlProcess.runProcess(); // uses default processing of the perl process' iostreams provided by SafeProcess 429 430 if (exitVal == 0) { 431 success = true; 432 sendProcessStatus(new ConstructionEvent(this, GSStatus.CONTINUING, "Success")); 433 } else { 434 sendProcessStatus(new ConstructionEvent(this, GSStatus.ERROR, "Failure")); 435 success = false; // explicit 436 } 437 438 return success; 439 } 440 441 442 /** returns true if completed correctly, false otherwise 443 * Building operations call runPerlCommand which sends build output to collect/log/build_log.#*.txt 444 */ 445 protected boolean runPerlCommand(String[] command) { 446 return runPerlCommand(command, null, null); 447 } 448 449 450 protected boolean runPerlCommand(String[] command, String[] envvars, File dir) 451 { 452 boolean success = true; 453 454 String command_str = ""; 455 for (int i = 0; i < command.length; i++) { 456 command_str = command_str + command[i] + " "; 457 } 458 459 sendMessage(new ConstructionEvent(this, GSStatus.INFO, "command = " + command_str)); 460 461 logger.info("### Running logged command = " + command_str); 462 463 // This is where we create and run our perl process safely 464 SafeProcess perlProcess = createPerlProcess(command, envvars, dir); // dir can be null 418 465 419 466 sendProcessBegun(new ConstructionEvent(this, GSStatus.ACCEPTED, "starting")); … … 428 475 BufferedWriter bw = null; 429 476 try { 430 bw = new BufferedWriter(new FileWriter(GSFile.collectDir(this.site_home) + File.separator + this.collection_name + File.separator + "log" + File.separator + "build_log." + (System.currentTimeMillis()) + ".txt")); 477 478 bw = new BufferedWriter(new FileWriter(new File(logDir, "build_log." + (System.currentTimeMillis()) + ".txt"))); 431 479 432 480 bw.write("Document Editor Build \n"); … … 434 482 435 483 // handle each incoming line from stdout and stderr streams, and any exceptions that occur then 436 SynchronizedProcessLineByLineHandler outLineByLineHandler 437 = new SynchronizedProcessLineByLineHandler(bw, SynchronizedProcessLineByLineHandler.STDOUT); 438 SynchronizedProcessLineByLineHandler errLineByLineHandler 439 = new SynchronizedProcessLineByLineHandler(bw, SynchronizedProcessLineByLineHandler.STDERR); 440 perlProcess.setStdOutLineByLineHandler(outLineByLineHandler); 441 perlProcess.setStdErrLineByLineHandler(errLineByLineHandler); 484 SafeProcess.CustomProcessHandler processOutHandler 485 = new SynchronizedProcessHandler(bw, SynchronizedProcessHandler.STDOUT); 486 SafeProcess.CustomProcessHandler processErrHandler 487 = new SynchronizedProcessHandler(bw, SynchronizedProcessHandler.STDERR); 442 488 443 489 // GS2PerlConstructor will do further handling of exceptions that may occur during the perl … … 450 496 // std in of java, as before. 451 497 452 perlProcess.runProcess( );498 perlProcess.runProcess(null, processOutHandler, processErrHandler); // use default procIn handling 453 499 454 500 // The original runPerlCommand() code had an ineffective check for whether the cmd had been cancelled … … 657 703 // Called when an exception happens during the running of our perl process. However, 658 704 // exceptions when reading from our perl process' stderr and stdout streams are handled by 659 // SynchronizedProcessLineByLineHandler.gotException() below. 705 // SynchronizedProcessHandler.gotException() below, since they happen in separate threads 706 // from this one (the ine from which the perl process is run). 660 707 public synchronized void gotException(Exception e) { 661 708 … … 664 711 e.printStackTrace(); 665 712 sendProcessStatus(new ConstructionEvent(this,GSStatus.ERROR, 666 "Exception occurred " + e.toString())); // atomic713 "Exception occurred " + e.toString())); 667 714 } 668 715 716 // Each instance of this class is run in its own thread by class SafeProcess.InputGobbler. 669 717 // This class deals with each incoming line from the perl process' stderr or stdout streams. One 670 // instance of this class for each stream. However, since multiple instances of this LineByLineHandler671 // could be (and in fact, are) writing to the same file in their own threads, the writer object needs672 // t o be made threadsafe.718 // instance of this class for each stream. However, since multiple instances of this CustomProcessHandler 719 // could be (and in fact, are) writing to the same file in their own threads, several objects, not just 720 // the bufferedwriter object, needed to be made threadsafe. 673 721 // This class also handles exceptions during the running of the perl process. 674 722 // The runPerlCommand code originally would do a sendProcessStatus on each exception, so we ensure 675 // we do that here too, to continue original behaviour. 676 protected class SynchronizedProcessLineByLineHandler implements SafeProcess.LineByLineHandler 723 // we do that here too, to continue original behaviour. These calls are also synchronized to make their 724 // use of the EventListeners threadsafe. 725 protected class SynchronizedProcessHandler implements SafeProcess.CustomProcessHandler 677 726 { 678 727 public static final int STDERR = 0; … … 683 732 684 733 685 public SynchronizedProcessLineByLineHandler(BufferedWriter bw, int src) { 686 this.bwHandle = bw; 734 public SynchronizedProcessHandler(BufferedWriter bw, int src) { 735 this.bwHandle = bw; // caller will close bw, since many more than one 736 // SynchronizedProcessHandlers are using it 687 737 this.source = src; // STDERR or STDOUT 688 738 } 689 739 690 public synchronized void gotLine(String line) { 691 //if(this.source == STDERR) { 692 ///System.err.println("ERROR: " + line); 693 //} else { 694 ///System.err.println("OUT: " + line); 695 //} 740 public void run(Closeable inputStream) { 741 InputStream is = (InputStream) inputStream; 742 743 BufferedReader br = null; 744 try { 745 br = new BufferedReader(new InputStreamReader(is, "UTF-8")); 746 String line=null; 747 while ( (line = br.readLine()) != null ) { 748 749 if(Thread.currentThread().isInterrupted()) { // should we not instead check if SafeProcess thread was interrupted? 750 System.err.println("Got interrupted when reading lines from process err/out stream."); 751 break; // will go to finally block 752 } 753 754 /// System.out.println("@@@ GOT LINE: " + line); 755 /// GS2PerlConstructor.logger.info("@@@ GOT LINE: " + line + " STDOUT=1: " + source); 756 757 //if(this.source == STDERR) { 758 ///System.err.println("ERROR: " + line); 759 //} else { 760 ///System.err.println("OUT: " + line); 761 //} 762 763 764 this.gotLine(line); // synchronized 765 766 /* 767 try { 768 synchronized(bwHandle) { // get a lock on the writer handle, then write 769 770 bwHandle.write(line + "\n"); 771 } 772 } catch(IOException ioe) { 773 String msg = (source == STDERR) ? "stderr" : "stdout"; 774 msg = "Exception when writing out a line read from perl process' " + msg + " stream."; 775 GS2PerlConstructor.logger.error(msg, ioe); 776 } 777 778 // this next method is thread safe since only synchronized methods are invoked. 779 // and only immutable (final) vars are used. 780 // NO, What about the listeners??? 781 sendProcessStatus(new ConstructionEvent(GS2PerlConstructor.this, GSStatus.CONTINUING, line)); 782 */ 783 } 784 } catch (IOException ioe) { // problem with reading in from process with BufferedReader br 785 786 String msg = (source == STDERR) ? "stderr" : "stdout"; 787 msg = "Got exception when processing the perl process' " + msg + " stream."; 788 GS2PerlConstructor.logger.error(msg, ioe); 789 // now do what the original runPerlCommand() code always did: 790 ioe.printStackTrace(); 791 logException(ioe); // synchronized 792 793 } catch (Exception e) { // problem with BufferedWriter bwHandle on processing each line 794 e.printStackTrace(); 795 logException(e); // synchronized 796 } finally { 797 SafeProcess.closeResource(br); 798 } 799 } 800 801 // trying to keep synchronized methods as short as possible 802 private synchronized void logException(Exception e) { 803 sendProcessStatus(new ConstructionEvent(this, GSStatus.ERROR, "Exception occurred " + e.toString())); 804 } 805 806 // trying to keep synchronized methods as short as possible 807 private synchronized void gotLine(String line) throws Exception { 696 808 697 809 // BufferedWriter writes may not be atomic … … 699 811 // Choosing to put try-catch outside of sync block, since it's okay to give up lock on exception 700 812 // http://stackoverflow.com/questions/14944551/it-is-better-to-have-a-synchronized-block-inside-a-try-block-or-a-try-block-insi 701 // "All methods on Logger are multi-thread safe", see 702 // http://stackoverflow.com/questions/14211629/java-util-logger-write-synchronization 703 704 try { 705 bwHandle.write(line + "\n"); 813 try { 814 bwHandle.write(line + "\n"); 815 816 /// System.out.println("@@@ WROTE LINE: " + line); 817 /// GS2PerlConstructor.logger.info("@@@ WROTE LINE: " + line); 818 819 // this next method is thread safe since only synchronized methods are invoked. 820 // and only immutable (final) vars are used. 821 sendProcessStatus(new ConstructionEvent(GS2PerlConstructor.this, GSStatus.CONTINUING, line)); 822 823 } catch(IOException ioe) { // can't throw Exceptions, but are forced to handle Exceptions here 824 // since our method definition doesn't specify a throws list. 825 // "All methods on Logger are multi-thread safe", see 826 // http://stackoverflow.com/questions/14211629/java-util-logger-write-synchronization 706 827 707 } catch(IOException ioe) {708 828 String msg = (source == STDERR) ? "stderr" : "stdout"; 709 msg = "Exception when writing out a line read from perl process' " + msg + " stream."; 710 GS2PerlConstructor.logger.error(msg, ioe); 711 } 712 713 // this next method is thread safe since only synchronized methods are invoked. 714 // and only immutable (final) vars are used. 715 sendProcessStatus(new ConstructionEvent(GS2PerlConstructor.this, GSStatus.CONTINUING, line)); 716 } 717 718 // This is called when we get an exception during the processing of a perl's 719 // input-, err- or output stream 720 public synchronized void gotException(Exception e) { 721 String msg = (source == STDERR) ? "stderr" : "stdout"; 722 msg = "Got exception when processing the perl process' " + msg + " stream."; 723 724 // now do what the original runPerlCommand() code always did: 725 e.printStackTrace(); 726 sendProcessStatus(new ConstructionEvent(this, GSStatus.ERROR, "Exception occurred " + e.toString())); // atomic 727 } 728 729 } // end inner class SynchronizedProcessLineByLineHandler 829 msg = "IOException when writing out a line read from perl process' " + msg + " stream."; 830 msg += "\nGot line: " + line + "\n"; 831 throw new Exception(msg, ioe); 832 } 833 } 834 835 } // end inner class SynchronizedProcessHandler 730 836 731 837 } -
main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/GS2Construct.java
r31546 r31591 1187 1187 // now we know we have an archives folder 1188 1188 String old_value = coll_db.getValue(oid); 1189 String new_value = old_value.replace("<index-status>B", "<index-status>" + mark); 1189 String new_value = "<index-status>" + mark; 1190 if(old_value == null) { 1191 logger.error("### null old_value in flat DB for oid " + oid); 1192 } else { 1193 new_value = old_value.replace("<index-status>B", "<index-status>" + mark); 1194 logger.info("### Replacing db entry for oid " + oid + " which has old_value " + old_value); 1195 logger.info("### with new value " + new_value); 1196 1197 } 1190 1198 // Close database for reading 1191 1199 coll_db.closeDatabase(); 1200 1192 1201 if (!coll_db.openDatabase(coll_db_file, SimpleCollectionDatabase.WRITE)) 1193 {1202 { 1194 1203 logger.error("Could not open collection archives database. Somebody already using this database!"); 1195 1204 return; 1196 } 1205 } 1206 1197 1207 coll_db.setValue(oid, new_value); 1198 coll_db.closeDatabase();1199 1208 1209 coll_db.closeDatabase(); 1200 1210 } 1201 1211 } -
main/trunk/greenstone3/src/java/org/greenstone/util/SafeProcess.java
r31588 r31591 35 35 private int exitValue = -1; 36 36 37 // user can write custom LineByLineHandler to deal with stdout lines as they come out one line at a time 38 // and stderr lines as they come out one at a time 39 private LineByLineHandler errLineByLineHandler = null; 40 private LineByLineHandler outLineByLineHandler = null; 37 // allow callers to process exceptions of the main process thread if they want 41 38 private ExceptionHandler exceptionHandler = null; 42 39 … … 79 76 } 80 77 81 // register a handler whose gotLine() method will get called as each line is read from the process' stdout82 public void setStdOutLineByLineHandler(LineByLineHandler out_lbl_handler) {83 outLineByLineHandler = out_lbl_handler;84 }85 86 // register a handler whose gotLine() method will get called as each line is read from the process' stderr87 public void setStdErrLineByLineHandler(LineByLineHandler err_lbl_handler) {88 errLineByLineHandler = err_lbl_handler;89 }90 91 78 // register a SafeProcess ExceptionHandler whose gotException() method will 92 79 // get called for each exception encountered … … 104 91 105 92 //***************** Copied from gli's gui/FormatConversionDialog.java *************// 93 106 94 public int runProcess() { 107 95 return runProcess(null, null, null); // use default processing of all 3 of the process' iostreams 96 } 97 98 public int runProcess(CustomProcessHandler procInHandler, 99 CustomProcessHandler procOutHandler, 100 CustomProcessHandler procErrHandler) 101 { 108 102 Process prcs = null; 109 103 SafeProcess.OutputStreamGobbler inputGobbler = null; … … 112 106 113 107 try { 108 114 109 Runtime rt = Runtime.getRuntime(); 110 111 115 112 if(this.command != null) { 116 113 prcs = rt.exec(this.command); … … 119 116 120 117 // http://stackoverflow.com/questions/5283444/convert-array-of-strings-into-a-string-in-java 121 ///logger.info("SafeProcess running: " + Arrays.toString(command_args));118 logger.info("SafeProcess running: " + Arrays.toString(command_args)); 122 119 123 120 if(this.envp == null) { … … 136 133 } 137 134 138 // send inputStr to process. The following constructor can handle inputStr being null 139 inputGobbler = // WriterToProcessInputStream 140 new SafeProcess.OutputStreamGobbler(prcs.getOutputStream(), this.inputStr); 141 142 // monitor for any error messages 143 errorGobbler // ReaderFromProcessOutputStream 144 = new SafeProcess.InputStreamGobbler(prcs.getErrorStream(), splitStdErrorNewLines); 145 146 // monitor for the expected std output line(s) 147 outputGobbler 148 = new SafeProcess.InputStreamGobbler(prcs.getInputStream(), splitStdOutputNewLines); 149 150 // register line by line handlers, if any were set, for the process stderr and stdout streams 151 if(this.outLineByLineHandler != null) { 152 outputGobbler.setLineByLineHandler(this.outLineByLineHandler); 153 } 154 if(this.errLineByLineHandler != null) { 155 errorGobbler.setLineByLineHandler(this.errLineByLineHandler); 156 } 157 if(this.exceptionHandler != null) { 158 inputGobbler.setExceptionHandler(this.exceptionHandler); 159 } 135 logger.info("### Before creating ProcessInGobbler"); 136 137 // Create the streamgobblers and set any specified handlers on them 138 139 // PROC INPUT STREAM 140 if(procInHandler == null) { 141 // send inputStr to process. The following constructor can handle inputStr being null 142 inputGobbler = // WriterToProcessInputStream 143 new SafeProcess.OutputStreamGobbler(prcs.getOutputStream(), this.inputStr); 144 } else { // user will do custom handling of process' InputStream 145 inputGobbler = new SafeProcess.OutputStreamGobbler(prcs.getOutputStream(), procInHandler); 146 } 147 148 logger.info("### Before creating ProcessErrGobbler"); 149 150 // PROC ERR STREAM to monitor for any error messages or expected output in the process' stderr 151 if(procErrHandler == null) { 152 errorGobbler // ReaderFromProcessOutputStream 153 = new SafeProcess.InputStreamGobbler(prcs.getErrorStream(), splitStdErrorNewLines); 154 } else { 155 errorGobbler 156 = new SafeProcess.InputStreamGobbler(prcs.getErrorStream(), procErrHandler); 157 } 158 159 logger.info("### Before creating ProcessOutGobbler"); 160 161 // PROC OUT STREAM to monitor for the expected std output line(s) 162 if(procOutHandler == null) { 163 outputGobbler 164 = new SafeProcess.InputStreamGobbler(prcs.getInputStream(), splitStdOutputNewLines); 165 } else { 166 outputGobbler 167 = new SafeProcess.InputStreamGobbler(prcs.getInputStream(), procOutHandler); 168 } 169 170 171 logger.info("### Before streamgobblers.start()"); 160 172 161 173 // kick off the stream gobblers … … 163 175 errorGobbler.start(); 164 176 outputGobbler.start(); 177 178 logger.info("### After streamgobblers.start() - before waitFor"); 165 179 166 180 // any error??? 167 this.exitValue = prcs.waitFor(); // can throw an InterruptedException if process did not terminate 181 this.exitValue = prcs.waitFor(); // can throw an InterruptedException if process did not terminate 182 183 logger.info("Process exitValue: " + exitValue); 184 185 logger.info("### Before streamgobblers.join()"); 186 168 187 // From the comments of 169 188 // http://www.javaworld.com/article/2071275/core-java/when-runtime-exec---won-t.html?page=2 … … 175 194 inputGobbler.join(); 176 195 196 logger.info("### After streamgobblers.join()"); 197 177 198 // set the variables the code that created a SafeProcess object may want to inspect 178 199 this.outputStr = outputGobbler.getOutput(); 179 200 this.errorStr = errorGobbler.getOutput(); 180 201 181 202 // Since we didn't have an exception, process should have terminated now (waitFor blocks until then) 182 203 // Set process to null so we don't forcibly terminate it below with process.destroy() … … 192 213 } 193 214 } catch(InterruptedException ie) { 215 194 216 if(exceptionHandler != null) { 195 217 exceptionHandler.gotException(ie); … … 197 219 logger.error("Process InterruptedException: " + ie.getMessage(), ie); 198 220 //System.err.println("Process InterruptedException " + ie.getMessage()); 199 //ie.printStackTrace(); // an interrupt here is not an error, it can be a cancel action 200 } 201 221 ///ie.printStackTrace(); // an interrupt here is not an error, it can be a cancel action 222 } 202 223 203 224 // propagate interrupts to worker threads here? … … 237 258 } 238 259 } 239 260 240 261 return this.exitValue; 241 262 } … … 257 278 } 258 279 259 // When reading from a process' stdout or stderr stream, you can create a LineByLineHandler260 // to do something on a line by line basis, such as sending the line to a log261 public static interface LineByLineHandler { 262 public void gotLine(String line); 263 public void gotException(Exception e); // for when an exception occurs instead of getting a line280 // write your own run() body for any StreamGobbler 281 // Make sure your implementation is threadsafe if you're sharing immutable objects between the threaded streams 282 // example implementation is in the GS2PerlConstructor.SynchronizedProcessHandler class. 283 public static interface CustomProcessHandler { 284 public void run(Closeable stream); //InputStream or OutputStream 264 285 } 265 286 … … 270 291 public static class InputStreamGobbler extends Thread 271 292 { 272 InputStream is = null;273 StringBuffer outputstr = new StringBuffer();274 boolean split_newlines = false;275 LineByLineHandler lineByLineHandler = null;276 293 private InputStream is = null; 294 private StringBuffer outputstr = new StringBuffer(); 295 private boolean split_newlines = false; 296 private CustomProcessHandler customHandler = null; 297 277 298 public InputStreamGobbler(InputStream is) 278 299 { 279 300 this.is = is; 280 split_newlines = false;301 this.split_newlines = false; 281 302 } 282 303 … … 287 308 } 288 309 289 public void setLineByLineHandler(LineByLineHandler lblHandler) { 290 lineByLineHandler = lblHandler; 291 } 292 293 294 public void run() 310 public InputStreamGobbler(InputStream is, CustomProcessHandler customHandler) 311 { 312 this.is = is; 313 this.customHandler = customHandler; 314 } 315 316 // default run() behaviour 317 public void runDefault() 295 318 { 296 319 BufferedReader br = null; … … 307 330 //System.out.println("@@@ GOT LINE: " + line); 308 331 outputstr.append(line); 309 310 332 if(split_newlines) { 311 333 outputstr.append(Misc.NEWLINE); // "\n" is system dependent (Win must be "\r\n") 312 334 } 313 314 if(lineByLineHandler != null) { // let handler deal with newlines 315 lineByLineHandler.gotLine(line); 316 } 317 } 318 } catch (IOException ioe) { 319 if(lineByLineHandler != null) { 320 lineByLineHandler.gotException(ioe); 321 } else { 322 logger.error("Exception when reading from a process' stdout/stderr stream: ", ioe); 323 //ioe.printStackTrace(); 324 } 335 } 336 } catch (IOException ioe) { 337 logger.error("Exception when reading from a process' stdout/stderr stream: ", ioe); 338 //System.err.println("Exception when reading from a process' stdout/stderr stream: "); 339 //ioe.printStackTrace(); 325 340 326 341 } finally { … … 329 344 } 330 345 346 public void runCustom() { 347 this.customHandler.run(is); 348 } 349 350 public void run() { 351 if(this.customHandler == null) { 352 runDefault(); 353 } else { 354 runCustom(); 355 } 356 } 357 331 358 public String getOutput() { 332 359 return outputstr.toString(); // implicit toString() call anyway. //return outputstr; … … 340 367 public static class OutputStreamGobbler extends Thread 341 368 { 342 OutputStream os = null;343 String inputstr = "";344 ExceptionHandler exceptionHandler = null;369 private OutputStream os = null; 370 private String inputstr = ""; 371 private CustomProcessHandler customHandler = null; 345 372 346 373 public OutputStreamGobbler(OutputStream os) { … … 353 380 this.inputstr = inputstr; 354 381 } 355 356 public void setExceptionHandler(ExceptionHandler eHandler) { 357 exceptionHandler = eHandler; 358 } 359 360 public void run() 361 { 382 383 public OutputStreamGobbler(OutputStream os, CustomProcessHandler customHandler) { 384 this.os = os; 385 this.customHandler = customHandler; 386 } 387 388 // default run() behaviour 389 public void runDefault() { 390 362 391 if (inputstr == null) { 363 392 return; … … 365 394 366 395 BufferedWriter osw = null; 367 try 396 try { 368 397 osw = new BufferedWriter(new OutputStreamWriter(os, "UTF-8")); 369 398 //System.out.println("@@@ SENDING LINE: " + inputstr); … … 385 414 */ 386 415 } catch (IOException ioe) { 387 if (this.exceptionHandler != null) { 388 this.exceptionHandler.gotException(ioe); 389 } else { 390 logger.error("Exception writing to SafeProcess' inputstream: ", ioe); 391 //ioe.printStackTrace(); 392 } 393 416 logger.error("Exception writing to SafeProcess' inputstream: ", ioe); 417 //System.err.println("Exception writing to SafeProcess' inputstream: "); 418 //ioe.printStackTrace(); 394 419 } finally { 395 420 SafeProcess.closeResource(osw); 396 421 } 422 } 423 424 // call the user's custom handler for the run() method 425 public void runCustom() { 426 this.customHandler.run(os); 427 } 428 429 public void run() 430 { 431 if(this.customHandler == null) { 432 runDefault(); 433 } else { 434 runCustom(); 435 } 436 397 437 } 398 438 } // end static inner class OutputStreamGobbler
Note:
See TracChangeset
for help on using the changeset viewer.