001: /*
002: * This file or a portion of this file is licensed under the terms of
003: * the Globus Toolkit Public License, found in file GTPL, or at
004: * http://www.globus.org/toolkit/download/license.html. This notice must
005: * appear in redistributions of this file, with or without modification.
006: *
007: * Redistributions of this Software, with or without modification, must
008: * reproduce the GTPL in: (1) the Software, or (2) the Documentation or
009: * some other similar material which is provided with the Software (if
010: * any).
011: *
012: * Copyright 1999-2004 University of Chicago and The University of
013: * Southern California. All rights reserved.
014: */
015: package org.griphyn.cPlanner.common;
016:
017: import org.griphyn.cPlanner.common.LogManager;
018:
019: import java.io.InputStream;
020: import java.io.InputStreamReader;
021: import java.io.OutputStream;
022: import java.io.PrintWriter;
023: import java.io.BufferedReader;
024: import java.io.IOException;
025:
026: /**
027: * A Stream gobbler class to take care of reading from a stream and optionally
028: * write out to another stream. Allows for non blocking reads on both stdout
029: * and stderr, when invoking a process through Runtime.exec().
030: * Also, the user can specify a callback that is called whenever anything
031: * is read from the stream.
032: *
033: * @author Karan Vahi
034: */
035: public class StreamGobbler extends Thread {
036:
037: /**
038: * The input stream that is to be read from.
039: */
040: private InputStream mIPStream;
041:
042: /**
043: * The output stream to which the contents have to be redirected to.
044: */
045: private OutputStream mOPStream;
046:
047: /**
048: * The callback to be used.
049: */
050: private StreamGobblerCallback mCallback;
051:
052: /**
053: * The prompt that is to be written to the output stream.
054: */
055: private String mPrompt;
056:
057: /**
058: * A boolean indicating whether the thread has started or not.
059: */
060: private boolean mStarted;
061:
062: /**
063: * The handle to the logging object.
064: */
065: private LogManager mLogger;
066:
067: /**
068: * The overloaded constructor.
069: *
070: * @param is the input stream from which to read from.
071: * @param callback the callback to call when a line is read.
072: */
073: public StreamGobbler(InputStream is, StreamGobblerCallback callback) {
074: this .mIPStream = is;
075: mCallback = callback;
076: mLogger = LogManager.getInstance();
077:
078: //set the prompt to nothing
079: mPrompt = "";
080: }
081:
082: /**
083: * Sets the output stream to which to redirect the contents of the input
084: * stream.
085: *
086: * @param ops the output stream.
087: * @param prompt the prompt for the output stream.
088: */
089: public void redirect(OutputStream ops, String prompt) {
090:
091: if (mStarted) {
092: //should throw a specific VTor exception
093: throw new RuntimeException(
094: "The thread has already started execution");
095: }
096:
097: mOPStream = ops;
098: mPrompt = (prompt == null) ? "" : prompt;
099: }
100:
101: /**
102: * The main method of the gobbler, that does all the work.
103: */
104: public void run() {
105: try {
106: mStarted = true;
107: PrintWriter pw = (mOPStream == null) ? null
108: : new PrintWriter(mOPStream);
109:
110: boolean redirect = !(pw == null);
111:
112: InputStreamReader isr = new InputStreamReader(mIPStream);
113: BufferedReader br = new BufferedReader(isr);
114: String line = null;
115: while ((line = br.readLine()) != null) {
116: //redirect to output stream
117: if (redirect)
118: pw.println(mPrompt + line);
119:
120: //callout to the callback
121: mCallback.work(line);
122:
123: //be nice and sleep
124: this .sleep(5);
125:
126: }
127: } catch (IOException e) {
128: mLogger.log(" While reading in StreamGobbler ", e,
129: LogManager.ERROR_MESSAGE_LEVEL);
130: } catch (InterruptedException e) {
131: //ignore
132: } finally {
133: mStarted = false;
134: }
135:
136: }
137:
138: /**
139: * Closes the open connections to the streams whenever this object
140: * is destroyed.
141: */
142: protected void finalize() {
143: close();
144: }
145:
146: /**
147: * Closes the underneath input and output stream that were opened.
148: */
149: public void close() {
150: //close the input stream
151: try {
152: if (mIPStream != null)
153: mIPStream.close();
154:
155: } catch (IOException e) {
156: //ignore
157: } finally {
158: mIPStream = null;
159: }
160:
161: //close the output stream
162: try {
163: if (mOPStream != null)
164: mOPStream.close();
165:
166: } catch (IOException e) {
167: //ignore
168: } finally {
169: mOPStream = null;
170: }
171:
172: }
173: }
|