Removed DOCUMENT ME comments that were generated and applied source code
[utils] / support / general / src / main / java / org / wamblee / io / SimpleProcess.java
1 /*
2  * Copyright 2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.wamblee.io;
17
18 import org.apache.commons.logging.Log;
19 import org.apache.commons.logging.LogFactory;
20
21 import java.io.BufferedReader;
22 import java.io.File;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.InputStreamReader;
26 import java.io.OutputStream;
27 import java.io.PrintStream;
28 import java.io.StringWriter;
29 import java.io.Writer;
30
31 /**
32  * 
33  * @author $author$
34  * @version $Revision$
35  */
36 public class SimpleProcess {
37     private static final Log LOG = LogFactory.getLog(SimpleProcess.class);
38
39     private File directory;
40
41     private String[] cmd;
42
43     private String stdout;
44
45     private String stderr;
46
47     /**
48      * Creates a new SimpleProcess object.
49      * 
50      */
51     public SimpleProcess(File aDirectory, String[] aCmd) {
52         directory = aDirectory;
53         cmd = aCmd;
54     }
55
56     /**
57      * 
58      * @return the stdout
59      */
60     public String getStdout() {
61         return stdout;
62     }
63
64     /**
65      * 
66      * @return the stderr
67      */
68     public String getStderr() {
69         return stderr;
70     }
71
72     /**
73      * Runs the process and blocks until it is done.
74      * 
75      * @return Exit status of the process.
76      * 
77      * @throws IOException
78      *             In case of problems.
79      */
80     public int run() throws IOException {
81         return runImpl();
82     }
83
84     private int runImpl() throws IOException {
85         try {
86             String fullcmd = "";
87
88             for (String part : cmd) {
89                 fullcmd += (" " + part);
90             }
91
92             LOG.debug("Executing '" + fullcmd + "' in directory '" + directory +
93                 "'");
94
95             java.lang.Process proc = Runtime.getRuntime().exec(cmd, null,
96                 directory);
97
98             // Read standard output and error in separate threads to avoid
99             // deadlock.
100             StringWriter myStdout = new StringWriter();
101             StringWriter myStderr = new StringWriter();
102             Thread stdoutReader = readAndLogStream("STDOUT>  ", proc
103                 .getInputStream(), myStdout);
104             Thread stderrReader = readAndLogStream("STDERR>  ", proc
105                 .getErrorStream(), myStderr);
106
107             try {
108                 proc.waitFor();
109             } catch (InterruptedException e) {
110                 IOException exception = new IOException(
111                     "Process was terminated: " + this);
112                 exception.initCause(e);
113                 throw exception;
114             }
115
116             waitForReader(stdoutReader);
117             waitForReader(stderrReader);
118
119             stdout = myStdout.toString();
120             stderr = myStderr.toString();
121
122             if (proc.exitValue() != 0) {
123                 LOG.warn("Exit value was non-zero: " + this);
124             } else {
125                 LOG.debug("Process finished");
126             }
127
128             return proc.exitValue();
129         } catch (IOException e) {
130             IOException exception = new IOException(
131                 "Error executing process: " + this);
132             exception.initCause(e);
133             throw exception;
134         }
135     }
136
137     private void waitForReader(Thread aReaderThread) {
138         try {
139             aReaderThread.join();
140         } catch (InterruptedException e) {
141             LOG
142                 .warn(this +
143                     ": error waiting for output stream reader of process to finish");
144         }
145     }
146
147     private Thread readAndLogStream(final String aPrefix,
148         final InputStream aStream, final Writer aOutput) {
149         Thread inputReader = new Thread() {
150             @Override
151             public void run() {
152                 BufferedReader br = null;
153
154                 try {
155                     br = new BufferedReader(new InputStreamReader(aStream));
156
157                     String str;
158
159                     while ((str = br.readLine()) != null) {
160                         LOG.debug(aPrefix + str);
161                         aOutput.write(str);
162                     }
163                 } catch (IOException e) {
164                     LOG.warn(SimpleProcess.this +
165                         ": error reading input stream", e);
166                 } finally {
167                     if (br != null) {
168                         try {
169                             br.close();
170                         } catch (IOException e) {
171                             LOG.warn("Error closing stream " + aPrefix);
172                         }
173                     }
174                 }
175             }
176         };
177
178         inputReader.start();
179
180         return inputReader;
181     }
182
183     @Override
184     public String toString() {
185         String fullcmd = "";
186
187         for (String part : cmd) {
188             fullcmd += (part + " ");
189         }
190
191         return "process(dir = '" + directory + "', cmd = '" + fullcmd + "')";
192     }
193 }