Class ProcessRunner
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 Summary
-
Constructor Summary
ConstructorDescriptionProcessRunner
(Process process) No-input constructor.ProcessRunner
(Process process, byte[] input) Fixed input constructor.ProcessRunner
(Process process, WriteCallback inputWriter) Dynamic input constructor. -
Method Summary
Modifier and TypeMethodDescriptionGet theProcess
associated with this instance.byte[]
Get the standard error of the process.byte[]
Get the standard output of the process.protected void
Handle notification that the thread invokingrun()
has been interrupted.protected void
handleStandardError
(byte[] buf, int off, int len) Handle data received from the error output of the process.protected void
handleStandardOutput
(byte[] buf, int off, int len) Handle data received from the standard output of the process.int
run()
Send the process its standard input, read its standard output and standard error, and wait for it to exit.void
setDiscardStandardError
(boolean discardStandardError) Set whether to standard error should be discarded.void
setDiscardStandardOutput
(boolean discardStandardOutput) Set whether to standard output should be discarded.
-
Field Details
-
process
-
-
Constructor Details
-
ProcessRunner
No-input constructor.Use this constructor when the process requires no input on
stdin
.- Parameters:
process
- a newly-created process- Throws:
IllegalArgumentException
- ifprocess
is null
-
ProcessRunner
Fixed input constructor.Use this constructor when the process input can be expressed as a
byte[]
array.- Parameters:
process
- newly-created processinput
- process input- Throws:
IllegalArgumentException
- ifprocess
is nullIllegalArgumentException
- ifinput
is null
-
ProcessRunner
Dynamic input constructor.Use this constructor when the process input is computed in an online manner.
- Parameters:
process
- newly-created processinputWriter
- 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
- ifprocess
is null
-
-
Method Details
-
getProcess
Get theProcess
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, thengetStandardOutput()
will throwIllegalStateException
.- Parameters:
discardStandardOutput
- true to discard standard output, otherwise false- Throws:
IllegalStateException
- ifrun()
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, thengetStandardError()
will throwIllegalStateException
.- Parameters:
discardStandardError
- true to discard standard error, otherwise false- Throws:
IllegalStateException
- ifrun()
has already been invoked
-
run
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 overridehandleInterruption()
in order to do that.- Returns:
- exit value
- Throws:
IllegalStateException
- if this method has already been invokedInterruptedException
- if the current thread is interrupted while waiting for the process to finish
-
handleInterruption
protected void handleInterruption()Handle notification that the thread invokingrun()
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 viagetStandardOutput()
. 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 bufferoff
- offset of the first data bytelen
- 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 viagetStandardError()
. 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 bufferoff
- offset of the first data bytelen
- length of the data inbuf
-
getStandardOutput
public byte[] getStandardOutput()Get the standard output of the process.- Returns:
- process standard output
- Throws:
IllegalStateException
- ifrun()
has not been invoked yet or is still executingIllegalStateException
- 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
- ifrun()
has not been invoked yet or is still executingIllegalStateException
- if this instance was configured to discard standard error
-