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 }