View Javadoc
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 extends AbstractStreamHandler {
88      private final BufferedReader in;
89  
90      private final StreamConsumer consumer;
91  
92      private final PrintWriter out;
93  
94      private volatile Exception exception = null;
95  
96      private static final int SIZE = 1024;
97  
98      public StreamPumper(InputStream in) {
99          this(in, (StreamConsumer) null);
100     }
101 
102     public StreamPumper(InputStream in, StreamConsumer consumer) {
103         this(in, null, consumer);
104     }
105 
106     public StreamPumper(InputStream in, PrintWriter writer) {
107         this(in, writer, null);
108     }
109 
110     public StreamPumper(InputStream in, PrintWriter writer, StreamConsumer consumer) {
111         super();
112         this.in = new BufferedReader(new InputStreamReader(in), SIZE);
113         this.out = writer;
114         this.consumer = consumer;
115     }
116 
117     @Override
118     public void run() {
119         boolean outError = out != null ? out.checkError() : false;
120 
121         try {
122             for (String line = in.readLine(); line != null; line = in.readLine()) {
123                 try {
124                     if (exception == null && consumer != null && !isDisabled()) {
125                         consumer.consumeLine(line);
126                     }
127                 } catch (Exception t) {
128                     exception = t;
129                 }
130 
131                 if (out != null && !outError) {
132                     out.println(line);
133 
134                     out.flush();
135 
136                     if (out.checkError()) {
137                         outError = true;
138 
139                         try {
140                             // Thrown to fill in stack trace elements.
141                             throw new IOException(String.format("Failure printing line '%s'.", line));
142                         } catch (final IOException e) {
143                             exception = e;
144                         }
145                     }
146                 }
147             }
148         } catch (IOException e) {
149             exception = e;
150         } finally {
151             try {
152                 in.close();
153             } catch (final IOException e2) {
154                 if (exception == null) {
155                     exception = e2;
156                 }
157             }
158 
159             synchronized (this) {
160                 setDone();
161 
162                 this.notifyAll();
163             }
164         }
165     }
166 
167     public void flush() {
168         if (out != null) {
169             out.flush();
170 
171             if (out.checkError() && exception == null) {
172                 try {
173                     // Thrown to fill in stack trace elements.
174                     throw new IOException("Failure flushing output.");
175                 } catch (final IOException e) {
176                     exception = e;
177                 }
178             }
179         }
180     }
181 
182     public void close() {
183         if (out != null) {
184             out.close();
185 
186             if (out.checkError() && exception == null) {
187                 try {
188                     // Thrown to fill in stack trace elements.
189                     throw new IOException("Failure closing output.");
190                 } catch (final IOException e) {
191                     exception = e;
192                 }
193             }
194         }
195     }
196 
197     public Exception getException() {
198         return exception;
199     }
200 }