Mega Code Archive

 
Categories / Java / Development Class
 

Exec Helper

/*  * Convenience methods for executing non-Java processes.  * Copyright (C) 2005 Stephen Ostermiller  * http://ostermiller.org/contact.pl?regarding=Java+Utilities  *  * This program is free software; you can redistribute it and/or modify  * it under the terms of the GNU General Public License as published by  * the Free Software Foundation; either version 2 of the License, or  * (at your option) any later version.  *  * This program 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 General Public License for more details.  *  * See COPYING.TXT for details.  */ import java.io.*; /**  * Convenience methods for executing non-Java processes.  * More information about this class is available from <a target="_top" href=  * "http://ostermiller.org/utils/ExecHelper.html">ostermiller.org</a>.  *  * @author Stephen Ostermiller http://ostermiller.org/contact.pl?regarding=Java+Utilities  * @since ostermillerutils 1.06.00  */ public final class ExecHelper {   /**    * Executes the specified command and arguments in a separate process, and waits for the    * process to finish.    * <p>    * Output from the process is expected to be text in the system's default character set.    * <p>    * No input is passed to the process on STDIN.    *    * @param cmdarray array containing the command to call and its arguments.    * @return The results of the execution in an ExecHelper object.    * @throws SecurityException if a security manager exists and its checkExec method doesn't allow creation of a subprocess.    * @throws IOException - if an I/O error occurs    * @throws NullPointerException - if cmdarray is null    * @throws IndexOutOfBoundsException - if cmdarray is an empty array (has length 0).    *    * @since ostermillerutils 1.06.00    */   public static ExecHelper exec(String[] cmdarray) throws IOException {     return new ExecHelper(Runtime.getRuntime().exec(cmdarray), null);   }   /**    * Executes the specified command and arguments in a separate process, and waits for the    * process to finish.    * <p>    * Output from the process is expected to be text in the system's default character set.    * <p>    * No input is passed to the process on STDIN.    *    * @param cmdarray array containing the command to call and its arguments.    * @param envp array of strings, each element of which has environment variable settings in format name=value.    * @return The results of the execution in an ExecHelper object.    * @throws SecurityException if a security manager exists and its checkExec method doesn't allow creation of a subprocess.    * @throws IOException - if an I/O error occurs    * @throws NullPointerException - if cmdarray is null    * @throws IndexOutOfBoundsException - if cmdarray is an empty array (has length 0).    *    * @since ostermillerutils 1.06.00    */   public static ExecHelper exec(String[] cmdarray, String[] envp) throws IOException {     return new ExecHelper(Runtime.getRuntime().exec(cmdarray, envp), null);   }   /**    * Executes the specified command and arguments in a separate process, and waits for the    * process to finish.    * <p>    * Output from the process is expected to be text in the system's default character set.    * <p>    * No input is passed to the process on STDIN.    *    * @param cmdarray array containing the command to call and its arguments.    * @param envp array of strings, each element of which has environment variable settings in format name=value.    * @param dir the working directory of the subprocess, or null if the subprocess should inherit the working directory of the current process.    * @return The results of the execution in an ExecHelper object.    * @throws SecurityException if a security manager exists and its checkExec method doesn't allow creation of a subprocess.    * @throws IOException - if an I/O error occurs    * @throws NullPointerException - if cmdarray is null    * @throws IndexOutOfBoundsException - if cmdarray is an empty array (has length 0).    *    * @since ostermillerutils 1.06.00    */   public static ExecHelper exec(String[] cmdarray, String[] envp, File dir) throws IOException {     return new ExecHelper(Runtime.getRuntime().exec(cmdarray, envp, dir), null);   }   /**    * Executes the specified command and arguments in a separate process, and waits for the    * process to finish.    * <p>    * No input is passed to the process on STDIN.    *    * @param cmdarray array containing the command to call and its arguments.    * @param charset Output from the executed command is expected to be in this character set.    * @return The results of the execution in an ExecHelper object.    * @throws SecurityException if a security manager exists and its checkExec method doesn't allow creation of a subprocess.    * @throws IOException - if an I/O error occurs    * @throws NullPointerException - if cmdarray is null    * @throws IndexOutOfBoundsException - if cmdarray is an empty array (has length 0).    *    * @since ostermillerutils 1.06.00    */   public static ExecHelper exec(String[] cmdarray, String charset) throws IOException {     return new ExecHelper(Runtime.getRuntime().exec(cmdarray), charset);   }   /**    * Executes the specified command and arguments in a separate process, and waits for the    * process to finish.    * <p>    * No input is passed to the process on STDIN.    *    * @param cmdarray array containing the command to call and its arguments.    * @param envp array of strings, each element of which has environment variable settings in format name=value.    * @param charset Output from the executed command is expected to be in this character set.    * @return The results of the execution in an ExecHelper object.    * @throws SecurityException if a security manager exists and its checkExec method doesn't allow creation of a subprocess.    * @throws IOException - if an I/O error occurs    * @throws NullPointerException - if cmdarray is null    * @throws IndexOutOfBoundsException - if cmdarray is an empty array (has length 0).    *    * @since ostermillerutils 1.06.00    */   public static ExecHelper exec(String[] cmdarray, String[] envp, String charset) throws IOException {     return new ExecHelper(Runtime.getRuntime().exec(cmdarray, envp), charset);   }   /**    * Executes the specified command and arguments in a separate process, and waits for the    * process to finish.    * <p>    * No input is passed to the process on STDIN.    *    * @param cmdarray array containing the command to call and its arguments.    * @param envp array of strings, each element of which has environment variable settings in format name=value.    * @param dir the working directory of the subprocess, or null if the subprocess should inherit the working directory of the current process.    * @param charset Output from the executed command is expected to be in this character set.    * @return The results of the execution in an ExecHelper object.    * @throws SecurityException if a security manager exists and its checkExec method doesn't allow creation of a subprocess.    * @throws IOException - if an I/O error occurs    * @throws NullPointerException - if cmdarray is null    * @throws IndexOutOfBoundsException - if cmdarray is an empty array (has length 0).    *    * @since ostermillerutils 1.06.00    */   public static ExecHelper exec(String[] cmdarray, String[] envp, File dir, String charset) throws IOException {     return new ExecHelper(Runtime.getRuntime().exec(cmdarray, envp, dir), charset);   }   /**    * Executes the specified command using a shell.  On windows uses cmd.exe or command.exe.    * On other platforms it uses /bin/sh.    * <p>    * A shell should be used to execute commands when features such as file redirection, pipes,    * argument parsing are desired.    * <p>    * Output from the process is expected to be text in the system's default character set.    * <p>    * No input is passed to the process on STDIN.    *    * @param command String containing a command to be parsed by the shell and executed.    * @return The results of the execution in an ExecHelper object.    * @throws SecurityException if a security manager exists and its checkExec method doesn't allow creation of a subprocess.    * @throws IOException - if an I/O error occurs    * @throws NullPointerException - if command is null    *    * @since ostermillerutils 1.06.00    */   public static ExecHelper execUsingShell(String command) throws IOException {     return execUsingShell(command, null);   }   /**    * Executes the specified command using a shell.  On windows uses cmd.exe or command.exe.    * On other platforms it uses /bin/sh.    * <p>    * A shell should be used to execute commands when features such as file redirection, pipes,    * argument parsing are desired.    * <p>    * No input is passed to the process on STDIN.    *    * @param command String containing a command to be parsed by the shell and executed.    * @param charset Output from the executed command is expected to be in this character set.    * @return The results of the execution in an ExecHelper object.    * @throws SecurityException if a security manager exists and its checkExec method doesn't allow creation of a subprocess.    * @throws IOException - if an I/O error occurs    * @throws NullPointerException - if command is null    *    * @since ostermillerutils 1.06.00    */   public static ExecHelper execUsingShell(String command, String charset) throws IOException {     if (command == null) throw new NullPointerException();     String[] cmdarray;     String os = System.getProperty("os.name");     if (os.equals("Windows 95") || os.equals("Windows 98") || os.equals("Windows ME")){       cmdarray = new String[]{"command.exe", "/C", command};     } else if (os.startsWith("Windows")){       cmdarray = new String[]{"cmd.exe", "/C", command};     } else {       cmdarray = new String[]{"/bin/sh", "-c", command};     }     return new ExecHelper(Runtime.getRuntime().exec(cmdarray), charset);   }   /**    * Take a process, record its standard error and standard out streams, wait for it to finish    *    * @param process process to watch    * @throws SecurityException if a security manager exists and its checkExec method doesn't allow creation of a subprocess.    * @throws IOException - if an I/O error occurs    * @throws NullPointerException - if cmdarray is null    * @throws IndexOutOfBoundsException - if cmdarray is an empty array (has length 0).    *    * @since ostermillerutils 1.06.00    */   private ExecHelper(Process process, String charset) throws IOException {     StringBuffer output = new StringBuffer();     StringBuffer error = new StringBuffer();     Reader stdout;     Reader stderr;     if (charset == null){       // This is one time that the system charset is appropriate,       // don't specify a character set.       stdout = new InputStreamReader(process.getInputStream());       stderr = new InputStreamReader(process.getErrorStream());     } else {       stdout = new InputStreamReader(process.getInputStream(), charset);       stderr = new InputStreamReader(process.getErrorStream(), charset);     }     char[] buffer = new char[1024];     boolean done = false;     boolean stdoutclosed = false;     boolean stderrclosed = false;     while (!done){       boolean readSomething = false;       // read from the process's standard output       if (!stdoutclosed && stdout.ready()){         readSomething = true;         int read = stdout.read(buffer, 0, buffer.length);         if (read < 0){           readSomething = true;           stdoutclosed = true;         } else if (read > 0){           readSomething = true;           output.append(buffer, 0, read);         }       }       // read from the process's standard error       if (!stderrclosed && stderr.ready()){         int read = stderr.read(buffer, 0, buffer.length);         if (read < 0){           readSomething = true;           stderrclosed = true;         } else if (read > 0){           readSomething = true;           error.append(buffer, 0, read);         }       }       // Check the exit status only we haven't read anything,       // if something has been read, the process is obviously not dead yet.       if (!readSomething){         try {           this.status = process.exitValue();           done = true;         } catch (IllegalThreadStateException itx){           // Exit status not ready yet.           // Give the process a little breathing room.           try {             Thread.sleep(100);           } catch (InterruptedException ix){             process.destroy();             throw new IOException("Interrupted - processes killed");           }         }       }     }     this.output = output.toString();     this.error = error.toString();   }   /**    * The output of the job that ran.    *    * @since ostermillerutils 1.06.00    */   private String output;   /**    * Get the output of the job that ran.    *    * @return Everything the executed process wrote to its standard output as a String.    *    * @since ostermillerutils 1.06.00    */   public String getOutput(){     return output;   }   /**    * The error output of the job that ran.    *    * @since ostermillerutils 1.06.00    */   private String error;   /**    * Get the error output of the job that ran.    *    * @return Everything the executed process wrote to its standard error as a String.    *    * @since ostermillerutils 1.06.00    */   public String getError(){     return error;   }   /**    * The status of the job that ran.    *    * @since ostermillerutils 1.06.00    */   private int status;   /**    * Get the status of the job that ran.    *    * @return exit status of the executed process, by convention, the value 0 indicates normal termination.    *    * @since ostermillerutils 1.06.00    */   public int getStatus(){     return status;   } }