KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mmbase > util > externalprocess > StreamCopyThread


1 /*
2
3 This software is OSI Certified Open Source Software.
4 OSI Certified is a certification mark of the Open Source Initiative.
5
6 The license (Mozilla version 1.0) can be read at the MMBase site.
7 See http://www.MMBase.org/license
8
9 */

10 package org.mmbase.util.externalprocess;
11
12 import java.io.BufferedOutputStream JavaDoc;
13 import java.io.BufferedInputStream JavaDoc;
14 import java.io.InputStream JavaDoc;
15 import java.io.OutputStream JavaDoc;
16 import java.io.IOException JavaDoc;
17
18 import org.mmbase.util.logging.Logger;
19 import org.mmbase.util.logging.Logging;
20
21 /**
22  * Thread which continuously reads from a input stream and pushes the read data
23  * to an output stream which is immediately flushed afterwards.
24  *
25  * @author Nico Klasens (Finalist IT Group)
26  * @version $Id: StreamCopyThread.java,v 1.4 2005/01/30 16:46:39 nico Exp $
27  * @since MMBase-1.6
28  */

29 class StreamCopyThread extends Thread JavaDoc {
30
31     /** MMBase logging system */
32     private static Logger log = Logging.getLoggerInstance(StreamCopyThread.class.getName());
33
34     /**
35      * The number of milliseconds to wait before writing
36      */

37     protected static final long WAIT_DELAY = 25;
38
39     /**
40      * Default buffer size.
41      */

42     public static final int BUFFER_SIZE = 1024;
43
44     /**
45      * The stream from which to pipe the data.
46      */

47     private InputStream JavaDoc inputStream;
48
49     /**
50      * The stream to pipe the data to.
51      */

52     private OutputStream JavaDoc outputStream;
53
54     /**
55      * This thread writes to the external process
56      */

57     private boolean processInput = false;
58
59     /**
60      * Stream copying finished
61      */

62     private boolean finished = false;
63
64     /**
65      * Create a thread to copy bytes fro one strea to the other
66      *
67      * @param name the name of the new thread
68      * @param in the stream from which to pipe the data
69      * @param out the stream to pipe the data to
70      * @param pInput This thread writes to the external process
71      */

72     public StreamCopyThread(String JavaDoc name, InputStream JavaDoc in, OutputStream JavaDoc out, boolean pInput) {
73         this(null, name, in, out, pInput);
74     }
75
76     /**
77      * Create a thread to copy bytes fro one stream to the other
78      *
79      * @param group ThreadGroup where this thread belongs to
80      * @param name the name of the new thread
81      * @param in the stream from which to pipe the data
82      * @param out the stream to pipe the data to
83      * @param bSize the size of the buffer in which data is piped
84      * @param pInput This thread writes to the external process
85      */

86     public StreamCopyThread(
87         ThreadGroup JavaDoc group,
88         String JavaDoc name,
89         InputStream JavaDoc in,
90         OutputStream JavaDoc out,
91         boolean pInput) {
92         super(group, name);
93         processInput = pInput;
94         outputStream = out;
95         inputStream = in;
96         setDaemon(true);
97     }
98
99     /**
100     * @see java.lang.Runnable#run()
101     */

102     public void run() {
103         BufferedInputStream JavaDoc reader = new BufferedInputStream JavaDoc(inputStream);
104         BufferedOutputStream JavaDoc writer = null;
105         if (outputStream != null) {
106             writer = new BufferedOutputStream JavaDoc(outputStream);
107         }
108         try {
109             /*
110              * Without the sleep call, the subprocess doesn't get enough time
111              * to get started before we try to read its output, so we got
112              * nothing. This is a kludge, but it achieves the desired effect.
113              * Finding a more elegant solution is an exercise for the student,
114              * as those horrible college math book authors loved to say.
115              */

116             try {
117                 Thread.sleep(WAIT_DELAY);
118             } catch (InterruptedException JavaDoc e) {
119                 // we only wanted a delay
120
}
121
122             int size = 0;
123             //this buffer has nothing to do with the OS buffer
124
byte[] buffer = new byte[StreamCopyThread.BUFFER_SIZE];
125
126             while ((size = reader.read(buffer)) != -1) {
127                 if (writer != null) {
128                     writer.write(buffer, 0, size);
129                     writer.flush();
130                 }
131                 //log.debug("StreamCopy " + this.getName() + " read " + size + " bytes from input and wrote to output." );
132

133                 //Maybe we should reset variables
134
//size = 0;
135
//buffer = new byte[BUFFER_SIZE];
136
}
137         } catch (IOException JavaDoc x) {
138             // ignore
139
} finally {
140             /*
141              This thread only closes the stream to the process.
142              This way , the external process knows that we are finished writing.
143              Closing the stdout and sterr is not critical, but it is still nice
144              to close all the resources
145              This thread is not responsible for closing the stream of the java process.
146             */

147             if (processInput) {
148                 try {
149                     if (writer != null) {
150                         writer.close();
151                     }
152                 } catch (IOException JavaDoc e) {
153                     //ignore
154
}
155             } else {
156                 try {
157                     if (reader != null) {
158                         reader.close();
159                     }
160                 } catch (IOException JavaDoc e) {
161                     //ignore
162
}
163             }
164             complete();
165         }
166     }
167
168     /**
169      * Returns whether this thread has finished copying bytes
170      *
171      * @return <code>true</code> if finished and <code>false</code> otherwise
172      */

173     public synchronized boolean finished() {
174         return finished;
175     }
176
177     /**
178     * By calling this method the calling thread will wait until this thread is
179     * finished copying bytes
180     */

181     public synchronized void waitFor() {
182         while (!finished) {
183             try {
184                 wait();
185             } catch (InterruptedException JavaDoc e) {}
186         }
187     }
188
189     /**
190     * This method is called when the copying of bytes is done and notifies a
191     * waiting thread
192     */

193     protected synchronized void complete() {
194         finished = true;
195         notify();
196         log.debug("StreamCopy " + this.getName() + " finished.");
197     }
198 }
Popular Tags