Source code: com/arranger/jarl/util/ProcessStreamMonitor.java
1 package com.arranger.jarl.util;
2
3 import java.io.*;
4
5 /**
6 * ProcessStreamMonitor created on Apr 4, 2003
7 */
8 public class ProcessStreamMonitor {
9
10 protected Process m_process;
11 protected PumpStreamHandler m_pumpStreamHandler;
12
13 public ProcessStreamMonitor(Process process) {
14 m_process = process;
15 }
16
17 public void start() {
18 m_pumpStreamHandler = new PumpStreamHandler();
19 m_pumpStreamHandler.setProcessErrorStream(m_process.getErrorStream());
20 m_pumpStreamHandler.setProcessOutputStream(m_process.getInputStream());
21 m_pumpStreamHandler.setProcessInputStream(m_process.getOutputStream());
22 m_pumpStreamHandler.start();
23 }
24
25 protected static class PumpStreamHandler {
26
27 private Thread inputThread;
28 private Thread errorThread;
29
30 private OutputStream out, err;
31
32 public PumpStreamHandler(OutputStream out, OutputStream err) {
33 this.out = out;
34 this.err = err;
35 }
36
37 public PumpStreamHandler(OutputStream outAndErr) {
38 this(outAndErr, outAndErr);
39 }
40
41 public PumpStreamHandler() {
42 this(System.out, System.err);
43 }
44
45 public void setProcessOutputStream(InputStream is) {
46 createProcessOutputPump(is, out);
47 }
48
49
50 public void setProcessErrorStream(InputStream is) {
51 createProcessErrorPump(is, err);
52 }
53
54
55 public void setProcessInputStream(OutputStream os) {
56 }
57
58
59 public void start() {
60 inputThread.start();
61 errorThread.start();
62 }
63
64
65 public void stop() {
66 try {
67 inputThread.join();
68 } catch (InterruptedException e) {
69 }
70 try {
71 errorThread.join();
72 } catch (InterruptedException e) {
73 }
74 try {
75 err.flush();
76 } catch (IOException e) {
77 }
78 try {
79 out.flush();
80 } catch (IOException e) {
81 }
82 }
83
84 protected OutputStream getErr() {
85 return err;
86 }
87
88 protected OutputStream getOut() {
89 return out;
90 }
91
92 protected void createProcessOutputPump(InputStream is, OutputStream os) {
93 inputThread = createPump(is, os);
94 }
95
96 protected void createProcessErrorPump(InputStream is, OutputStream os) {
97 errorThread = createPump(is, os);
98 }
99
100
101 /**
102 * Creates a stream pumper to copy the given input stream to the
103 * given output stream.
104 */
105 protected Thread createPump(InputStream is, OutputStream os) {
106 final Thread result = new Thread(new StreamPumper(is, os));
107 result.setDaemon(true);
108 return result;
109 }
110 }
111
112 protected static class StreamPumper implements Runnable {
113
114 private static final int SLEEP = 5;
115 private static final int SIZE = 128;
116 private InputStream is;
117 private OutputStream os;
118 private boolean finished;
119
120 /**
121 * Create a new stream pumper.
122 *
123 * @param is input stream to read data from
124 * @param os output stream to write data to.
125 */
126 public StreamPumper(InputStream is, OutputStream os) {
127 this.is = is;
128 this.os = os;
129 }
130
131 /**
132 * Copies data from the input stream to the output stream.
133 *
134 * Terminates as soon as the input stream is closed or an error occurs.
135 */
136 public void run() {
137 synchronized (this) {
138 // Just in case this object is reused in the future
139 finished = false;
140 }
141
142 final byte[] buf = new byte[SIZE];
143
144 int length;
145 try {
146 while ((length = is.read(buf)) > 0) {
147 os.write(buf, 0, length);
148 try {
149 Thread.sleep(SLEEP);
150 } catch (InterruptedException e) {
151 }
152 }
153 } catch (IOException e) {
154 } finally {
155 synchronized (this) {
156 finished = true;
157 notify();
158 }
159 }
160 }
161
162 /**
163 * Tells whether the end of the stream has been reached.
164 * @return true is the stream has been exhausted.
165 **/
166 public synchronized boolean isFinished() {
167 return finished;
168 }
169
170 /**
171 * This method blocks until the stream pumper finishes.
172 * @see #isFinished()
173 **/
174 public synchronized void waitFor()
175 throws InterruptedException {
176 while (!isFinished()) {
177 wait();
178 }
179 }
180 }
181 }