Class ProcessRunner

java.lang.Object
org.dellroad.stuff.java.ProcessRunner

public class ProcessRunner extends Object
Handles external process I/O and async execution.

This class makes it convenient to execute an external process and gather it's output without having to deal directly with the inherent issues relating to threads, race conditions, and deadlocks.

Standard input can be specified in three ways, either as empty, a fixed buffer, or written dynamically via callback. Standard output and error are by default collected into buffers. Alternatively, you can configure either or both to be discarded, or override the corresponding handler methods for arbitrary action. These handler methods and the standard input callback, if any, will be invoked from independent threads.

  • Field Details

    • process

      protected final Process process
  • Constructor Details

    • ProcessRunner

      public ProcessRunner(Process process)
      No-input constructor.

      Use this constructor when the process requires no input on stdin.

      Parameters:
      process - a newly-created process
      Throws:
      IllegalArgumentException - if process is null
    • ProcessRunner

      public ProcessRunner(Process process, byte[] input)
      Fixed input constructor.

      Use this constructor when the process input can be expressed as a byte[] array.

      Parameters:
      process - newly-created process
      input - process input
      Throws:
      IllegalArgumentException - if process is null
      IllegalArgumentException - if input is null
    • ProcessRunner

      public ProcessRunner(Process process, WriteCallback inputWriter)
      Dynamic input constructor.

      Use this constructor when the process input is computed in an online manner.

      Parameters:
      process - newly-created process
      inputWriter - object capable of writing input to the process, which will be invoked from a separate thread, or null if the process does not get any input
      Throws:
      IllegalArgumentException - if process is null
  • Method Details

    • getProcess

      public Process getProcess()
      Get the Process associated with this instance.
      Returns:
      associated process
    • setDiscardStandardOutput

      public void setDiscardStandardOutput(boolean discardStandardOutput)
      Set whether to standard output should be discarded. Default is false. If configured to discard, then getStandardOutput() will throw IllegalStateException.
      Parameters:
      discardStandardOutput - true to discard standard output, otherwise false
      Throws:
      IllegalStateException - if run() has already been invoked
    • setDiscardStandardError

      public void setDiscardStandardError(boolean discardStandardError)
      Set whether to standard error should be discarded. Default is false. If configured to discard, then getStandardError() will throw IllegalStateException.
      Parameters:
      discardStandardError - true to discard standard error, otherwise false
      Throws:
      IllegalStateException - if run() has already been invoked
    • run

      public int run() throws InterruptedException
      Send the process its standard input, read its standard output and standard error, and wait for it to exit.

      If the current thread is interrupted, the standard input, output, and error connections to the process are closed and an InterruptedException is thrown. However, the process itself is not explicitly killed; you can override handleInterruption() in order to do that.

      Returns:
      exit value
      Throws:
      IllegalStateException - if this method has already been invoked
      InterruptedException - if the current thread is interrupted while waiting for the process to finish
    • handleInterruption

      protected void handleInterruption()
      Handle notification that the thread invoking run() has been interrupted.

      The implementation in ProcessRunner does nothing. Subclasses that want to kill the process may do so here.

    • handleStandardOutput

      protected void handleStandardOutput(byte[] buf, int off, int len)
      Handle data received from the standard output of the process.

      The implementation in ProcessRunner simply discards the data if this instance is configured to do so, otherwise it adds the data to an in-memory buffer, which is made available when the process completes via getStandardOutput(). Subclasses may override if necessary, e.g., to send/mirror the data elsewhere.

      This method will be invoked by a separate thread from the one that invoked run().

      Parameters:
      buf - data buffer
      off - offset of the first data byte
      len - length of the data
    • handleStandardError

      protected void handleStandardError(byte[] buf, int off, int len)
      Handle data received from the error output of the process.

      The implementation in ProcessRunner simply discards the data if this instance is configured to do so, otherwise it adds the data to an in-memory buffer, which is made available when the process completes via getStandardError(). Subclasses may override if necessary, e.g., to send/mirror the data elsewhere.

      This method will be invoked by a separate thread from the one that invoked run().

      Parameters:
      buf - data buffer
      off - offset of the first data byte
      len - length of the data in buf
    • getStandardOutput

      public byte[] getStandardOutput()
      Get the standard output of the process.
      Returns:
      process standard output
      Throws:
      IllegalStateException - if run() has not been invoked yet or is still executing
      IllegalStateException - if this instance was configured to discard standard output
    • getStandardError

      public byte[] getStandardError()
      Get the standard error of the process.
      Returns:
      process standard error output
      Throws:
      IllegalStateException - if run() has not been invoked yet or is still executing
      IllegalStateException - if this instance was configured to discard standard error