Package simtools.util

Source Code of simtools.util.SysExec$PrintThread

/* ==============================================
* Simtools : The tools library used in JSynoptic
* ==============================================
*
* Project Info:  http://jsynoptic.sourceforge.net/index.html
*
* This library is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* (C) Copyright 1997-2003, by :
*     Corporate:
*         Astrium SAS (MATRA MARCONI SPACE)
*         EADS CRC
*     Individual:
*         Jean-Louis PATANE
*         Claude Cazenave
*     Nicolas Brodu
*
*
* $Id: SysExec.java,v 1.7 2007/10/23 11:14:00 ogor Exp $
*
* Changes
* -------
* 25-Sep-2003 : Initial public release (NB);
*
*/

package simtools.util ;

import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Vector;
import java.util.logging.Logger;

/**
* This class defines a way to execute system commands
*
* @author Jean-Louis PATANE
*
* @version 1.0, 12/11/97
*/
public class SysExec {

  /**
   * A looger to dump error or warning messages in a soket, an output stream, a file...
   */
  static Logger _logger = simtools.util.LogConfigurator.getLogger(SysExec.class.getName());

 
  /**
   * Constant for process execution error.
   */
  static public final int MISS_ERROR = 999 ;

  /**
   * Constant for process execution error.
   */
  static public final int WAIT_ERROR = 888 ;

  /**
   * Constant for process execution error.
   */
  static public final int EXEC_ERROR = 777 ;

  /**
   * Constant for process execution error.
   */
  static public final int READ_ERROR = 666 ;

  /**
   * Constant for process execution error.
   */
  static public final int SYNC_ERROR = 555 ;

  /**
   * Constant for process execution error.
   */
  static public final int KILL_ERROR = 444 ;

  /**
   * This commands of strings holds process execution commands.
   */
  Vector commands ;
 
  /**
   * This commands of strings holds process environment variables.
   */
  Vector envVariables;
 
  /**
   * This file represent the working directory
   */
  File workingDirectory;

  /**
   * This flag is used by children threads to know if the process is terminated.
   */
  public boolean finished ;

  /**
   * The exit value of the process (0 == ok)
   */
  public int exitValue ;
 
  /**
   *
   */
  public String errorMessage;

  /**
   * This thread manages with the stdout of the process.
   */
  public OutPrintThread outPrintThread ;

  /**
   * This thread manages with the stderr of the process.
   */
  public ErrPrintThread errPrintThread ;

  /**
   * This thread waits for the end of the process.
   */
  public WaitThread waitThread ;

  /**
   * The child process to execute the command line currently built.
   */
  Process process ;

  /**
   * The object where to write output & errors.
   */
  ErrOutWriter writer ;

 
  /**
   * Write output & errors to logger.
   */
  boolean dumpToLogger;
 
 
  /**
   * Initialization of the instance
   * with an empty vector of process execution commands.
   */
  public SysExec() {
    commands = new Vector() ;
    envVariables = new Vector();
    process = null ;
    writer = null ;
    outPrintThread = null ;
    errPrintThread = null ;
    waitThread = null;
    workingDirectory = null;
    dumpToLogger = false;
  }


  /**
   * @param theWriter: an ErrOutWriter object (for output & error streams)
   */
  public SysExec(ErrOutWriter theWriter) {
    this();
    writer = theWriter;
  }
 
  /**
   * @param dumpToLogger: an logger object (for output & error streams)
   */
  public SysExec(boolean dumpToLogger){
    this();
    dumpToLogger = true;
  }

  /**
   * Inner interface for output & error streams.
   */
  public interface ErrOutWriter {
    public void outPrintln(String line);
    public void errPrintln(String line);
  }

  /**
   * Remove all commands in the command line currently built.
   */
  public void reset() {
    envVariables.removeAllElements();
    commands.removeAllElements();
    workingDirectory  = null;
  }

  /**
   * Append a command at the end of the command line currently built.
   *
   * @param command to append at the end of the command line
   * @see UNIX_PreProcH
   * @see MSDOS_PreProc
   */
  public void add(String cmd) {

    commands.addElement(cmd) ;
  }

  /**
   * Stops the currently working process.
   */
  public void killAll() {

    if (process != null) {
      process.destroy() ;
    }
    exitValue = KILL_ERROR ;
  }
 
 
  /**
   * set working directory for SysExec
   * @param workingDirectoryPath : the path
   * @return : true if the working has been correctly set
   */
  public boolean setWorkingDirectory(String workingDirectoryPath){
    boolean result = false;
    workingDirectory = new File(workingDirectoryPath);
      if(workingDirectory.isDirectory()){
        result = true;
      }else{
        workingDirectory = null;
      }
    return result;
  }
 
  /**
   * add an environment variable
   * @param variableName : the name of the variable
   * @param variableValue : th value of the variable
   * @return : true if the variable has been correctly added and, else false
   */
  public boolean addEnvVariable(String variableName, String variableValue){
    boolean result = false;
      if(variableName!=null && variableValue!=null){
        envVariables.add((String)(variableName+"="+variableValue));
        result = true;
      }
    return result;
  }

  /**
   * Create an external child process to execute the command line currently built,
   * and wait for this process terminates.
   *
   * @return the exit value of the process (0 == ok)
   * @see UNIX_PreProcH
   * @see MSDOS_PreProc
   */
  public int run() {

        // First wait for the end of previous run
        while(waitThread != null) {
            try {
                waitThread.join() ;
                continue ;
            }
            catch (NullPointerException e) {
                e.printStackTrace();
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.err.println("Waiting for the end of previous run ...");
        }

        // Get the parameters for the call
        String [] params = (String[]) commands.toArray(new String[commands.size()]);
        //Get the envirronment variable for the call
        String [] env = (String[]) envVariables.toArray(new String[envVariables.size()]);
       
        exitValue = MISS_ERROR ;
        try {

            if(workingDirectory != null){
                //If working directory is not null. (with or wothout env var).
                process = Runtime.getRuntime().exec(params,env,workingDirectory) ;
            }else if(env != null && env.length > 0){
                //Here working directory is null, but there is env var defined.
                process = Runtime.getRuntime().exec(params,env);
            }else{
                //and finally, here there is no env, nor working directory defined.
                process = Runtime.getRuntime().exec(params);
            }
                       
            // Gets the input stream of the subprocess. This stream is usually buffered.
            // The input stream connected to the normal output of the subprocess.
            InputStream processOutInputStream = process.getInputStream() ;

            // Gets the error stream of the subprocess. This stream is usually unbuffered.
            // The input stream connected to the error stream of the subprocess.
            InputStream processErrInputStream = process.getErrorStream() ;

            finished = false ;

            //Starting all the outputs thread.
            outPrintThread = new OutPrintThread(this,processOutInputStream) ;
            errPrintThread = new ErrPrintThread(this,processErrInputStream) ;
            waitThread = new WaitThread(this,process) ;
            outPrintThread.start() ;
            errPrintThread.start() ;
            //waiting for task completion.
            waitThread.start() ;
            waitThread.join() ;
        }catch (IOException ex2) {
            exitValue = EXEC_ERROR ;
            errPrintln("SysExec error : " + ex2) ;
            errorMessage = ex2.getMessage();
        }catch (InterruptedException ex1) {
            exitValue = SYNC_ERROR ;
            errPrintln("SysExec error : " + ex1) ;
            errorMessage = ex1.getMessage();
        }
        //Nullify all threads.
        process = null;
        //Here there is no need to stop the different threads.
        //Since when SysExec.finished become true, these thread will be stopped automatically.
        outPrintThread = null ;
        errPrintThread = null ;
        waitThread = null ;
        //return the result.
        return exitValue ;
  }

  /**
   * This method can be overwritten in a derived class to
   * catch each text line sent by the process in its stdout.
   *
   * @param line A text line sent by the process in its stdout.
   */
  public void outPrintln(String line) {
    if(writer != null) {
      writer.outPrintln(line) ;
     
    }else {
      if (dumpToLogger)
        _logger.fine(line) ;
      else
        System.out.println(line);
    }
  }

  /**
   * This method can be overwritten in a derived class to
   * catch each text line sent by the process in its stderr.
   *
   * @param line A text line sent by the process in its stderr.
   */
  public void errPrintln(String line) {
    if(writer != null) {
      writer.errPrintln(line) ;
     
    }else {
      if (dumpToLogger)
        _logger.severe(line) ;
      else
        System.err.println(line);
    }
  }

  class OutPrintThread extends PrintThread {

    public OutPrintThread(SysExec _parent, InputStream _input) {

      super("OutPrintThread",_parent,_input) ;
    }

    protected void println(String line) {

      parent.outPrintln(line) ;
    }
  }

  class ErrPrintThread extends PrintThread {

    public ErrPrintThread(SysExec _parent, InputStream _input) {

      super("ErrPrintThread",_parent,_input) ;
    }

    protected void println(String line) {

      parent.errPrintln(line) ;
    }
  }

  abstract class PrintThread extends Thread {

    InputStream input ;
    SysExec parent ;

    abstract protected void println(String line) ;

    public PrintThread(String _name, SysExec _parent, InputStream _input) {

      super(_name) ;
      parent = _parent ;
      input = _input ;
    }

    public void run() {

      try {

        StringBuffer tmp = new StringBuffer(200) ;
        DataInputStream r = new DataInputStream(input) ;
        while (! parent.finished) {

          sleep(10);
          while (r.available() > 0) {

            int b = r.readUnsignedByte() ;
            if (b != '\r') {

              if (b == '\n') {

                println(tmp.toString()) ;
                yield() ;
                tmp = new StringBuffer(200) ;
              }
              else {

                tmp.append((char) b) ;
              }
            }
          }
        }
        if (tmp.toString().length() > 0) {

          println(tmp.toString()) ;
        }
      }
      catch (IOException e) {

        parent.exitValue = READ_ERROR ;
        //Do not display IOException, since it can be raised if nominal case is to kill the parent.
        //parent.errPrintln("SysExec error " + getName() + " : " + e) ;
      }
      catch (InterruptedException ie) {

        parent.exitValue = READ_ERROR ;
        parent.errPrintln("SysExec error " + getName() + " : " + ie) ;
      }
    }
  }

  class WaitThread extends Thread {

    SysExec parent ;
    Process process ;

    public WaitThread(SysExec _parent, Process _process) {

      super("WaitThread") ;
      parent = _parent ;
      process = _process ;
    }

    public void run() {

      try {

        parent.exitValue = process.waitFor() ;
      }
      catch (InterruptedException e) {

        parent.exitValue = WAIT_ERROR ;
        parent.errPrintln("SysExec error " + getName() + " : " + e) ;
      }
      try {

        parent.finished = true ;
        parent.outPrintThread.join() ;
        parent.errPrintThread.join() ;
      }
      catch (InterruptedException e) {

        parent.exitValue = SYNC_ERROR ;
        parent.errPrintln("SysExec error " + getName() + " : " + e) ;
      }
      catch (NullPointerException e) {

        parent.exitValue = SYNC_ERROR ;
        parent.errPrintln("SysExec error " + getName() + " : " + e) ;
      }
    }
  }



  public void print() {
   
    Enumeration e = commands.elements() ;
    while (e.hasMoreElements()) {
     
      _logger.fine("--> \"" + (String) e.nextElement() + "\"") ;
     }
   }
 
  public static void main(String args[]) {
    SysExec se = new SysExec() ;

    se.add("sh") ;
    se.add("-c") ;
    se.add("ls > ls.txt") ;
    se.print() ;
    se.run() ;

    se.reset() ;
    se.add("cat") ;
    se.add("ls.txt") ;
    se.print() ;
    se.run() ;
  }
}
TOP

Related Classes of simtools.util.SysExec$PrintThread

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.