FileDocCategorySizeDatePackage
DotTerminatedMessageReader.javaAPI DocApache Commons NET 1.4.1 API8913Sat Dec 03 10:05:50 GMT 2005org.apache.commons.net.io

DotTerminatedMessageReader

public final class DotTerminatedMessageReader extends Reader
DotTerminatedMessageReader is a class used to read messages from a server that are terminated by a single dot followed by a <CR><LF> sequence and with double dots appearing at the begining of lines which do not signal end of message yet start with a dot. Various Internet protocols such as NNTP and POP3 produce messages of this type.

This class handles stripping of the duplicate period at the beginning of lines starting with a period, converts NETASCII newlines to the local line separator format, truncates the end of message indicator, and ensures you cannot read past the end of the message.

author
Daniel F. Savarese
version
$Id: DotTerminatedMessageReader.java 165675 2005-05-02 20:09:55Z rwinston $

Fields Summary
private static final String
LS
private static final char[]
LS_CHARS
private boolean
atBeginning
private boolean
eof
private int
pos
private char[]
internalBuffer
private PushbackReader
internalReader
Constructors Summary
public DotTerminatedMessageReader(Reader reader)
Creates a DotTerminatedMessageReader that wraps an existing Reader input source.

param
reader The Reader input source containing the message.

        super(reader);
        internalBuffer = new char[LS_CHARS.length + 3];
        pos = internalBuffer.length;
        // Assumes input is at start of message
        atBeginning = true;
        eof = false;
        internalReader = new PushbackReader(reader);
    
Methods Summary
public voidclose()
Closes the message for reading. This doesn't actually close the underlying stream. The underlying stream may still be used for communicating with the server and therefore is not closed.

If the end of the message has not yet been reached, this method will read the remainder of the message until it reaches the end, so that the underlying stream may continue to be used properly for communicating with the server. If you do not fully read a message, you MUST close it, otherwise your program will likely hang or behave improperly.

exception
IOException If an error occurs while reading the underlying stream.

        synchronized (lock)
        {
            if (internalReader == null)
            {
                return;
            }

            if (!eof)
            {
                while (read() != -1)
                {
                    ;
                }
            }
            eof = true;
            atBeginning = false;
            pos = internalBuffer.length;
            internalReader = null;
        }
    
public intread()
Reads and returns the next character in the message. If the end of the message has been reached, returns -1. Note that a call to this method may result in multiple reads from the underlying input stream to decode the message properly (removing doubled dots and so on). All of this is transparent to the programmer and is only mentioned for completeness.

return
The next character in the message. Returns -1 if the end of the message has been reached.
exception
IOException If an error occurs while reading the underlying stream.

        int ch;

        synchronized (lock)
        {
            if (pos < internalBuffer.length)
            {
                return internalBuffer[pos++];
            }

            if (eof)
            {
                return -1;
            }

            if ((ch = internalReader.read()) == -1)
            {
                eof = true;
                return -1;
            }

            if (atBeginning)
            {
                atBeginning = false;
                if (ch == '.")
                {
                    ch = internalReader.read();

                    if (ch != '.")
                    {
                        // read newline
                        eof = true;
                        internalReader.read();
                        return -1;
                    }
                    else
                    {
                        return '.";
                    }
                }
            }

            if (ch == '\r")
            {
                ch = internalReader.read();

                if (ch == '\n")
                {
                    ch = internalReader.read();

                    if (ch == '.")
                    {
                        ch = internalReader.read();

                        if (ch != '.")
                        {
                            // read newline and indicate end of file
                            internalReader.read();
                            eof = true;
                        }
                        else
                        {
                            internalBuffer[--pos] = (char) ch;
                        }
                    }
                    else
                    {
                        internalReader.unread(ch);
                    }

                    pos -= LS_CHARS.length;
                    System.arraycopy(LS_CHARS, 0, internalBuffer, pos,
                                     LS_CHARS.length);
                    ch = internalBuffer[pos++];
                }
                else
                {
                    internalBuffer[--pos] = (char) ch;
                    return '\r";
                }
            }

            return ch;
        }
    
public intread(char[] buffer)
Reads the next characters from the message into an array and returns the number of characters read. Returns -1 if the end of the message has been reached.

param
buffer The character array in which to store the characters.
return
The number of characters read. Returns -1 if the end of the message has been reached.
exception
IOException If an error occurs in reading the underlying stream.

        return read(buffer, 0, buffer.length);
    
public intread(char[] buffer, int offset, int length)
Reads the next characters from the message into an array and returns the number of characters read. Returns -1 if the end of the message has been reached. The characters are stored in the array starting from the given offset and up to the length specified.

param
buffer The character array in which to store the characters.
param
offset The offset into the array at which to start storing characters.
param
length The number of characters to read.
return
The number of characters read. Returns -1 if the end of the message has been reached.
exception
IOException If an error occurs in reading the underlying stream.

        int ch, off;
        synchronized (lock)
        {
            if (length < 1)
            {
                return 0;
            }
            if ((ch = read()) == -1)
            {
                return -1;
            }
            off = offset;

            do
            {
                buffer[offset++] = (char) ch;
            }
            while (--length > 0 && (ch = read()) != -1);

            return (offset - off);
        }
    
public booleanready()
Determines if the message is ready to be read.

return
True if the message is ready to be read, false if not.
exception
IOException If an error occurs while checking the underlying stream.

        synchronized (lock)
        {
            return (pos < internalBuffer.length || internalReader.ready());
        }