/******************************************************************************* * Copyright (c) 2010 Robert "Unlogic" Olofsson (unlogic@unlogic.se). * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser Public License v3 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/lgpl-3.0-standalone.html ******************************************************************************/ package se.unlogic.standardutils.exec; import java.io.IOException; import java.io.OutputStream; /** * Utility class for executing processes and handling the output from them. * * @author Robert "Unlogic" Olofsson (unlogic@unlogic.se) * */ public class ExecUtils { /** * Executes the given command and waits for the resulting processes to terminate and all data written to standard out and error out to be handled.<p> * * All data written to standard out is piped to System.out with the given prefix<p> * * All data written to error out is piped to System.err with the given prefix<p> * * @param command the command to executed * @param timeout an optional timeout that controls how long the process i allowed to run before it is killed * @return the exit value of the process. By convention, 0 indicates normal termination. * @throws IOException * @throws InterruptedException */ public static int execAndWait(String command, Long timeout) throws IOException, InterruptedException { Runtime rt = Runtime.getRuntime(); Process proc = rt.exec(command); try{ StreamHandler errorOutHandler = new StreamPrinter(System.err); StreamHandler stdOutHandler = new StreamPrinter(); errorOutHandler.handleStream(proc.getErrorStream()); stdOutHandler.handleStream(proc.getInputStream()); return waitForProcessAndStreams(proc,stdOutHandler,errorOutHandler, timeout); }finally{ if(proc != null){ proc.destroy(); } } } /** * Executes the given command and waits for the resulting processes to terminate and all data written to standard out and error out to be handled.<p> * * @param command the command to executed * @param stdOutHandler the {@link StreamHandler} to handle all output the process writes on standard out * @param errorOutHandler the {@link StreamHandler} to handle all output the process writes on error out * @param timeout an optional timeout that controls how long the process i allowed to run before it is killed * @return the exit value of the process. By convention, 0 indicates normal termination. * @throws IOException * @throws InterruptedException */ public static int execAndWait(String command, StreamHandler stdOutHandler, StreamHandler errorOutHandler, Long timeout) throws IOException, InterruptedException { Runtime rt = Runtime.getRuntime(); Process proc = rt.exec(command); try{ errorOutHandler.handleStream(proc.getErrorStream()); stdOutHandler.handleStream(proc.getInputStream()); return waitForProcessAndStreams(proc,stdOutHandler,errorOutHandler,timeout); }finally{ if(proc != null){ proc.destroy(); } } } /** * Executes the given command and waits for the resulting processes to terminate and all data written to standard out and error out to be handled.<p> * * All data written to standard out and error out is piped to the given {@link OutputStream}<p> * * @param command the command to executed * @param outputStream the {@link OutputStream} to handle all output of the process * @param timeout an optional timeout that controls how long the process i allowed to run before it is killed * @return the exit value of the process. By convention, 0 indicates normal termination. * @throws IOException * @throws InterruptedException */ public static int execAndWait(String command, OutputStream outputStream, Long timeout) throws IOException, InterruptedException { Runtime rt = Runtime.getRuntime(); Process proc = rt.exec(command); try{ StreamHandler errorOutHandler = new StreamPrinter(outputStream); StreamHandler stdOutHandler = new StreamPrinter(outputStream); errorOutHandler.handleStream(proc.getErrorStream()); stdOutHandler.handleStream(proc.getInputStream()); return waitForProcessAndStreams(proc,stdOutHandler,errorOutHandler, timeout); }finally{ if(proc != null){ proc.destroy(); } } } /** * Executes the given command and waits for the resulting processes to terminate and all data written to standard out and error out to be handled.<p> * * All data written to standard out and error out is piped to the given {@link OutputStream}<p> * * @param builder the ProcessBuilder to get to start the Process through * @param outputStream the {@link OutputStream} to handle all output of the process * @param timeout an optional timeout that controls how long the process i allowed to run before it is killed * @return the exit value of the process. By convention, 0 indicates normal termination. * @throws IOException * @throws InterruptedException */ public static int execAndWait(ProcessBuilder builder, OutputStream outputStream, Long timeout) throws IOException, InterruptedException { Process proc = builder.start(); try{ StreamHandler errorOutHandler = new StreamPrinter(outputStream); StreamHandler stdOutHandler = new StreamPrinter(outputStream); errorOutHandler.handleStream(proc.getErrorStream()); stdOutHandler.handleStream(proc.getInputStream()); return waitForProcessAndStreams(proc,stdOutHandler,errorOutHandler, timeout); }finally{ if(proc != null){ proc.destroy(); } } } /** * Waits for the given processes to terminate and all data written to standard out and error out to be handled.<p> * * All data written to standard out and error out is piped to the given {@link OutputStream}<p> * * @param command the command to executed * @param outputStream the {@link OutputStream} to handle all output of the process * @return the exit value of the process. By convention, 0 indicates normal termination. * @throws IOException * @throws InterruptedException */ public static int waitForProcessAndStreams(Process proc, StreamHandler stdOutHandler, StreamHandler errorOutHandler, Long timeout) throws InterruptedException { int exitVal; if(timeout != null){ long elapsedTimeout = 0; while(true){ if(elapsedTimeout > timeout){ proc.destroy(); } Thread.sleep(100); try{ exitVal = proc.exitValue(); break; }catch(IllegalThreadStateException e){ elapsedTimeout += 100; } } exitVal = proc.exitValue(); stdOutHandler.terminate(); errorOutHandler.terminate(); }else{ exitVal = proc.waitFor(); } if(!stdOutHandler.isFinished()){ stdOutHandler.awaitFinish(); } if(errorOutHandler != null){ if(!errorOutHandler.isFinished()){ errorOutHandler.awaitFinish(); } } return exitVal; } }