1. /*
  2. * Copyright 2000-2004 The Apache Software Foundation
  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. */
  17. package org.apache.tools.ant.taskdefs;
  18. import java.io.IOException;
  19. import java.io.InputStream;
  20. import java.io.OutputStream;
  21. /**
  22. * Copies standard output and error of subprocesses to standard output and
  23. * error of the parent process.
  24. *
  25. * @since Ant 1.2
  26. */
  27. public class PumpStreamHandler implements ExecuteStreamHandler {
  28. private Thread outputThread;
  29. private Thread errorThread;
  30. private Thread inputThread;
  31. private OutputStream out;
  32. private OutputStream err;
  33. private InputStream input;
  34. /**
  35. * Construct a new <CODE>PumpStreamHandler</CODE>.
  36. * @param out the output <CODE>OutputStream</CODE>.
  37. * @param err the error <CODE>OutputStream</CODE>.
  38. * @param input the input <CODE>InputStream</CODE>.
  39. */
  40. public PumpStreamHandler(OutputStream out, OutputStream err,
  41. InputStream input) {
  42. this.out = out;
  43. this.err = err;
  44. this.input = input;
  45. }
  46. /**
  47. * Construct a new <CODE>PumpStreamHandler</CODE>.
  48. * @param out the output <CODE>OutputStream</CODE>.
  49. * @param err the error <CODE>OutputStream</CODE>.
  50. */
  51. public PumpStreamHandler(OutputStream out, OutputStream err) {
  52. this(out, err, null);
  53. }
  54. /**
  55. * Construct a new <CODE>PumpStreamHandler</CODE>.
  56. * @param outAndErr the output/error <CODE>OutputStream</CODE>.
  57. */
  58. public PumpStreamHandler(OutputStream outAndErr) {
  59. this(outAndErr, outAndErr);
  60. }
  61. /**
  62. * Construct a new <CODE>PumpStreamHandler</CODE>.
  63. */
  64. public PumpStreamHandler() {
  65. this(System.out, System.err);
  66. }
  67. /**
  68. * Set the <CODE>InputStream</CODE> from which to read the
  69. * standard output of the process.
  70. * @param is the <CODE>InputStream</CODE>.
  71. */
  72. public void setProcessOutputStream(InputStream is) {
  73. createProcessOutputPump(is, out);
  74. }
  75. /**
  76. * Set the <CODE>InputStream</CODE> from which to read the
  77. * standard error of the process.
  78. * @param is the <CODE>InputStream</CODE>.
  79. */
  80. public void setProcessErrorStream(InputStream is) {
  81. if (err != null) {
  82. createProcessErrorPump(is, err);
  83. }
  84. }
  85. /**
  86. * Set the <CODE>OutputStream</CODE> by means of which
  87. * input can be sent to the process.
  88. * @param os the <CODE>OutputStream</CODE>.
  89. */
  90. public void setProcessInputStream(OutputStream os) {
  91. if (input != null) {
  92. inputThread = createPump(input, os, true);
  93. } else {
  94. try {
  95. os.close();
  96. } catch (IOException e) {
  97. //ignore
  98. }
  99. }
  100. }
  101. /**
  102. * Start the <CODE>Thread</CODE>s.
  103. */
  104. public void start() {
  105. outputThread.start();
  106. errorThread.start();
  107. if (inputThread != null) {
  108. inputThread.start();
  109. }
  110. }
  111. /**
  112. * Stop pumping the streams.
  113. */
  114. public void stop() {
  115. try {
  116. outputThread.join();
  117. } catch (InterruptedException e) {
  118. // ignore
  119. }
  120. try {
  121. errorThread.join();
  122. } catch (InterruptedException e) {
  123. // ignore
  124. }
  125. if (inputThread != null) {
  126. try {
  127. inputThread.join();
  128. } catch (InterruptedException e) {
  129. // ignore
  130. }
  131. }
  132. try {
  133. err.flush();
  134. } catch (IOException e) {
  135. // ignore
  136. }
  137. try {
  138. out.flush();
  139. } catch (IOException e) {
  140. // ignore
  141. }
  142. }
  143. /**
  144. * Get the error stream.
  145. * @return <CODE>OutputStream</CODE>.
  146. */
  147. protected OutputStream getErr() {
  148. return err;
  149. }
  150. /**
  151. * Get the output stream.
  152. * @return <CODE>OutputStream</CODE>.
  153. */
  154. protected OutputStream getOut() {
  155. return out;
  156. }
  157. /**
  158. * Create the pump to handle process output.
  159. * @param is the <CODE>InputStream</CODE>.
  160. * @param os the <CODE>OutputStream</CODE>.
  161. */
  162. protected void createProcessOutputPump(InputStream is, OutputStream os) {
  163. outputThread = createPump(is, os);
  164. }
  165. /**
  166. * Create the pump to handle error output.
  167. * @param is the <CODE>InputStream</CODE>.
  168. * @param os the <CODE>OutputStream</CODE>.
  169. */
  170. protected void createProcessErrorPump(InputStream is, OutputStream os) {
  171. errorThread = createPump(is, os);
  172. }
  173. /**
  174. * Creates a stream pumper to copy the given input stream to the
  175. * given output stream.
  176. */
  177. protected Thread createPump(InputStream is, OutputStream os) {
  178. return createPump(is, os, false);
  179. }
  180. /**
  181. * Creates a stream pumper to copy the given input stream to the
  182. * given output stream.
  183. */
  184. protected Thread createPump(InputStream is, OutputStream os,
  185. boolean closeWhenExhausted) {
  186. final Thread result
  187. = new Thread(new StreamPumper(is, os, closeWhenExhausted));
  188. result.setDaemon(true);
  189. return result;
  190. }
  191. }