Source code: com/port80/eclipse/util/ProcessMonitor.java
1 package com.port80.eclipse.util;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5
6 //import com.port80.util.msg;
7
8 /** Monitor a background process in a separate thread.
9 *
10 * @author chrisl Jun 5, 2002
11 */
12 public class ProcessMonitor {
13
14 ////////////////////////////////////////////////////////////////////////
15
16 private static final int BUFSIZE = 2048;
17
18 ////////////////////////////////////////////////////////////////////////
19
20 protected Process process; /** java.lang.Process being monitored. */
21 protected String name; /** Optional name for the monitor thread.*/
22 protected IProcessMonitorListener listener;
23
24 protected Thread thread; /** The process monitor thread.*/
25 protected Thread outThread; /** The output stream monitor thread.*/
26 protected Thread errThread; /** The error stream monitor thread.*/
27 protected InputStream outStream;
28 protected InputStream errStream;
29 protected StringBuffer outContent;
30 protected StringBuffer errContent;
31 protected int exitValue;
32
33 ////////////////////////////////////////////////////////////////////////
34
35 /**
36 * Creates a new process monitor and starts monitoring the process
37 * for termination.
38 */
39 public ProcessMonitor(
40 Process process,
41 String name,
42 IProcessMonitorListener listener,
43 boolean monitor_output,
44 boolean monitor_error) {
45 this.process = process;
46 this.name = name;
47 this.listener = listener;
48 this.outContent = new StringBuffer();
49 this.errContent = new StringBuffer();
50 this.exitValue = -2;
51 if (monitor_output) {
52 outStream = process.getInputStream();
53 startOutMonitor();
54 }
55 if (monitor_error) {
56 errStream = process.getErrorStream();
57 startErrMonitor();
58 }
59 startProcessMonitor();
60 }
61
62 public ProcessMonitor(Process process, String name, IProcessMonitorListener listener) {
63 this(process, name, listener, true, true);
64 }
65
66 ////////////////////////////////////////////////////////////////////////
67
68 /**
69 * Kills the monitoring thread.
70 *
71 * This method is to be useful for dealing with the error
72 * case of an underlying process to hang.
73 */
74 public void kill() {
75 thread.interrupt();
76 }
77
78 public String getOutContent() {
79 return outContent.toString();
80 }
81
82 public String getErrContent() {
83 return errContent.toString();
84 }
85
86 public int exitValue() {
87 return exitValue;
88 }
89
90 /**
91 * Wait till the process being monitored is done. If interrupted, the underlying process is killed.
92 */
93 public synchronized void waitFor() {
94 while (process != null) {
95 try {
96 wait();
97 } catch (InterruptedException e) {
98 kill();
99 }
100 }
101 }
102
103 ////////////////////////////////////////////////////////////////////////
104
105 /** Starts monitoring the underlying process. */
106 private void startProcessMonitor() {
107 if (thread == null) {
108 thread = new Thread(new Runnable() {
109 public void run() {
110 monitorProcess();
111 }
112 }, name);
113 thread.start();
114 }
115 }
116
117 /**
118 * Monitors the underlying process for termination. When the underlying process terminates
119 * (or if the monitoring thread is interrupted), inform the IProcessMaster that it has terminated.
120 */
121 void monitorProcess() {
122 while (process != null) {
123 try {
124 process.waitFor();
125 } catch (InterruptedException ie) {
126 } finally {
127 process.destroy();
128 exitValue = process.exitValue();
129 if(listener!=null) listener.terminated(exitValue);
130 synchronized (this) {
131 process = null;
132 notifyAll();
133 }
134 }
135 }
136 }
137
138 ////////////////////////////////////////////////////////////////////////
139
140 /** Start the output stream monitoring thread.*/
141 private void startOutMonitor() {
142 if (outThread == null) {
143 outThread = new Thread(new Runnable() {
144 public void run() {
145 outMonitor();
146 }
147 }, name + ".out");
148 outThread.start();
149 }
150 }
151
152 /** Continually reads from the output stream of the process. */
153 void outMonitor() {
154 byte[] bytes = new byte[BUFSIZE];
155 int nread = 0;
156 while (nread >= 0) {
157 try {
158 nread = outStream.read(bytes);
159 if (nread > 0) {
160 String text = new String(bytes, 0, nread);
161 outContent.append(text);
162 if(listener!=null) listener.outputAppended(text);
163 }
164 } catch (IOException ioe) {
165 System.err.println(ioe);
166 return;
167 }
168 }
169 }
170
171 ////////////////////////////////////////////////////////////////////////
172
173 /** Start the output stream monitoring thread.*/
174 private void startErrMonitor() {
175 if (errThread == null) {
176 errThread = new Thread(new Runnable() {
177 public void run() {
178 errMonitor();
179 }
180 }, name + ".err");
181 errThread.start();
182 }
183 }
184
185 /** Continually reads from the err stream of the process. */
186 void errMonitor() {
187 byte[] bytes = new byte[BUFSIZE];
188 int nread = 0;
189 while (nread >= 0) {
190 try {
191 nread = errStream.read(bytes);
192 if (nread > 0) {
193 String text = new String(bytes, 0, nread);
194 errContent.append(text);
195 if(listener!=null) listener.errorAppended(text);
196 }
197 } catch (IOException ioe) {
198 System.err.println(ioe);
199 return;
200 }
201 }
202 }
203
204 ////////////////////////////////////////////////////////////////////////
205
206 public static void main(String[] args) {
207 }
208
209 ////////////////////////////////////////////////////////////////////////
210 }