Changeset 31593 for main/trunk/gli

Show
Ignore:
Timestamp:
07.04.2017 18:38:05 (3 years ago)
Author:
ak19
Message:

Porting the modifications for SafeProcess?.java from GS3 src code to GLI. Now GLI also uses the new SafeProcess?.CustomProcessHandler? instead of the LineByLineHandler? whose process flow may have been less transparent to developers. GLI's updated SafeProcess?.java has now been tested successfully against DownloadPane?, GS3ServerThread and FormatConversionDialog? all of which use SafeProcess?.java since yesterday. Things that worked still work.

Location:
main/trunk/gli/src/org/greenstone/gatherer
Files:
3 modified

Legend:

Unmodified
Added
Removed
  • main/trunk/gli/src/org/greenstone/gatherer/gui/DownloadPane.java

    r31585 r31593  
    280280        // This time we expect XML to have come out of the process std error stream. 
    281281        String errStreamOutput = process.getStdError(); 
     282        ///System.err.println("*********\nDownload Pane data, got:\n" + errStreamOutput + "\n**********\n"); 
    282283        StringReader xmlStrReader = new StringReader(errStreamOutput); 
    283284        document = XMLTools.parseXML(xmlStrReader); 
  • main/trunk/gli/src/org/greenstone/gatherer/util/GS3ServerThread.java

    r31584 r31593  
    132132    else { 
    133133        System.err.println("********** FAILED TO SUCCESSFULLY stop THE GS3 SERVER ON EXIT"); 
    134         //throw new Exception ("Failed to successfully stop the GS3 server on exit."); 
    135134    } 
    136135     
  • main/trunk/gli/src/org/greenstone/gatherer/util/SafeProcess.java

    r31586 r31593  
    2121public class SafeProcess { 
    2222 
    23     //static Logger logger = Logger.getLogger(org.greenstone.util.SafeProcess.class.getName()); 
     23    ///static Logger logger = Logger.getLogger(org.greenstone.util.SafeProcess.class.getName()); 
    2424 
    2525    // input to SafeProcess and initialising it 
     
    3535    private int exitValue = -1; 
    3636 
    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 
    4138    private ExceptionHandler exceptionHandler = null; 
    4239 
     
    7976    } 
    8077 
    81     // register a handler whose gotLine() method will get called as each line is read from the process' stdout 
    82     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' stderr 
    87     public void setStdErrLineByLineHandler(LineByLineHandler err_lbl_handler) { 
    88     errLineByLineHandler = err_lbl_handler; 
    89     } 
    90  
    9178    // register a SafeProcess ExceptionHandler whose gotException() method will 
    9279    // get called for each exception encountered 
     
    10491 
    10592//***************** Copied from gli's gui/FormatConversionDialog.java *************// 
     93 
    10694    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    { 
    108102    Process prcs = null; 
    109103    SafeProcess.OutputStreamGobbler inputGobbler = null; 
     
    112106 
    113107    try {        
     108         
    114109        Runtime rt = Runtime.getRuntime();       
     110         
     111         
    115112        if(this.command != null) { 
    116113        prcs = rt.exec(this.command); 
     
    126123             
    127124            if(this.dir == null) { 
    128             System.err.println("\twith: " + Arrays.toString(this.envp)); 
     125            ///System.err.println("\twith: " + Arrays.toString(this.envp)); 
    129126            prcs = rt.exec(this.command_args, this.envp); 
    130127            } else { 
    131             System.err.println("\tfrom directory: " + this.dir); 
    132             System.err.println("\twith: " + Arrays.toString(this.envp)); 
     128            //System.err.println("\tfrom directory: " + this.dir); 
     129            //System.err.println("\twith: " + Arrays.toString(this.envp)); 
    133130            prcs = rt.exec(this.command_args, this.envp, this.dir); 
    134131            } 
     
    136133        } 
    137134 
    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         }        
    160  
     135        // Create the streamgobblers and set any specified handlers on them 
     136 
     137        // PROC INPUT STREAM 
     138        if(procInHandler == null) { 
     139        // send inputStr to process. The following constructor can handle inputStr being null 
     140        inputGobbler = // WriterToProcessInputStream 
     141            new SafeProcess.OutputStreamGobbler(prcs.getOutputStream(), this.inputStr); 
     142        } else { // user will do custom handling of process' InputStream  
     143        inputGobbler = new SafeProcess.OutputStreamGobbler(prcs.getOutputStream(), procInHandler); 
     144        } 
     145 
     146        // PROC ERR STREAM to monitor for any error messages or expected output in the process' stderr 
     147        if(procErrHandler == null) { 
     148        errorGobbler // ReaderFromProcessOutputStream 
     149            = new SafeProcess.InputStreamGobbler(prcs.getErrorStream(), splitStdErrorNewLines);      
     150        } else { 
     151        errorGobbler 
     152            = new SafeProcess.InputStreamGobbler(prcs.getErrorStream(), procErrHandler); 
     153        } 
     154 
     155            // PROC OUT STREAM to monitor for the expected std output line(s) 
     156        if(procOutHandler == null) { 
     157        outputGobbler 
     158            = new SafeProcess.InputStreamGobbler(prcs.getInputStream(), splitStdOutputNewLines); 
     159        } else { 
     160        outputGobbler 
     161            = new SafeProcess.InputStreamGobbler(prcs.getInputStream(), procOutHandler); 
     162        } 
     163 
     164         
    161165            // kick off the stream gobblers 
    162166            inputGobbler.start(); 
    163167            errorGobbler.start(); 
    164168            outputGobbler.start(); 
    165                                      
     169 
    166170            // any error??? 
    167             this.exitValue = prcs.waitFor(); // can throw an InterruptedException if process did not terminate               
     171            this.exitValue = prcs.waitFor(); // can throw an InterruptedException if process did not terminate 
     172 
     173            ///System.err.println("Process exitValue: " + exitValue); 
     174 
    168175        // From the comments of  
    169176        // http://www.javaworld.com/article/2071275/core-java/when-runtime-exec---won-t.html?page=2 
     
    175182        inputGobbler.join();  
    176183         
     184 
    177185        // set the variables the code that created a SafeProcess object may want to inspect 
    178186        this.outputStr = outputGobbler.getOutput(); 
    179187        this.errorStr = errorGobbler.getOutput(); 
    180  
     188         
    181189        // Since we didn't have an exception, process should have terminated now (waitFor blocks until then) 
    182190        // Set process to null so we don't forcibly terminate it below with process.destroy() 
     
    192200        } 
    193201    } catch(InterruptedException ie) { 
     202 
    194203        if(exceptionHandler != null) { 
    195204        exceptionHandler.gotException(ie); 
     
    197206        //logger.error("Process InterruptedException: " + ie.getMessage(), ie); 
    198207        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  
     208        ///ie.printStackTrace(); // an interrupt here is not an error, it can be a cancel action 
     209        } 
    202210 
    203211        // propagate interrupts to worker threads here? 
     
    237245        } 
    238246    } 
    239  
     247     
    240248    return this.exitValue; 
    241249    } 
     
    257265} 
    258266 
    259 // When reading from a process' stdout or stderr stream, you can create a LineByLineHandler 
    260 // to do something on a line by line basis, such as sending the line to a log 
    261 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 line 
     267// write your own run() body for any StreamGobbler 
     268// Make sure your implementation is threadsafe if you're sharing immutable objects between the threaded streams 
     269// example implementation is in the GS2PerlConstructor.SynchronizedProcessHandler class. 
     270public static interface CustomProcessHandler { 
     271    public void run(Closeable stream); //InputStream or OutputStream 
    264272} 
    265273 
     
    270278public static class InputStreamGobbler extends Thread 
    271279{ 
    272     InputStream is = null; 
    273     StringBuffer outputstr = new StringBuffer(); 
    274     boolean split_newlines = false; 
    275     LineByLineHandler lineByLineHandler = null; 
    276      
     280    private InputStream is = null; 
     281    private StringBuffer outputstr = new StringBuffer(); 
     282    private boolean split_newlines = false; 
     283    private CustomProcessHandler customHandler = null; 
     284 
    277285    public InputStreamGobbler(InputStream is) 
    278286    { 
    279287    this.is = is; 
    280     split_newlines = false; 
     288    this.split_newlines = false; 
    281289    } 
    282290     
     
    287295    } 
    288296     
    289     public void setLineByLineHandler(LineByLineHandler lblHandler) { 
    290     lineByLineHandler = lblHandler; 
    291     } 
    292  
    293  
    294     public void run() 
     297    public InputStreamGobbler(InputStream is, CustomProcessHandler customHandler) 
     298    { 
     299    this.is = is; 
     300    this.customHandler = customHandler; 
     301    } 
     302 
     303    // default run() behaviour 
     304    public void runDefault() 
    295305    { 
    296306    BufferedReader br = null; 
     
    307317        //System.out.println("@@@ GOT LINE: " + line); 
    308318        outputstr.append(line); 
    309          
    310319        if(split_newlines) { 
    311320            outputstr.append(Utility.NEWLINE); // "\n" is system dependent (Win must be "\r\n") 
    312321        } 
    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         } 
     322        } 
     323    } catch (IOException ioe) {      
     324        //logger.error("Exception when reading from a process' stdout/stderr stream: ", ioe); 
     325        System.err.println("Exception when reading from a process' stdout/stderr stream: "); 
     326        ioe.printStackTrace();   
    325327         
    326328    } finally { 
     
    329331    } 
    330332     
     333    public void runCustom() { 
     334    this.customHandler.run(is); 
     335    } 
     336     
     337    public void run() { 
     338    if(this.customHandler == null) { 
     339        runDefault(); 
     340    } else { 
     341        runCustom(); 
     342    } 
     343    } 
     344 
    331345    public String getOutput() {  
    332346    return outputstr.toString(); // implicit toString() call anyway. //return outputstr;  
     
    340354public static class OutputStreamGobbler extends Thread 
    341355{ 
    342     OutputStream os = null; 
    343     String inputstr = ""; 
    344     ExceptionHandler exceptionHandler = null; 
     356    private OutputStream os = null; 
     357    private String inputstr = ""; 
     358    private CustomProcessHandler customHandler = null; 
    345359 
    346360    public OutputStreamGobbler(OutputStream os) { 
     
    353367    this.inputstr = inputstr; 
    354368    } 
    355      
    356     public void setExceptionHandler(ExceptionHandler eHandler) { 
    357     exceptionHandler = eHandler; 
    358     } 
    359  
    360     public void run() 
    361     {    
     369 
     370    public OutputStreamGobbler(OutputStream os, CustomProcessHandler customHandler) { 
     371    this.os = os; 
     372    this.customHandler = customHandler; 
     373    } 
     374 
     375    // default run() behaviour 
     376    public void runDefault() { 
     377     
    362378    if (inputstr == null) { 
    363379        return; 
     
    365381     
    366382    BufferedWriter osw = null; 
    367     try { 
     383    try { 
    368384        osw = new BufferedWriter(new OutputStreamWriter(os, "UTF-8")); 
    369385        //System.out.println("@@@ SENDING LINE: " + inputstr); 
     
    385401        */ 
    386402    } 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          
     403        //logger.error("Exception writing to SafeProcess' inputstream: ", ioe); 
     404        System.err.println("Exception writing to SafeProcess' inputstream: "); 
     405        ioe.printStackTrace();   
    394406    } finally { 
    395407        SafeProcess.closeResource(osw); 
    396408    } 
     409    } 
     410 
     411    // call the user's custom handler for the run() method 
     412    public void runCustom() { 
     413    this.customHandler.run(os);  
     414    } 
     415 
     416    public void run() 
     417    { 
     418    if(this.customHandler == null) { 
     419        runDefault(); 
     420    } else { 
     421        runCustom(); 
     422    } 
     423 
    397424    }    
    398425} // end static inner class OutputStreamGobbler