1 package org.apache.maven.shared.utils.cli;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.OutputStream;
25 import java.util.concurrent.atomic.AtomicReference;
26
27 /**
28 * Read from an InputStream and write the output to an OutputStream.
29 *
30 * @author <a href="mailto:trygvis@inamo.no">Trygve Laugstøl</a>
31 * @version $Id$
32 */
33 class StreamFeeder
34 extends AbstractStreamHandler
35 {
36
37 private final AtomicReference<InputStream> input;
38
39 private final AtomicReference<OutputStream> output;
40
41 private volatile Throwable exception;
42
43 /**
44 * Create a new StreamFeeder
45 *
46 * @param input Stream to read from
47 * @param output Stream to write to
48 */
49 StreamFeeder( InputStream input, OutputStream output )
50 {
51 super();
52 this.input = new AtomicReference<InputStream>( input );
53 this.output = new AtomicReference<OutputStream>( output );
54 }
55
56 @Override
57 public void run()
58 {
59 try
60 {
61 feed();
62 }
63 catch ( Throwable e )
64 {
65 // Catch everything so the streams will be closed and flagged as done.
66 if ( this.exception != null )
67 {
68 this.exception = e;
69 }
70 }
71 finally
72 {
73 close();
74
75 synchronized ( this )
76 {
77 notifyAll();
78 }
79 }
80 }
81
82 public void close()
83 {
84 setDone();
85 final InputStream is = input.getAndSet( null );
86 if ( is != null )
87 {
88 try
89 {
90 is.close();
91 }
92 catch ( IOException ex )
93 {
94 if ( this.exception != null )
95 {
96 this.exception = ex;
97 }
98 }
99 }
100
101 final OutputStream os = output.getAndSet( null );
102 if ( os != null )
103 {
104 try
105 {
106 os.close();
107 }
108 catch ( IOException ex )
109 {
110 if ( this.exception != null )
111 {
112 this.exception = ex;
113 }
114 }
115 }
116 }
117
118 /**
119 * @since 3.2.0
120 */
121 public Throwable getException()
122 {
123 return this.exception;
124 }
125
126 @SuppressWarnings( "checkstyle:innerassignment" )
127 private void feed()
128 throws IOException
129 {
130 InputStream is = input.get();
131 OutputStream os = output.get();
132 boolean flush = false;
133
134 if ( is != null && os != null )
135 {
136 for ( int data; !isDone() && ( data = is.read() ) != -1; )
137 {
138 if ( !isDisabled() )
139 {
140 os.write( data );
141 flush = true;
142 }
143 }
144
145 if ( flush )
146 {
147 os.flush();
148 }
149 }
150 }
151
152 }