|
|||||||||||||||||||
Source file | Conditionals | Statements | Methods | TOTAL | |||||||||||||||
StreamRedirectThread.java | 0% | 0% | 0% | 0% |
|
1 | /*BEGIN_COPYRIGHT_BLOCK | |
2 | * | |
3 | * Copyright (c) 2001-2010, JavaPLT group at Rice University (drjava@rice.edu) | |
4 | * All rights reserved. | |
5 | * | |
6 | * Redistribution and use in source and binary forms, with or without | |
7 | * modification, are permitted provided that the following conditions are met: | |
8 | * * Redistributions of source code must retain the above copyright | |
9 | * notice, this list of conditions and the following disclaimer. | |
10 | * * Redistributions in binary form must reproduce the above copyright | |
11 | * notice, this list of conditions and the following disclaimer in the | |
12 | * documentation and/or other materials provided with the distribution. | |
13 | * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the | |
14 | * names of its contributors may be used to endorse or promote products | |
15 | * derived from this software without specific prior written permission. | |
16 | * | |
17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
18 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
19 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
20 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |
21 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
22 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
24 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
25 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
26 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
27 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
28 | * | |
29 | * This software is Open Source Initiative approved Open Source Software. | |
30 | * Open Source Initative Approved is a trademark of the Open Source Initiative. | |
31 | * | |
32 | * This file is part of DrJava. Download the current version of this project | |
33 | * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/ | |
34 | * | |
35 | * END_COPYRIGHT_BLOCK*/ | |
36 | ||
37 | package edu.rice.cs.util; | |
38 | ||
39 | import java.io.*; | |
40 | import edu.rice.cs.plt.concurrent.CompletionMonitor; | |
41 | ||
42 | /** StreamRedirectThread is a thread which copies its input to its output and terminates when it completes. */ | |
43 | public class StreamRedirectThread extends Thread { | |
44 | /// Input reader | |
45 | private Reader in; | |
46 | ||
47 | /// Output writer | |
48 | private final Writer out; | |
49 | ||
50 | /// Data buffer size | |
51 | private static final int BUFFER_SIZE = 2048; | |
52 | ||
53 | /// When stop flag is set to true, this thread should stop copying. | |
54 | private volatile boolean stop = false; | |
55 | ||
56 | /// When close flag is set to true, the streams are closed when copying has stopped. | |
57 | private volatile boolean close = true; | |
58 | ||
59 | /** When keepRunning flag is set to true, the thread will not terminate when the | |
60 | * stream ends. Instead, it will wait until another input stream is provided using | |
61 | * setInputStream(), and begin reading from that stream. To terminate the thread, | |
62 | * use setStopFlag(). */ | |
63 | private volatile boolean keepRunning = false; | |
64 | ||
65 | /** This completion monitor is used when a new input stream is set. The copying loop | |
66 | * waits for a signal, which is set in setInputStream(). */ | |
67 | private volatile CompletionMonitor cm = new CompletionMonitor(); | |
68 | ||
69 | /** | |
70 | * Constructor | |
71 | * | |
72 | * @param name thread name | |
73 | * @param in stream to copy from | |
74 | * @param out stream to copy to | |
75 | * @param close true if the streams should be closed after copying has ended | |
76 | */ | |
77 | 0 | public StreamRedirectThread(String name, InputStream in, OutputStream out, boolean close) { |
78 | 0 | this(name,in,out,close,false/*keepRunning*/); |
79 | } | |
80 | ||
81 | /** | |
82 | * Constructor | |
83 | * | |
84 | * @param name thread name | |
85 | * @param in stream to copy from | |
86 | * @param out stream to copy to | |
87 | * @param tg thread group for this thread | |
88 | */ | |
89 | 0 | public StreamRedirectThread(String name, InputStream in, OutputStream out, ThreadGroup tg) { |
90 | 0 | this(name,in,out,true/*close*/,tg,false/*keepRunning*/); |
91 | } | |
92 | /** | |
93 | * Constructor | |
94 | * | |
95 | * @param name thread name | |
96 | * @param in stream to copy from | |
97 | * @param out stream to copy to | |
98 | * @param close true if the streams should be closed after copying has ended | |
99 | * @param tg thread group for this thread | |
100 | */ | |
101 | 0 | public StreamRedirectThread(String name, InputStream in, OutputStream out, boolean close, ThreadGroup tg) { |
102 | 0 | this(name,in,out,close,tg,false/*keepRunning*/); |
103 | } | |
104 | ||
105 | /** | |
106 | * Constructor | |
107 | * | |
108 | * @param name thread name | |
109 | * @param in stream to copy from | |
110 | * @param out stream to copy to | |
111 | */ | |
112 | 0 | public StreamRedirectThread(String name, InputStream in, OutputStream out) { |
113 | 0 | this(name,in,out,true/*close*/,false/*keepRunning*/); |
114 | } | |
115 | ||
116 | /** | |
117 | * Constructor | |
118 | * | |
119 | * @param name thread name | |
120 | * @param in stream to copy from | |
121 | * @param out stream to copy to | |
122 | * @param close true if the streams should be closed after copying has ended | |
123 | * @param keepRunning true if the thread should keep running and not terminate when a stream ends | |
124 | */ | |
125 | 0 | public StreamRedirectThread(String name, InputStream in, OutputStream out, boolean close, boolean keepRunning) { |
126 | 0 | super(name); |
127 | 0 | this.keepRunning = keepRunning; |
128 | 0 | this.close = close; |
129 | 0 | this.in = new BufferedReader(new InputStreamReader(in)); |
130 | 0 | this.out = new BufferedWriter(new OutputStreamWriter(out)); |
131 | 0 | setPriority(Thread.MAX_PRIORITY - 1); |
132 | } | |
133 | ||
134 | /** | |
135 | * Constructor | |
136 | * @param name thread name | |
137 | * @param in stream to copy from | |
138 | * @param out stream to copy to | |
139 | * @param tg thread group for this thread | |
140 | * @param keepRunning true if the thread should keep running and not terminate when a stream ends | |
141 | */ | |
142 | 0 | public StreamRedirectThread(String name, InputStream in, OutputStream out, ThreadGroup tg, boolean keepRunning) { |
143 | 0 | this(name,in,out,true,tg,keepRunning); |
144 | } | |
145 | ||
146 | /** | |
147 | * Constructor | |
148 | * | |
149 | * @param name thread name | |
150 | * @param in stream to copy from | |
151 | * @param out stream to copy to | |
152 | * @param close true if the streams should be closed after copying has ended | |
153 | * @param tg thread group for this thread | |
154 | * @param keepRunning true if the thread should keep running and not terminate when a stream ends | |
155 | */ | |
156 | 0 | public StreamRedirectThread(String name, InputStream in, OutputStream out, boolean close, ThreadGroup tg, boolean keepRunning) { |
157 | 0 | super(tg,name); |
158 | 0 | this.keepRunning = keepRunning; |
159 | 0 | this.close = close; |
160 | 0 | this.in = new BufferedReader(new InputStreamReader(in)); |
161 | 0 | this.out = new BufferedWriter(new OutputStreamWriter(out)); |
162 | 0 | setPriority(Thread.MAX_PRIORITY - 1); |
163 | } | |
164 | ||
165 | /** | |
166 | * Set a new input stream. | |
167 | * @param in new input stream to read from | |
168 | */ | |
169 | 0 | public void setInputStream(InputStream in) { |
170 | 0 | this.in = new BufferedReader(new InputStreamReader(in)); |
171 | 0 | cm.signal(); |
172 | } | |
173 | ||
174 | /** | |
175 | * Copy. | |
176 | */ | |
177 | 0 | public void run() { |
178 | 0 | do { |
179 | 0 | try { |
180 | 0 | char[] cbuf = new char[BUFFER_SIZE]; |
181 | 0 | int count; |
182 | 0 | while ((!stop) && ((count = in.read(cbuf, 0, BUFFER_SIZE)) >= 0)) { |
183 | 0 | try { |
184 | 0 | out.write(cbuf, 0, count); |
185 | 0 | out.flush(); |
186 | } | |
187 | catch (IOException exc) { | |
188 | 0 | GeneralProcessCreator.LOG.log("StreamRedirectThread " + getName() + " had IOException while writing: " + exc); |
189 | 0 | throw new StreamRedirectException("An error occurred during stream redirection, while piping data into a process.", |
190 | exc); | |
191 | } | |
192 | } | |
193 | 0 | GeneralProcessCreator.LOG.log("StreamRedirectThread " + getName() + " finished copying"); |
194 | 0 | out.flush(); |
195 | 0 | if (close) { |
196 | 0 | in.close(); |
197 | } | |
198 | } | |
199 | catch (IOException exc) { | |
200 | 0 | GeneralProcessCreator.LOG.log("StreamRedirectThread " + getName() + " had IOException: " + exc); |
201 | 0 | throw new StreamRedirectException("An error occurred during stream redirection, while piping data out of a process.", |
202 | exc); | |
203 | } | |
204 | 0 | if (keepRunning) { |
205 | // wait for a new input stream | |
206 | 0 | while(!cm.attemptEnsureSignaled()); |
207 | 0 | cm.reset(); |
208 | } | |
209 | 0 | } while(keepRunning && !close); |
210 | 0 | if (close) { |
211 | 0 | try { |
212 | 0 | out.close(); |
213 | } | |
214 | catch (IOException exc) { | |
215 | 0 | GeneralProcessCreator.LOG.log("StreamRedirectThread " + getName() + " had IOException: " + exc); |
216 | 0 | throw new StreamRedirectException("An error occurred during stream redirection, while piping data out of a process.", |
217 | exc); | |
218 | } | |
219 | } | |
220 | } | |
221 | ||
222 | /** | |
223 | * Tell the thread to stop copying. | |
224 | */ | |
225 | 0 | public void setStopFlag() { |
226 | 0 | stop = true; |
227 | } | |
228 | } |
|