1 package org.codehaus.plexus.util.cli;
2
3 /*
4 * Copyright The Codehaus Foundation.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 /********************************************************************************
20 * CruiseControl, a Continuous Integration Toolkit
21 * Copyright (c) 2001-2003, ThoughtWorks, Inc.
22 * 651 W Washington Ave. Suite 500
23 * Chicago, IL 60661 USA
24 * All rights reserved.
25 *
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions
28 * are met:
29 *
30 * + Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 *
33 * + Redistributions in binary form must reproduce the above
34 * copyright notice, this list of conditions and the following
35 * disclaimer in the documentation and/or other materials provided
36 * with the distribution.
37 *
38 * + Neither the name of ThoughtWorks, Inc., CruiseControl, nor the
39 * names of its contributors may be used to endorse or promote
40 * products derived from this software without specific prior
41 * written permission.
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
44 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
45 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
46 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
47 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
48 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
49 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
50 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
51 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
52 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
53 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 ********************************************************************************/
55
56 /* ====================================================================
57 * Copyright 2003-2004 The Apache Software Foundation.
58 *
59 * Licensed under the Apache License, Version 2.0 (the "License");
60 * you may not use this file except in compliance with the License.
61 * You may obtain a copy of the License at
62 *
63 * http://www.apache.org/licenses/LICENSE-2.0
64 *
65 * Unless required by applicable law or agreed to in writing, software
66 * distributed under the License is distributed on an "AS IS" BASIS,
67 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
68 * See the License for the specific language governing permissions and
69 * limitations under the License.
70 * ====================================================================
71 */
72
73 import java.io.BufferedReader;
74 import java.io.IOException;
75 import java.io.InputStream;
76 import java.io.InputStreamReader;
77 import java.io.PrintWriter;
78
79 /**
80 * Class to pump the error stream during Process's runtime. Copied from the Ant built-in task.
81 *
82 * @author <a href="mailto:fvancea@maxiq.com">Florin Vancea </a>
83 * @author <a href="mailto:pj@thoughtworks.com">Paul Julius </a>
84 *
85 * @since June 11, 2001
86 */
87 public class StreamPumper
88 extends AbstractStreamHandler
89 {
90 private final BufferedReader in;
91
92 private final StreamConsumer consumer;
93
94 private final PrintWriter out;
95
96 private volatile Exception exception = null;
97
98 private static final int SIZE = 1024;
99
100 public StreamPumper( InputStream in )
101 {
102 this( in, (StreamConsumer) null );
103 }
104
105 public StreamPumper( InputStream in, StreamConsumer consumer )
106 {
107 this( in, null, consumer );
108 }
109
110 public StreamPumper( InputStream in, PrintWriter writer )
111 {
112 this( in, writer, null );
113 }
114
115 public StreamPumper( InputStream in, PrintWriter writer, StreamConsumer consumer )
116 {
117 super();
118 this.in = new BufferedReader( new InputStreamReader( in ), SIZE );
119 this.out = writer;
120 this.consumer = consumer;
121 }
122
123 @Override
124 public void run()
125 {
126 boolean outError = out != null ? out.checkError() : false;
127
128 try
129 {
130 for ( String line = in.readLine(); line != null; line = in.readLine() )
131 {
132 try
133 {
134 if ( exception == null && consumer != null && !isDisabled() )
135 {
136 consumer.consumeLine( line );
137 }
138 }
139 catch ( Exception t )
140 {
141 exception = t;
142 }
143
144 if ( out != null && !outError )
145 {
146 out.println( line );
147
148 out.flush();
149
150 if ( out.checkError() )
151 {
152 outError = true;
153
154 try
155 {
156 // Thrown to fill in stack trace elements.
157 throw new IOException( String.format( "Failure printing line '%s'.", line ) );
158 }
159 catch ( final IOException e )
160 {
161 exception = e;
162 }
163 }
164 }
165 }
166 }
167 catch ( IOException e )
168 {
169 exception = e;
170 }
171 finally
172 {
173 try
174 {
175 in.close();
176 }
177 catch ( final IOException e2 )
178 {
179 if ( exception == null )
180 {
181 exception = e2;
182 }
183 }
184
185 synchronized ( this )
186 {
187 setDone();
188
189 this.notifyAll();
190 }
191 }
192 }
193
194 public void flush()
195 {
196 if ( out != null )
197 {
198 out.flush();
199
200 if ( out.checkError() && exception == null )
201 {
202 try
203 {
204 // Thrown to fill in stack trace elements.
205 throw new IOException( "Failure flushing output." );
206 }
207 catch ( final IOException e )
208 {
209 exception = e;
210 }
211 }
212 }
213 }
214
215 public void close()
216 {
217 if ( out != null )
218 {
219 out.close();
220
221 if ( out.checkError() && exception == null )
222 {
223 try
224 {
225 // Thrown to fill in stack trace elements.
226 throw new IOException( "Failure closing output." );
227 }
228 catch ( final IOException e )
229 {
230 exception = e;
231 }
232 }
233 }
234 }
235
236 public Exception getException()
237 {
238 return exception;
239 }
240 }