001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.tools.ant.taskdefs;
020:
021: import java.io.IOException;
022: import java.io.InputStream;
023: import java.io.OutputStream;
024:
025: /**
026: * Copies standard output and error of subprocesses to standard output and
027: * error of the parent process.
028: *
029: * @since Ant 1.2
030: */
031: public class PumpStreamHandler implements ExecuteStreamHandler {
032:
033: private Thread outputThread;
034: private Thread errorThread;
035: private StreamPumper inputPump;
036:
037: private OutputStream out;
038: private OutputStream err;
039: private InputStream input;
040:
041: /**
042: * Construct a new <code>PumpStreamHandler</code>.
043: * @param out the output <code>OutputStream</code>.
044: * @param err the error <code>OutputStream</code>.
045: * @param input the input <code>InputStream</code>.
046: */
047: public PumpStreamHandler(OutputStream out, OutputStream err,
048: InputStream input) {
049: this .out = out;
050: this .err = err;
051: this .input = input;
052: }
053:
054: /**
055: * Construct a new <code>PumpStreamHandler</code>.
056: * @param out the output <code>OutputStream</code>.
057: * @param err the error <code>OutputStream</code>.
058: */
059: public PumpStreamHandler(OutputStream out, OutputStream err) {
060: this (out, err, null);
061: }
062:
063: /**
064: * Construct a new <code>PumpStreamHandler</code>.
065: * @param outAndErr the output/error <code>OutputStream</code>.
066: */
067: public PumpStreamHandler(OutputStream outAndErr) {
068: this (outAndErr, outAndErr);
069: }
070:
071: /**
072: * Construct a new <code>PumpStreamHandler</code>.
073: */
074: public PumpStreamHandler() {
075: this (System.out, System.err);
076: }
077:
078: /**
079: * Set the <code>InputStream</code> from which to read the
080: * standard output of the process.
081: * @param is the <code>InputStream</code>.
082: */
083: public void setProcessOutputStream(InputStream is) {
084: createProcessOutputPump(is, out);
085: }
086:
087: /**
088: * Set the <code>InputStream</code> from which to read the
089: * standard error of the process.
090: * @param is the <code>InputStream</code>.
091: */
092: public void setProcessErrorStream(InputStream is) {
093: if (err != null) {
094: createProcessErrorPump(is, err);
095: }
096: }
097:
098: /**
099: * Set the <code>OutputStream</code> by means of which
100: * input can be sent to the process.
101: * @param os the <code>OutputStream</code>.
102: */
103: public void setProcessInputStream(OutputStream os) {
104: if (input != null) {
105: inputPump = createInputPump(input, os, true);
106: } else {
107: try {
108: os.close();
109: } catch (IOException e) {
110: //ignore
111: }
112: }
113: }
114:
115: /**
116: * Start the <code>Thread</code>s.
117: */
118: public void start() {
119: outputThread.start();
120: errorThread.start();
121: if (inputPump != null) {
122: Thread inputThread = new Thread(inputPump);
123: inputThread.setDaemon(true);
124: inputThread.start();
125: }
126: }
127:
128: /**
129: * Stop pumping the streams.
130: */
131: public void stop() {
132: try {
133: outputThread.join();
134: } catch (InterruptedException e) {
135: // ignore
136: }
137: try {
138: errorThread.join();
139: } catch (InterruptedException e) {
140: // ignore
141: }
142:
143: if (inputPump != null) {
144: inputPump.stop();
145: }
146:
147: try {
148: err.flush();
149: } catch (IOException e) {
150: // ignore
151: }
152: try {
153: out.flush();
154: } catch (IOException e) {
155: // ignore
156: }
157: }
158:
159: /**
160: * Get the error stream.
161: * @return <code>OutputStream</code>.
162: */
163: protected OutputStream getErr() {
164: return err;
165: }
166:
167: /**
168: * Get the output stream.
169: * @return <code>OutputStream</code>.
170: */
171: protected OutputStream getOut() {
172: return out;
173: }
174:
175: /**
176: * Create the pump to handle process output.
177: * @param is the <code>InputStream</code>.
178: * @param os the <code>OutputStream</code>.
179: */
180: protected void createProcessOutputPump(InputStream is,
181: OutputStream os) {
182: outputThread = createPump(is, os);
183: }
184:
185: /**
186: * Create the pump to handle error output.
187: * @param is the input stream to copy from.
188: * @param os the output stream to copy to.
189: */
190: protected void createProcessErrorPump(InputStream is,
191: OutputStream os) {
192: errorThread = createPump(is, os);
193: }
194:
195: /**
196: * Creates a stream pumper to copy the given input stream to the
197: * given output stream.
198: * @param is the input stream to copy from.
199: * @param os the output stream to copy to.
200: * @return a thread object that does the pumping.
201: */
202: protected Thread createPump(InputStream is, OutputStream os) {
203: return createPump(is, os, false);
204: }
205:
206: /**
207: * Creates a stream pumper to copy the given input stream to the
208: * given output stream.
209: * @param is the input stream to copy from.
210: * @param os the output stream to copy to.
211: * @param closeWhenExhausted if true close the inputstream.
212: * @return a thread object that does the pumping.
213: */
214: protected Thread createPump(InputStream is, OutputStream os,
215: boolean closeWhenExhausted) {
216: final Thread result = new Thread(new StreamPumper(is, os,
217: closeWhenExhausted));
218: result.setDaemon(true);
219: return result;
220: }
221:
222: /**
223: * Creates a stream pumper to copy the given input stream to the
224: * given output stream. Used for standard input.
225: * @since Ant 1.6.3
226: */
227: /*protected*/StreamPumper createInputPump(InputStream is,
228: OutputStream os, boolean closeWhenExhausted) {
229: StreamPumper pumper = new StreamPumper(is, os,
230: closeWhenExhausted);
231: pumper.setAutoflush(true);
232: return pumper;
233: }
234:
235: }
|