001: package snow.utils;
002:
003: import snow.concurrent.*;
004: import java.util.*;
005: import java.io.*;
006:
007: /** Reads a stream and pas it to another, (possibly to ignore it).
008: * External processes must be read (gobbled) to avoid some buffer overflows.
009: * Typically, one will gobble a Process's output to System.out .
010: */
011: public class StreamGobbler extends Thread {
012: public boolean debug = false;
013:
014: private final InputStream inputStream;
015: private final Writer writer;
016: private StringGobblerLineListener lineListener = null;
017:
018: public final Object syncLock; // Not null, either the output stream OR an object.
019:
020: // these lines are not written out
021: public final Set<String> ignoredLinesForWriting = new HashSet<String>();
022:
023: // Is just a text, which is repeated on each beginning of a line.
024: private String streamIdentifier = "";
025:
026: public final Counter lineCounter = new Counter();
027:
028: /**
029: * The input will be read, but not forwarded.
030: */
031: public StreamGobbler(final InputStream inputStream) {
032: this (inputStream, null);
033: }
034:
035: /**
036: * The outputStream can be null - then the input just will be read, but not forwarded.
037: * If non null outputStream is used as lock for the write op.
038: */
039: public StreamGobbler(final InputStream inputStream,
040: final OutputStream outputStream) {
041: this .inputStream = inputStream;
042: if (outputStream != null) {
043: syncLock = outputStream;
044: this .writer = new PrintWriter(outputStream);
045: } else {
046: //new Throwable("null out").printStackTrace();
047: syncLock = new Object();
048: this .writer = null;
049: }
050: }
051:
052: /**
053: * An additional name is passed, which is written out on each beginning of a line.
054: * The outputStream can be null - then the input just will be read, but not forwarded.
055: */
056: public StreamGobbler(final InputStream inputStream,
057: final OutputStream outputStream,
058: final String theStreamIdentifier) {
059: this (inputStream, outputStream);
060: this .streamIdentifier = theStreamIdentifier + "> ";
061: setName("StreamGobbler"
062: + (streamIdentifier != null ? " (" + streamIdentifier
063: + ")" : ""));
064: }
065:
066: /**
067: * Constructor 3: use a Writer
068: */
069: public StreamGobbler(final InputStream inputStream, final Writer w,
070: final String theStreamIdentifier) {
071: //if(w==null) new Throwable("null writer").printStackTrace();
072:
073: if (theStreamIdentifier != null
074: && theStreamIdentifier.length() > 0) {
075: this .streamIdentifier = theStreamIdentifier + "> ";
076: setName("StreamGobbler" + " (" + streamIdentifier + ")");
077: } else {
078: this .streamIdentifier = "";
079: }
080: this .inputStream = inputStream;
081: this .writer = w;
082: setName("StreamGobbler (" + theStreamIdentifier + ")");
083: syncLock = (w != null ? w : new Object());
084: }
085:
086: public synchronized void setLineListener(
087: StringGobblerLineListener ll) {
088: if (lineListener != null)
089: new Throwable("already existing, replacing...")
090: .printStackTrace();
091: lineListener = ll;
092: }
093:
094: @Override
095: public void run() {
096: if (debug)
097: System.out.println("gobbler start (debug)");
098: try {
099: final InputStreamReader isr = new InputStreamReader(
100: this .inputStream);
101: final BufferedReader br = new BufferedReader(isr);
102:
103: String line;
104: while ((line = br.readLine()) != null) {
105: if (debug)
106: System.out.println("GLine: " + line);
107:
108: lineCounter.increment(1);
109: synchronized (this ) {
110: if (lineListener != null) {
111: if (line.equals(lineListener.lineToMatch())) {
112: lineListener.lineMatch(line);
113: } else {
114: lineListener.lineRead(line);
115: }
116: }
117: }
118:
119: if (debug) {
120: System.out.println("L='" + line + "', "
121: + ignoredLinesForWriting + " " + writer);
122: }
123:
124: if (writer != null) {
125:
126: if (!ignoredLinesForWriting.contains(line.trim())) {
127:
128: synchronized (syncLock) // [Nov2007]
129: {
130: // write a full line
131: writer.append(this .streamIdentifier + line
132: + "\r\n");
133: //System.out.println("Debug: "+line);
134: writer.flush(); //printWriter.flush();
135: }
136: }
137: } // else we do nothing
138: }
139: } catch (IOException ioe) {
140: ioe.printStackTrace();
141: }
142: } //run
143:
144: }
|