You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by do...@apache.org on 2001/12/23 05:53:27 UTC

cvs commit: jakarta-ant/proposal/myrmidon/src/java/org/apache/myrmidon/framework/exec ProcessMonitor.java

donaldp     01/12/22 20:53:27

  Added:       proposal/myrmidon/src/java/org/apache/myrmidon/framework/exec
                        ProcessMonitor.java
  Log:
  Add in class that will replace ExecuteWatchDog, ExeuteStreamHandler and related classes.
  
  Revision  Changes    Path
  1.1                  jakarta-ant/proposal/myrmidon/src/java/org/apache/myrmidon/framework/exec/ProcessMonitor.java
  
  Index: ProcessMonitor.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included  with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.myrmidon.framework.exec;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  
  /**
   * This class is responsible for monitoring a process.
   * It will monitor a process and if it goes longer than its timeout
   * then it will terminate it. The monitor will also read data from
   * stdout and stderr of process and pass it onto user specified streams.
   * It will also in the future do the same for stdin.
   *
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @version $Revision: 1.1 $ $Date: 2001/12/23 04:53:27 $
   */
  public class ProcessMonitor
      extends AbstractLogEnabled
      implements Runnable
  {
      //Time to sleep in loop while processing output
      //of command and monitoring for timeout
      private final static int SLEEP_TIME = 5;
  
      //State to indicate process is still running
      private static final int STATE_RUNNING = 0;
  
      //State to indicate process shutdown by itself
      private static final int STATE_STOPPED = 1;
  
      //State to indicate process was terminated due to timeout
      private static final int STATE_TERMINATED = 2;
  
      /**
       * The state of the process monitor and thus
       * the state of the underlying process.
       */
      private int m_state = STATE_RUNNING;
  
      /**
       * This is the process we are monitoring.
       */
      private final Process m_process;
  
      /**
       * This specifies the time at which this process will
       * timeout. 0 implies no timeout.
       */
      private final long m_timeout;
  
      /**
       * Stream from which to read standard input.
       */
      private final InputStream m_input;
  
      /**
       * Stream to write standard output to.
       */
      private final OutputStream m_output;
  
      /**
       * Stream to write standard error to.
       */
      private final OutputStream m_error;
  
      public ProcessMonitor( final Process process,
                             final InputStream input,
                             final OutputStream output,
                             final OutputStream error,
                             final long timeoutDuration )
      {
          if( null == process )
          {
              throw new NullPointerException( "process" );
          }
  
          if( 0 > timeoutDuration )
          {
              throw new IllegalArgumentException( "timeoutDuration" );
          }
  
          final long now = System.currentTimeMillis();
          long timeout = 0;
          if( 0 != timeoutDuration )
          {
              timeout = now + timeoutDuration;
          }
  
          m_process = process;
          m_input = input;
          m_output = output;
          m_error = error;
          m_timeout = timeout;
      }
  
      /**
       * Thread method to monitor the state of the process.
       */
      public void run()
      {
          while( STATE_RUNNING == m_state )
          {
              processStandardInput();
              processStandardOutput();
              processStandardError();
  
              if( !isProcessStopped() )
              {
                  checkTimeout();
              }
  
              try
              {
                  Thread.sleep( SLEEP_TIME );
              }
              catch( final InterruptedException ie )
              {
                  //swallow it
              }
          }
      }
  
      /**
       * Check if process has stopped. If it has then update state
       * and return true, else return false.
       */
      private boolean isProcessStopped()
      {
          boolean stopped;
          try
          {
              m_process.exitValue();
              stopped = true;
          }
          catch( final IllegalThreadStateException itse )
          {
              stopped = false;
          }
  
          if( stopped )
          {
              m_state = STATE_STOPPED;
          }
  
          return stopped;
      }
  
      /**
       * Check if the process has exceeded time allocated to it.
       * If it has reached timeout then terminate the process
       * and set state to <code>STATE_TERMINATED</code>.
       */
      private void checkTimeout()
      {
          if( 0 == m_timeout )
          {
              return;
          }
  
          final long now = System.currentTimeMillis();
          if( now > m_timeout )
          {
              m_state = STATE_TERMINATED;
              m_process.destroy();
          }
      }
  
      /**
       * Process the standard input of process.
       * Reading it from user specified stream and copy it
       * to processes standard input stream.
       */
      private void processStandardInput()
      {
          if( null != m_input )
          {
              //Note can not do this as the process may block
              //when written to which will result in this whole
              //thread being blocked. Probably need to write to
              //stdin in another thread
              //copy( m_input, m_process.getOutputStream() );
          }
      }
  
      /**
       * Process the standard output of process.
       * Reading it and sending it to user specified stream
       * or into the void.
       */
      private void processStandardOutput()
      {
          final InputStream input = m_process.getInputStream();
          copy( input, m_output );
      }
  
      /**
       * Process the standard error of process.
       * Reading it and sending it to user specified stream
       * or into the void.
       */
      private void processStandardError()
      {
          final InputStream input = m_process.getInputStream();
          copy( input, m_error );
      }
  
      /**
       * Copy data from specified input stream to output stream if
       * output stream exists. The size of data that should be attempted
       * to read is determined by calling available() on input stream.
       */
      private void copy( final InputStream input,
                         final OutputStream output )
      {
          try
          {
              final int available = input.available();
              if( 0 >= available ) return;
  
              final byte[] data = new byte[ available ];
              final int read = input.read( data );
  
              if( null != output )
              {
                  output.write( data, 0, read );
              }
          }
          catch( final IOException ioe )
          {
              final String message = "Error processing streams";
              getLogger().error( message, ioe );
          }
      }
  }
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>