Class ExternalProcess


  • public final class ExternalProcess
    extends Object
    Utility class to execute an external process and to handle the STDOUT, STDERR and STDIN streams in multiple threads managed by a thread pool.

    This class is intended for applications that call an external program many times, e.g. in a loop, and that need high performance throughput, i.e. the program's input and output should not be written to disk. The Java Runtime.exec(java.lang.String) methods requires the application to read/write the external program's input and output streams in multiple threads. Otherwise the calling application may block. However, instantiating multiple threads for each call is extensive. On Linux systems there is also the problem that each Java thread is represented by a single process and the number of processes is limited on Linux. Because the Java garbage collector does not free the Thread objects properly, an application might run out of threads (indicated by a OutOfMemoryError exception) after multiple iterations. Therefore, the ExternalProcess class uses a thread pool.

    The simplest way to use this class is by calling the static methods execute(String) and execute(String, String, StringWriter, StringWriter). However, these methods are not thread safe and no configuration is possible. In the former case the program's input, output and error output is redirected to STDIN, STDOUT and STDERR of the calling program. In the latter case input is provided as string and output and error output is written to StringWriter objects. The environment, i.e. the current working directory and the environment variables, are inherited from the calling process. In both cases, a static thread pool of size THREAD_POOL_SIZE is used. The command that should be executed is provided as a string argument.

    In scenarios where the environment has to be changed, the program input is generated just in time, or the program's output is parsed just in time, the use of an explicit instance of the ExternalProcess class is recommended. This instance could be initialized with a custom thread pool. Otherwise a SimpleThreadPool of size 3 is used. The input and output is managed by multithreaded input handler and output handler objects. There are four predefined handlers that read the program's input from a Reader object or a InputStream object and write the program's output to a Writer object or a OutputStream object. These classes are called: ReaderInputHandler, SimpleInputHandler, WriterOutputHandler and SimpleOutputHandler. If no handlers are specified the input and output is redirected to the standards streams of the calling process.

    Before one of the methods execute() or execute(Properties) is called, the commands property should be set. One may include placeholders of the form %PARAM% within the commands. If a Properties object is passed to the execute(Properties) method, the placeholders are replaced by the particular property value. Therefore, the Properties object must contain a key named PARAM (case doesn't matter). The environment for calling the external program can be configured using the properties workingDirectory and environmentProperties.

    Finally, the sleepTime property can be increased, in case the output handlers are not able to catch the whole program's output within the given time. The default value is SLEEP_TIME [in milliseconds].

    Version:
    $Revision$
    Author:
    Martin Szugat
    See Also:
    Process
    • Constructor Detail

      • ExternalProcess

        public ExternalProcess()
        Initializes the external process.
      • ExternalProcess

        public ExternalProcess​(ThreadPool threadPool)
        Initializes the external process.
        Parameters:
        threadPool - a thread pool with at least three threads or null if the default thread pool should be used
    • Method Detail

      • main

        public static void main​(String[] args)
        Runs an external program from the command line. The external process inherits the environment variables and the current working directory from the parent process.
        Parameters:
        args - the path or the name of the external program and its command line arguments
      • resolveCommands

        public static String resolveCommands​(String commands,
                                             Properties variables)
                                      throws NullPointerException
        Resolves the given command line by replacing all placeholder of the format %NAME% with the values from the given properties for the corresponding keys of the format NAME.
        Parameters:
        commands - the given command line
        variables - the placeholders or null if no resolvement should be performed
        Returns:
        the new command line
        Throws:
        NullPointerException - if commands is null.
      • execute

        public static int execute​(String commands)
                           throws IOException,
                                  InterruptedException,
                                  NullPointerException,
                                  SecurityException,
                                  IllegalArgumentException
        Executes an external program. The working directory and the environment variables are inherited from the parent process. The program input is read from STDIN, the program output is written to STDOUT and the program error output is written to STDERR.

        Note: This method is not thread-safe.

        Parameters:
        commands - the command line including the path or the name of the external program and its command line arguments
        Returns:
        the exit code from the external program
        Throws:
        SecurityException - if a security manager exists and its checkExec method doesn't allow creation of a subprocess.
        IOException - if an I/O error occurs.
        NullPointerException - if commands is null.
        IllegalArgumentException - if commandList is empty.
        InterruptedException - if the current thread is interrupted by another thread while it is waiting, then the wait is ended and an InterruptedException is thrown.
      • execute

        public static int execute​(String commands,
                                  String inputString,
                                  StringWriter outputString,
                                  StringWriter errorString)
                           throws IOException,
                                  InterruptedException,
                                  NullPointerException,
                                  SecurityException,
                                  IllegalArgumentException
        Executes an external program. The working directory and the environment variables are inherited from the parent process.

        Note: This method is not thread-safe.

        Parameters:
        commands - the command line including the path or the name of the external program and its command line arguments
        inputString - the input for the external programm or null if the input should be read from STDIN
        outputString - the output of the external programm or null if the output should be written to STDOUT
        errorString - the error output of the external program or null if the error output should be written to STDERR
        Returns:
        the exit code from the external program
        Throws:
        SecurityException - if a security manager exists and its checkExec method doesn't allow creation of a subprocess.
        IOException - if an I/O error occurs.
        NullPointerException - if commandList is null.
        IllegalArgumentException - if commandList is empty.
        InterruptedException - if the current thread is interrupted by another thread while it is waiting, then the wait is ended and an InterruptedException is thrown.
      • getCommands

        public String getCommands()
        Gets the command line including the path or name of the external program and its command line arguments.
        Returns:
        the command line
      • setCommands

        public void setCommands​(String commands)
                         throws NullPointerException
        Sets the command line including the path or name of the external program and its command line arguments.
        Parameters:
        commands - the command line
        Throws:
        NullPointerException - if commands is null.
      • getEnvironmentProperties

        public String[] getEnvironmentProperties()
        Gets environment variables for the external process.
        Returns:
        a list of strings in the format name=value or null if the environment variables should be inherited from the parent process
      • setEnvironmentProperties

        public void setEnvironmentProperties​(String[] environmentProperties)
        Sets environment variables for the external process.
        Parameters:
        environmentProperties - a list of strings in the format name=value or null if the environment variables should be inherited from the parent process
      • getErrorHandler

        public OutputHandler getErrorHandler()
        Gets the output error handler which is responsible for the standard error output of the external process.
        Returns:
        the error output handler
      • setErrorHandler

        public void setErrorHandler​(OutputHandler errorHandler)
        Sets the output error handler which is responsible for the standard error output of the external process.
        Parameters:
        errorHandler - the error output handler or null if the error output should be redirected to STDERR
      • getInputHandler

        public InputHandler getInputHandler()
        Gets the input handler which is responsible for the standard input of the external process.
        Returns:
        the input handler
      • setInputHandler

        public void setInputHandler​(InputHandler inputHandler)
        Sets the input handler which is responsible for the standard input of the external process.
        Parameters:
        inputHandler - the input handler or null if the input should be read from STDIN
      • getOutputHandler

        public OutputHandler getOutputHandler()
        Gets the output handler which is responsible for the standard output of the external process.
        Returns:
        the output handler
      • setOutputHandler

        public void setOutputHandler​(OutputHandler outputHandler)
        Sets the output handler which is responsible for the standard output of the external process.
        Parameters:
        outputHandler - the output handler or null if the output should be redirected to STDOUT
      • threadPool

        public ThreadPool threadPool()
        Gets the thread pool which is used for the input and output handlers.
        Returns:
        a thread pool with at least three threads
      • getWorkingDirectory

        public File getWorkingDirectory()
        Gets the working directory for the external process.
        Returns:
        the working directory or null if it should be inherited from the parent process
      • setWorkingDirectory

        public void setWorkingDirectory​(File workingDirectory)
        Sets the working directory for the external process.
        Parameters:
        workingDirectory - the working directory or null if it should be inherited from the parent process
      • getSleepTime

        public int getSleepTime()
        Gets the number of milliseconds the execute(Properties) method should pauses after the external process is terminated. This gives the stream handlers the time to complete their work.
        Returns:
        time in milliseconds
      • setSleepTime

        public void setSleepTime​(int sleepTime)
                          throws IllegalArgumentException
        Sets the number of milliseconds the execute(Properties) method should pauses after the external process is terminated. Increase this value if the output handlers didn't catch the whole program output.
        Parameters:
        sleepTime - time in milliseconds
        Throws:
        IllegalArgumentException - if sleepTime is negative.