001 /*--------------------------------------------------------------------------+ 002 $Id: ProcessUtils.java 26268 2010-02-18 10:44:30Z juergens $ 003 | | 004 | Copyright 2005-2010 Technische Universitaet Muenchen | 005 | | 006 | Licensed under the Apache License, Version 2.0 (the "License"); | 007 | you may not use this file except in compliance with the License. | 008 | You may obtain a copy of the License at | 009 | | 010 | http://www.apache.org/licenses/LICENSE-2.0 | 011 | | 012 | Unless required by applicable law or agreed to in writing, software | 013 | distributed under the License is distributed on an "AS IS" BASIS, | 014 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 015 | See the License for the specific language governing permissions and | 016 | limitations under the License. | 017 +--------------------------------------------------------------------------*/ 018 package edu.tum.cs.commons.io; 019 020 import java.io.IOException; 021 import java.io.OutputStreamWriter; 022 import java.io.Writer; 023 024 /** 025 * Executes a system process. Takes care of reading stdout and stderr of the 026 * process in separate threads to avoid blocking. 027 * 028 * @author juergens 029 * @author $Author: juergens $ 030 * @version $Rev: 26268 $ 031 * @levd.rating GREEN Hash: 4D8721B16BD1F29DDCC9C144FC6E0BCC 032 */ 033 public class ProcessUtils { 034 035 /** 036 * Executes a process in a thread-safe way. 037 * 038 * @param completeArguments 039 * Array of command line arguments to start the process 040 * 041 * @return result of the execution 042 */ 043 public static ExecutionResult execute(String[] completeArguments) 044 throws IOException { 045 return execute(completeArguments, null); 046 } 047 048 /** 049 * Executes a process in a thread-safe way. 050 * 051 * @param completeArguments 052 * Array of command line arguments to start the process 053 * @param input 054 * String that gets written to stdin 055 * 056 * @return result of the execution 057 */ 058 public static ExecutionResult execute(String[] completeArguments, 059 String input) throws IOException { 060 ProcessBuilder builder = new ProcessBuilder(completeArguments); 061 return execute(builder, input); 062 } 063 064 /** 065 * Executes a process in a thread-safe way. 066 * 067 * @param builder 068 * builder that gets executed 069 * @return result of the execution 070 */ 071 public static ExecutionResult execute(ProcessBuilder builder) 072 throws IOException { 073 return execute(builder, null); 074 } 075 076 /** 077 * Executes a process in a thread-safe way. 078 * 079 * @param builder 080 * builder that gets executed 081 * @param input 082 * String that gets written to stdin 083 * @return result of the execution 084 */ 085 public static ExecutionResult execute(ProcessBuilder builder, String input) 086 throws IOException { 087 // start process 088 Process process = builder.start(); 089 090 // read error for later use 091 StreamReaderThread stderrReader = new StreamReaderThread(process 092 .getErrorStream()); 093 StreamReaderThread stdoutReader = new StreamReaderThread(process 094 .getInputStream()); 095 096 // write input to process 097 if (input != null) { 098 Writer stdIn = new OutputStreamWriter(process.getOutputStream()); 099 stdIn.write(input); 100 stdIn.close(); 101 } 102 103 // wait for process 104 try { 105 process.waitFor(); 106 107 // It is important to wait for the threads, so the output is 108 // completely stored. 109 stderrReader.join(); 110 stdoutReader.join(); 111 112 } catch (InterruptedException e) { 113 // ignore this one 114 } 115 116 return new ExecutionResult(stdoutReader.getContent(), stderrReader 117 .getContent(), process.exitValue()); 118 } 119 120 /** 121 * Parameter object that encapsulates the result of a process execution. 122 * This object is immutable. 123 */ 124 public static class ExecutionResult { 125 126 /** Output on stdout of the process */ 127 private final String stdout; 128 129 /** Output on stderr of the process */ 130 private final String stderr; 131 132 /** Return code of the process */ 133 private final int returnCode; 134 135 /** Constructor */ 136 private ExecutionResult(String stdout, String stderr, int returnCode) { 137 this.stdout = stdout; 138 this.stderr = stderr; 139 this.returnCode = returnCode; 140 } 141 142 /** Returns stdout. */ 143 public String getStdout() { 144 return stdout; 145 } 146 147 /** Returns stderr. */ 148 public String getStderr() { 149 return stderr; 150 } 151 152 /** Returns returnCode. */ 153 public int getReturnCode() { 154 return returnCode; 155 } 156 } 157 }