FileDocCategorySizeDatePackage
CharTerminatedInputStream.javaAPI DocApache James 2.3.15918Fri Jan 12 12:56:32 GMT 2007org.apache.james.util

CharTerminatedInputStream

public class CharTerminatedInputStream extends InputStream
An InputStream class that terminates the stream when it encounters a particular byte sequence.
version
1.0.0, 24/04/1999

Fields Summary
private InputStream
in
The wrapped input stream
private int[]
match
The terminating character array
private int[]
buffer
An array containing the last N characters read from the stream, where N is the length of the terminating character array
private int
pos
The number of bytes that have been read that have not been placed in the internal buffer.
private boolean
endFound
Whether the terminating sequence has been read from the stream
Constructors Summary
public CharTerminatedInputStream(InputStream in, char[] terminator)
A constructor for this object that takes a stream to be wrapped and a terminating character sequence.

param
in the InputStream to be wrapped
param
terminator the array of characters that will terminate the stream.
throws
IllegalArgumentException if the terminator array is null or empty


                                                      
         
        if (terminator == null) {
            throw new IllegalArgumentException("The terminating character array cannot be null.");
        }
        if (terminator.length == 0) {
            throw new IllegalArgumentException("The terminating character array cannot be of zero length.");
        }
        match = new int[terminator.length];
        buffer = new int[terminator.length];
        for (int i = 0; i < terminator.length; i++) {
            match[i] = (int)terminator[i];
            buffer[i] = (int)terminator[i];
        }
        this.in = in;
    
Methods Summary
public intread()
Read a byte off this stream.

return
the byte read off the stream
throws
IOException if an IOException is encountered while reading off the stream
throws
ProtocolException if the underlying stream returns -1 before the terminator is seen.

        if (endFound) {
            //We've found the match to the terminator
            return -1;
        }
        if (pos == 0) {
            //We have no data... read in a record
            int b = in.read();
            if (b == -1) {
                //End of stream reached without seeing the terminator
                throw new java.net.ProtocolException("pre-mature end of data");
            }
            if (b != match[0]) {
                //this char is not the first char of the match
                return b;
            }
            //this is a match...put this in the first byte of the buffer,
            // and fall through to matching logic
            buffer[0] = b;
            pos++;
        } else {
            if (buffer[0] != match[0]) {
                //Maybe from a previous scan, there is existing data,
                // and the first available char does not match the
                // beginning of the terminating string.
                return topChar();
            }
            //we have a match... fall through to matching logic.
        }
        //MATCHING LOGIC

        //The first character is a match... scan for complete match,
        // reading extra chars as needed, until complete match is found
        for (int i = 0; i < match.length; i++) {
            if (i >= pos) {
                int b = in.read();
                if (b == -1) {
                    //end of stream found, so match cannot be fulfilled.
                    // note we don't set endFound, because otherwise
                    // remaining part of buffer won't be returned.
                    return topChar();
                }
                //put the read char in the buffer
                buffer[pos] = b;
                pos++;
            }
            if (buffer[i] != match[i]) {
                //we did not find a match... return the top char
                return topChar();
            }
        }
        //A complete match was made...
        endFound = true;
        return -1;
    
private inttopChar()
Private helper method to update the internal buffer of last read characters

return
the byte that was previously at the front of the internal buffer

        int b = buffer[0];
        if (pos > 1) {
            //copy down the buffer to keep the fresh data at top
            System.arraycopy(buffer, 1, buffer, 0, pos - 1);
        }
        pos--;
        return b;