FileDocCategorySizeDatePackage
POP3Handler.javaAPI DocApache James 2.3.145681Fri Jan 12 12:56:24 GMT 2007org.apache.james.pop3server

POP3Handler

public class POP3Handler extends org.apache.avalon.framework.logger.AbstractLogEnabled implements org.apache.avalon.cornerstone.services.connection.ConnectionHandler, org.apache.avalon.excalibur.pool.Poolable
The handler class for POP3 connections.

Fields Summary
private static final String
softwaretype
private static final String
OK_RESPONSE
private static final String
ERR_RESPONSE
private static final int
AUTHENTICATION_READY
private static final int
AUTHENTICATION_USERSET
private static final int
TRANSACTION
private static final org.apache.mailet.Mail
DELETED
private POP3HandlerConfigurationData
theConfigData
The per-service configuration data that applies to all handlers
private org.apache.james.services.MailRepository
userInbox
The mail server's copy of the user's inbox
private Thread
handlerThread
The thread executing this handler
private Socket
socket
The TCP/IP socket over which the POP3 interaction is occurring
private org.apache.james.util.CRLFTerminatedReader
in
The reader associated with incoming characters.
private PrintWriter
out
The writer to which outgoing messages are written.
private OutputStream
outs
The socket's output stream
private int
state
The current transaction state of the handler
private String
user
The user id associated with the POP3 dialogue
private ArrayList
userMailbox
A dynamic list representing the set of emails in the user's inbox at any given time during the POP3 transaction.
private ArrayList
backupUserMailbox
private org.apache.james.util.watchdog.Watchdog
theWatchdog
The watchdog being used by this handler to deal with idle timeouts.
private org.apache.james.util.watchdog.WatchdogTarget
theWatchdogTarget
The watchdog target that idles out this handler.
Constructors Summary
Methods Summary
private voiddoDELE(java.lang.String command, java.lang.String argument, java.lang.String argument1)
Handler method called upon receipt of a DELE command. This command deletes a particular mail message from the mailbox.

param
command the command parsed by the parseCommand method
param
argument the first argument parsed by the parseCommand method
param
argument1 the second argument parsed by the parseCommand method

        String responseString = null;
        if (state == TRANSACTION) {
            int num = 0;
            try {
                num = Integer.parseInt(argument);
            } catch (Exception e) {
                responseString = ERR_RESPONSE + " Usage: DELE [mail number]";
                writeLoggedFlushedResponse(responseString);
                return;
            }
            try {
                Mail mc = (Mail) userMailbox.get(num);
                if (mc == DELETED) {
                    StringBuffer responseBuffer =
                        new StringBuffer(64)
                                .append(ERR_RESPONSE)
                                .append(" Message (")
                                .append(num)
                                .append(") already deleted.");
                    responseString = responseBuffer.toString();
                    writeLoggedFlushedResponse(responseString);
                } else {
                    userMailbox.set(num, DELETED);
                    writeLoggedFlushedResponse(OK_RESPONSE + " Message deleted");
                }
            } catch (IndexOutOfBoundsException iob) {
                StringBuffer responseBuffer =
                    new StringBuffer(64)
                            .append(ERR_RESPONSE)
                            .append(" Message (")
                            .append(num)
                            .append(") does not exist.");
                responseString = responseBuffer.toString();
                writeLoggedFlushedResponse(responseString);
            }
        } else {
            responseString = ERR_RESPONSE;
            writeLoggedFlushedResponse(responseString);
        }
    
private voiddoLIST(java.lang.String command, java.lang.String argument, java.lang.String argument1)
Handler method called upon receipt of a LIST command. Returns the number of messages in the mailbox and its aggregate size, or optionally, the number and size of a single message.

param
command the command parsed by the parseCommand method
param
argument the first argument parsed by the parseCommand method
param
argument1 the second argument parsed by the parseCommand method

        String responseString = null;
        if (state == TRANSACTION) {
            if (argument == null) {
                long size = 0;
                int count = 0;
                try {
                    for (Iterator i = userMailbox.iterator(); i.hasNext(); ) {
                        Mail mc = (Mail) i.next();
                        if (mc != DELETED) {
                            size += mc.getMessageSize();
                            count++;
                        }
                    }
                    StringBuffer responseBuffer =
                        new StringBuffer(32)
                                .append(OK_RESPONSE)
                                .append(" ")
                                .append(count)
                                .append(" ")
                                .append(size);
                    responseString = responseBuffer.toString();
                    writeLoggedFlushedResponse(responseString);
                    count = 0;
                    for (Iterator i = userMailbox.iterator(); i.hasNext(); count++) {
                        Mail mc = (Mail) i.next();

                        if (mc != DELETED) {
                            responseBuffer =
                                new StringBuffer(16)
                                        .append(count)
                                        .append(" ")
                                        .append(mc.getMessageSize());
                            out.println(responseBuffer.toString());
                        }
                    }
                    out.println(".");
                    out.flush();
                } catch (MessagingException me) {
                    responseString = ERR_RESPONSE;
                    writeLoggedFlushedResponse(responseString);
                }
            } else {
                int num = 0;
                try {
                    num = Integer.parseInt(argument);
                    Mail mc = (Mail) userMailbox.get(num);
                    if (mc != DELETED) {
                        StringBuffer responseBuffer =
                            new StringBuffer(64)
                                    .append(OK_RESPONSE)
                                    .append(" ")
                                    .append(num)
                                    .append(" ")
                                    .append(mc.getMessageSize());
                        responseString = responseBuffer.toString();
                        writeLoggedFlushedResponse(responseString);
                    } else {
                        StringBuffer responseBuffer =
                            new StringBuffer(64)
                                    .append(ERR_RESPONSE)
                                    .append(" Message (")
                                    .append(num)
                                    .append(") already deleted.");
                        responseString = responseBuffer.toString();
                        writeLoggedFlushedResponse(responseString);
                    }
                } catch (IndexOutOfBoundsException npe) {
                    StringBuffer responseBuffer =
                        new StringBuffer(64)
                                .append(ERR_RESPONSE)
                                .append(" Message (")
                                .append(num)
                                .append(") does not exist.");
                    responseString = responseBuffer.toString();
                    writeLoggedFlushedResponse(responseString);
                } catch (NumberFormatException nfe) {
                    StringBuffer responseBuffer =
                        new StringBuffer(64)
                                .append(ERR_RESPONSE)
                                .append(" ")
                                .append(argument)
                                .append(" is not a valid number");
                    responseString = responseBuffer.toString();
                    writeLoggedFlushedResponse(responseString);
                } catch (MessagingException me) {
                    responseString = ERR_RESPONSE;
                    writeLoggedFlushedResponse(responseString);
               }
            }
        } else {
            responseString = ERR_RESPONSE;
            writeLoggedFlushedResponse(responseString);
        }
    
private voiddoNOOP(java.lang.String command, java.lang.String argument, java.lang.String argument1)
Handler method called upon receipt of a NOOP command. Like all good NOOPs, does nothing much.

param
command the command parsed by the parseCommand method
param
argument the first argument parsed by the parseCommand method
param
argument1 the second argument parsed by the parseCommand method

        String responseString = null;
        if (state == TRANSACTION) {
            responseString = OK_RESPONSE;
            writeLoggedFlushedResponse(responseString);
        } else {
            responseString = ERR_RESPONSE;
            writeLoggedFlushedResponse(responseString);
        }
    
private voiddoPASS(java.lang.String command, java.lang.String argument, java.lang.String argument1)
Handler method called upon receipt of a PASS command. Reads in and validates the password.

param
command the command parsed by the parseCommand method
param
argument the first argument parsed by the parseCommand method
param
argument1 the second argument parsed by the parseCommand method

        String responseString = null;
        if (state == AUTHENTICATION_USERSET && argument != null) {
            String passArg = argument;
            if (theConfigData.getUsersRepository().test(user, passArg)) {
                StringBuffer responseBuffer =
                    new StringBuffer(64)
                            .append(OK_RESPONSE)
                            .append(" Welcome ")
                            .append(user);
                responseString = responseBuffer.toString();
                state = TRANSACTION;
                writeLoggedFlushedResponse(responseString);
                userInbox = theConfigData.getMailServer().getUserInbox(user);
                stat();
            } else {
                responseString = ERR_RESPONSE + " Authentication failed.";
                state = AUTHENTICATION_READY;
                writeLoggedFlushedResponse(responseString);
            }
        } else {
            responseString = ERR_RESPONSE;
            writeLoggedFlushedResponse(responseString);
        }
    
private voiddoQUIT(java.lang.String command, java.lang.String argument, java.lang.String argument1)
Handler method called upon receipt of a QUIT command. This method handles cleanup of the POP3Handler state.

param
command the command parsed by the parseCommand method
param
argument the first argument parsed by the parseCommand method
param
argument1 the second argument parsed by the parseCommand method

        String responseString = null;
        if (state == AUTHENTICATION_READY ||  state == AUTHENTICATION_USERSET) {
            responseString = OK_RESPONSE + " Apache James POP3 Server signing off.";
            writeLoggedFlushedResponse(responseString);
            return;
        }
        List toBeRemoved =  ListUtils.subtract(backupUserMailbox, userMailbox);
        try {
            userInbox.remove(toBeRemoved);
            // for (Iterator it = toBeRemoved.iterator(); it.hasNext(); ) {
            //    Mail mc = (Mail) it.next();
            //    userInbox.remove(mc.getName());
            //}
            responseString = OK_RESPONSE + " Apache James POP3 Server signing off.";
            writeLoggedFlushedResponse(responseString);
        } catch (Exception ex) {
            responseString = ERR_RESPONSE + " Some deleted messages were not removed";
            writeLoggedFlushedResponse(responseString);
            getLogger().error("Some deleted messages were not removed: " + ex.getMessage());
        }
    
private voiddoRETR(java.lang.String command, java.lang.String argument, java.lang.String argument1)
Handler method called upon receipt of a RETR command. This command retrieves a particular mail message from the mailbox.

param
command the command parsed by the parseCommand method
param
argument the first argument parsed by the parseCommand method
param
argument1 the second argument parsed by the parseCommand method

        String responseString = null;
        if (state == TRANSACTION) {
            int num = 0;
            try {
                num = Integer.parseInt(argument.trim());
            } catch (Exception e) {
                responseString = ERR_RESPONSE + " Usage: RETR [mail number]";
                writeLoggedFlushedResponse(responseString);
                return;
            }
            try {
                Mail mc = (Mail) userMailbox.get(num);
                if (mc != DELETED) {
                    responseString = OK_RESPONSE + " Message follows";
                    writeLoggedFlushedResponse(responseString);
                    try {
                        ExtraDotOutputStream edouts =
                                new ExtraDotOutputStream(outs);
                        OutputStream nouts = new BytesWrittenResetOutputStream(edouts,
                                                                  theWatchdog,
                                                                  theConfigData.getResetLength());
                        mc.getMessage().writeTo(nouts);
                        nouts.flush();
                        edouts.checkCRLFTerminator();
                        edouts.flush();
                    } finally {
                        out.println(".");
                        out.flush();
                    }
                } else {
                    StringBuffer responseBuffer =
                        new StringBuffer(64)
                                .append(ERR_RESPONSE)
                                .append(" Message (")
                                .append(num)
                                .append(") already deleted.");
                    responseString = responseBuffer.toString();
                    writeLoggedFlushedResponse(responseString);
                }
            } catch (IOException ioe) {
                responseString = ERR_RESPONSE + " Error while retrieving message.";
                writeLoggedFlushedResponse(responseString);
            } catch (MessagingException me) {
                responseString = ERR_RESPONSE + " Error while retrieving message.";
                writeLoggedFlushedResponse(responseString);
            } catch (IndexOutOfBoundsException iob) {
                StringBuffer responseBuffer =
                    new StringBuffer(64)
                            .append(ERR_RESPONSE)
                            .append(" Message (")
                            .append(num)
                            .append(") does not exist.");
                responseString = responseBuffer.toString();
                writeLoggedFlushedResponse(responseString);
            }
        } else {
            responseString = ERR_RESPONSE;
            writeLoggedFlushedResponse(responseString);
        }
    
private voiddoRSET(java.lang.String command, java.lang.String argument, java.lang.String argument1)
Handler method called upon receipt of a RSET command. Calls stat() to reset the mailbox.

param
command the command parsed by the parseCommand method
param
argument the first argument parsed by the parseCommand method
param
argument1 the second argument parsed by the parseCommand method

        String responseString = null;
        if (state == TRANSACTION) {
            stat();
            responseString = OK_RESPONSE;
        } else {
            responseString = ERR_RESPONSE;
        }
        writeLoggedFlushedResponse(responseString);
    
private voiddoSTAT(java.lang.String command, java.lang.String argument, java.lang.String argument1)
Handler method called upon receipt of a STAT command. Returns the number of messages in the mailbox and its aggregate size.

param
command the command parsed by the parseCommand method
param
argument the first argument parsed by the parseCommand method
param
argument1 the second argument parsed by the parseCommand method

        String responseString = null;
        if (state == TRANSACTION) {
            long size = 0;
            int count = 0;
            try {
                for (Iterator i = userMailbox.iterator(); i.hasNext(); ) {
                    Mail mc = (Mail) i.next();
                    if (mc != DELETED) {
                        size += mc.getMessageSize();
                        count++;
                    }
                }
                StringBuffer responseBuffer =
                    new StringBuffer(32)
                            .append(OK_RESPONSE)
                            .append(" ")
                            .append(count)
                            .append(" ")
                            .append(size);
                responseString = responseBuffer.toString();
                writeLoggedFlushedResponse(responseString);
            } catch (MessagingException me) {
                responseString = ERR_RESPONSE;
                writeLoggedFlushedResponse(responseString);
            }
        } else {
            responseString = ERR_RESPONSE;
            writeLoggedFlushedResponse(responseString);
        }
    
private voiddoTOP(java.lang.String command, java.lang.String argument, java.lang.String argument1)
Handler method called upon receipt of a TOP command. This command retrieves the top N lines of a specified message in the mailbox. The expected command format is TOP [mail message number] [number of lines to return]

param
command the command parsed by the parseCommand method
param
argument the first argument parsed by the parseCommand method
param
argument1 the second argument parsed by the parseCommand method

        String responseString = null;
        if (state == TRANSACTION) {
            int num = 0;
            int lines = 0;
            try {
                num = Integer.parseInt(argument);
                lines = Integer.parseInt(argument1);
            } catch (NumberFormatException nfe) {
                responseString = ERR_RESPONSE + " Usage: TOP [mail number] [Line number]";
                writeLoggedFlushedResponse(responseString);
                return;
            }
            try {
                Mail mc = (Mail) userMailbox.get(num);
                if (mc != DELETED) {
                    responseString = OK_RESPONSE + " Message follows";
                    writeLoggedFlushedResponse(responseString);
                    try {
                        for (Enumeration e = mc.getMessage().getAllHeaderLines(); e.hasMoreElements(); ) {
                            out.println(e.nextElement());
                        }
                        out.println();
                        ExtraDotOutputStream edouts =
                                new ExtraDotOutputStream(outs);
                        OutputStream nouts = new BytesWrittenResetOutputStream(edouts,
                                                                  theWatchdog,
                                                                  theConfigData.getResetLength());
                        writeMessageContentTo(mc.getMessage(),nouts,lines);
                        nouts.flush();
                        edouts.checkCRLFTerminator();
                        edouts.flush();
                    } finally {
                        out.println(".");
                        out.flush();
                    }
                } else {
                    StringBuffer responseBuffer =
                        new StringBuffer(64)
                                .append(ERR_RESPONSE)
                                .append(" Message (")
                                .append(num)
                                .append(") already deleted.");
                    responseString = responseBuffer.toString();
                    writeLoggedFlushedResponse(responseString);
                }
            } catch (IOException ioe) {
                responseString = ERR_RESPONSE + " Error while retrieving message.";
                writeLoggedFlushedResponse(responseString);
            } catch (MessagingException me) {
                responseString = ERR_RESPONSE + " Error while retrieving message.";
                writeLoggedFlushedResponse(responseString);
            } catch (IndexOutOfBoundsException iob) {
                StringBuffer exceptionBuffer =
                    new StringBuffer(64)
                            .append(ERR_RESPONSE)
                            .append(" Message (")
                            .append(num)
                            .append(") does not exist.");
                responseString = exceptionBuffer.toString();
                writeLoggedFlushedResponse(responseString);
            }
        } else {
            responseString = ERR_RESPONSE;
            writeLoggedFlushedResponse(responseString);
        }
    
private voiddoUIDL(java.lang.String command, java.lang.String argument, java.lang.String argument1)
Handler method called upon receipt of a UIDL command. Returns a listing of message ids to the client.

param
command the command parsed by the parseCommand method
param
argument the first argument parsed by the parseCommand method
param
argument1 the second argument parsed by the parseCommand method

        String responseString = null;
        if (state == TRANSACTION) {
            if (argument == null) {
                responseString = OK_RESPONSE + " unique-id listing follows";
                writeLoggedFlushedResponse(responseString);
                int count = 0;
                for (Iterator i = userMailbox.iterator(); i.hasNext(); count++) {
                    Mail mc = (Mail) i.next();
                    if (mc != DELETED) {
                        StringBuffer responseBuffer =
                            new StringBuffer(64)
                                    .append(count)
                                    .append(" ")
                                    .append(mc.getName());
                        out.println(responseBuffer.toString());
                    }
                }
                out.println(".");
                out.flush();
            } else {
                int num = 0;
                try {
                    num = Integer.parseInt(argument);
                    Mail mc = (Mail) userMailbox.get(num);
                    if (mc != DELETED) {
                        StringBuffer responseBuffer =
                            new StringBuffer(64)
                                    .append(OK_RESPONSE)
                                    .append(" ")
                                    .append(num)
                                    .append(" ")
                                    .append(mc.getName());
                        responseString = responseBuffer.toString();
                        writeLoggedFlushedResponse(responseString);
                    } else {
                        StringBuffer responseBuffer =
                            new StringBuffer(64)
                                    .append(ERR_RESPONSE)
                                    .append(" Message (")
                                    .append(num)
                                    .append(") already deleted.");
                        responseString = responseBuffer.toString();
                        writeLoggedFlushedResponse(responseString);
                    }
                } catch (IndexOutOfBoundsException npe) {
                    StringBuffer responseBuffer =
                        new StringBuffer(64)
                                .append(ERR_RESPONSE)
                                .append(" Message (")
                                .append(num)
                                .append(") does not exist.");
                    responseString = responseBuffer.toString();
                    writeLoggedFlushedResponse(responseString);
                } catch (NumberFormatException nfe) {
                    StringBuffer responseBuffer =
                        new StringBuffer(64)
                                .append(ERR_RESPONSE)
                                .append(" ")
                                .append(argument)
                                .append(" is not a valid number");
                    responseString = responseBuffer.toString();
                    writeLoggedFlushedResponse(responseString);
                }
            }
        } else {
            writeLoggedFlushedResponse(ERR_RESPONSE);
        }
    
private voiddoUSER(java.lang.String command, java.lang.String argument, java.lang.String argument1)
Handler method called upon receipt of a USER command. Reads in the user id.

param
command the command parsed by the parseCommand method
param
argument the first argument parsed by the parseCommand method
param
argument1 the second argument parsed by the parseCommand method

        String responseString = null;
        if (state == AUTHENTICATION_READY && argument != null) {
            user = argument;
            state = AUTHENTICATION_USERSET;
            responseString = OK_RESPONSE;
        } else {
            responseString = ERR_RESPONSE;
        }
        writeLoggedFlushedResponse(responseString);
    
private voiddoUnknownCmd(java.lang.String command, java.lang.String argument, java.lang.String argument1)
Handler method called upon receipt of an unrecognized command. Returns an error response and logs the command.

param
command the command parsed by the parseCommand method
param
argument the first argument parsed by the parseCommand method
param
argument1 the second argument parsed by the parseCommand method

        writeLoggedFlushedResponse(ERR_RESPONSE);
    
org.apache.james.util.watchdog.WatchdogTargetgetWatchdogTarget()
Gets the Watchdog Target that should be used by Watchdogs managing this connection.

return
the WatchdogTarget

        return theWatchdogTarget;
    
public voidhandleConnection(java.net.Socket connection)

see
org.apache.avalon.cornerstone.services.connection.ConnectionHandler#handleConnection(Socket)


        String remoteHost = "";
        String remoteIP = "";

        try {
            this.socket = connection;
            synchronized (this) {
                handlerThread = Thread.currentThread();
            }
            // in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "ASCII"), 512);
            in = new CRLFTerminatedReader(new BufferedInputStream(socket.getInputStream(), 512), "ASCII");
            remoteIP = socket.getInetAddress().getHostAddress ();
            remoteHost = socket.getInetAddress().getHostName ();
        } catch (Exception e) {
            if (getLogger().isErrorEnabled()) {
                StringBuffer exceptionBuffer =
                    new StringBuffer(256)
                            .append("Cannot open connection from ")
                            .append(remoteHost)
                            .append(" (")
                            .append(remoteIP)
                            .append("): ")
                            .append(e.getMessage());
                getLogger().error( exceptionBuffer.toString(), e );
            }
        }

        if (getLogger().isInfoEnabled()) {
            StringBuffer logBuffer =
                new StringBuffer(128)
                        .append("Connection from ")
                        .append(remoteHost)
                        .append(" (")
                        .append(remoteIP)
                        .append(") ");
            getLogger().info(logBuffer.toString());
        }

        try {
            outs = new BufferedOutputStream(socket.getOutputStream(), 1024);
            out = new InternetPrintWriter(outs, true);
            state = AUTHENTICATION_READY;
            user = "unknown";
            StringBuffer responseBuffer =
                new StringBuffer(256)
                        .append(OK_RESPONSE)
                        .append(" ")
                        .append(theConfigData.getHelloName())
                        .append(" POP3 server (")
                        .append(POP3Handler.softwaretype)
                        .append(") ready ");
            out.println(responseBuffer.toString());

            theWatchdog.start();
            while (parseCommand(readCommandLine())) {
                theWatchdog.reset();
            }
            theWatchdog.stop();
            if (getLogger().isInfoEnabled()) {
                StringBuffer logBuffer =
                    new StringBuffer(128)
                        .append("Connection for ")
                        .append(user)
                        .append(" from ")
                        .append(remoteHost)
                        .append(" (")
                        .append(remoteIP)
                        .append(") closed.");
                getLogger().info(logBuffer.toString());
            }
        } catch (Exception e) {
            out.println(ERR_RESPONSE + " Error closing connection.");
            out.flush();
            StringBuffer exceptionBuffer =
                new StringBuffer(128)
                        .append("Exception during connection from ")
                        .append(remoteHost)
                        .append(" (")
                        .append(remoteIP)
                        .append(") : ")
                        .append(e.getMessage());
            getLogger().error(exceptionBuffer.toString(), e );
        } finally {
            resetHandler();
        }
    
voididleClose()
Idle out this connection

        if (getLogger() != null) {
            getLogger().error("POP3 Connection has idled out.");
        }
        try {
            if (socket != null) {
                socket.close();
            }
        } catch (Exception e) {
            // ignored
        } finally {
            socket = null;
        }

        synchronized (this) {
            // Interrupt the thread to recover from internal hangs
            if (handlerThread != null) {
                handlerThread.interrupt();
                handlerThread = null;
            }
        }

    
private final voidlogResponseString(java.lang.String responseString)
This method logs at a "DEBUG" level the response string that was sent to the POP3 client. The method is provided largely as syntactic sugar to neaten up the code base. It is declared private and final to encourage compiler inlining.

param
responseString the response string sent to the client

        if (getLogger().isDebugEnabled()) {
            getLogger().debug("Sent: " + responseString);
        }
    
private booleanparseCommand(java.lang.String rawCommand)
This method parses POP3 commands read off the wire in handleConnection. Actual processing of the command (possibly including additional back and forth communication with the client) is delegated to one of a number of command specific handler methods. The primary purpose of this method is to parse the raw command string to determine exactly which handler should be called. It returns true if expecting additional commands, false otherwise.

param
rawCommand the raw command string passed in over the socket
return
whether additional commands are expected.

        if (rawCommand == null) {
            return false;
        }
        boolean returnValue = true;
        String command = rawCommand;
        StringTokenizer commandLine = new StringTokenizer(command, " ");
        int arguments = commandLine.countTokens();
        if (arguments == 0) {
            return true;
        } else if(arguments > 0) {
            command = commandLine.nextToken().toUpperCase(Locale.US);
        }
        if (getLogger().isDebugEnabled()) {
            // Don't display password in logger
            if (!command.equals("PASS")) {
                getLogger().debug("Command received: " + rawCommand);
            } else {
                getLogger().debug("Command received: PASS <password omitted>");
            }
        }
        String argument = null;
        if(arguments > 1) {
            argument = commandLine.nextToken();
        }
        String argument1 = null;
        if(arguments > 2) {
            argument1 = commandLine.nextToken();
        }

        if (command.equals("USER")) {
            doUSER(command,argument,argument1);
        } else if (command.equals("PASS")) {
            doPASS(command,argument,argument1);
        } else if (command.equals("STAT")) {
            doSTAT(command,argument,argument1);
        } else if (command.equals("LIST")) {
            doLIST(command,argument,argument1);
        } else if (command.equals("UIDL")) {
            doUIDL(command,argument,argument1);
        } else if (command.equals("RSET")) {
            doRSET(command,argument,argument1);
        } else if (command.equals("DELE")) {
            doDELE(command,argument,argument1);
        } else if (command.equals("NOOP")) {
            doNOOP(command,argument,argument1);
        } else if (command.equals("RETR")) {
            doRETR(command,argument,argument1);
        } else if (command.equals("TOP")) {
            doTOP(command,argument,argument1);
        } else if (command.equals("QUIT")) {
            returnValue = false;
            doQUIT(command,argument,argument1);
        } else {
            doUnknownCmd(command,argument,argument1);
        }
        return returnValue;
    
final java.lang.StringreadCommandLine()
Reads a line of characters off the command line.

return
the trimmed input line
throws
IOException if an exception is generated reading in the input characters

        for (;;) try {
            String commandLine = in.readLine();
            if (commandLine != null) {
                commandLine = commandLine.trim();
            }
            return commandLine;
        } catch (CRLFTerminatedReader.TerminationException te) {
            writeLoggedFlushedResponse("-ERR Syntax error at character position " + te.position() + ". CR and LF must be CRLF paired.  See RFC 1939 #3.");
        }
    
private voidresetHandler()
Resets the handler data to a basic state.


        if (theWatchdog != null) {
            ContainerUtil.dispose(theWatchdog);
            theWatchdog = null;
        }

        // Close and clear streams, sockets

        try {
            if (socket != null) {
                socket.close();
                socket = null;
            }
        } catch (IOException ioe) {
            // Ignoring exception on close
        } finally {
            socket = null;
        }

        try {
            if (in != null) {
                in.close();
            }
        } catch (Exception e) {
            // Ignored
        } finally {
            in = null;
        }

        try {
            if (out != null) {
                out.close();
            }
        } catch (Exception e) {
            // Ignored
        } finally {
            out = null;
        }

        try {
           if (outs != null) {
               outs.close();
            }
        } catch (Exception e) {
            // Ignored
        } finally {
            outs = null;
        }

        synchronized (this) {
            handlerThread = null;
        }

        // Clear user data
        user = null;
        userInbox = null;
        if (userMailbox != null) {
            userMailbox.clear();
            userMailbox = null;
        }

        if (backupUserMailbox != null) {
            backupUserMailbox.clear();
            backupUserMailbox = null;
        }

        // Clear config data
        theConfigData = null;
    
voidsetConfigurationData(POP3HandlerConfigurationData theData)
Set the configuration data for the handler.

param
theData the configuration data


                     
       
        theConfigData = theData;
    
voidsetWatchdog(org.apache.james.util.watchdog.Watchdog theWatchdog)
Set the Watchdog for use by this handler.

param
theWatchdog the watchdog

        this.theWatchdog = theWatchdog;
    
private voidstat()
Implements a "stat". If the handler is currently in a transaction state, this amounts to a rollback of the mailbox contents to the beginning of the transaction. This method is also called when first entering the transaction state to initialize the handler copies of the user inbox.

        userMailbox = new ArrayList();
        userMailbox.add(DELETED);
        try {
            for (Iterator it = userInbox.list(); it.hasNext(); ) {
                String key = (String) it.next();
                Mail mc = userInbox.retrieve(key);
                // Retrieve can return null if the mail is no longer in the store.
                // In this case we simply continue to the next key
                if (mc == null) {
                    continue;
                }
                userMailbox.add(mc);
            }
        } catch(MessagingException e) {
            // In the event of an exception being thrown there may or may not be anything in userMailbox
            getLogger().error("Unable to STAT mail box ", e);
        }
        finally {
            backupUserMailbox = (ArrayList) userMailbox.clone();
        }
    
final voidwriteLoggedFlushedResponse(java.lang.String responseString)
Write and flush a response string. The response is also logged. Should be used for the last line of a multi-line response or for a single line response.

param
responseString the response string sent to the client

        out.println(responseString);
        out.flush();
        logResponseString(responseString);
    
final voidwriteLoggedResponse(java.lang.String responseString)
Write a response string. The response is also logged. Used for multi-line responses.

param
responseString the response string sent to the client

        out.println(responseString);
        logResponseString(responseString);
    
public voidwriteMessageContentTo(javax.mail.internet.MimeMessage message, java.io.OutputStream out, int lines)
Writes the content of the message, up to a total number of lines, out to an OutputStream.

param
out the OutputStream to which to write the content
param
lines the number of lines to write to the stream
throws
MessagingException if the MimeMessage is not set for this MailImpl
throws
IOException if an error occurs while reading or writing from the stream

        String line;
        BufferedReader br;
        if (message != null) {
            br = new BufferedReader(new InputStreamReader(message.getRawInputStream()));
            try {
                while (lines-- > 0) {
                    if ((line = br.readLine()) == null) {
                        break;
                    }
                    line += "\r\n";
                    out.write(line.getBytes());
                }
            } finally {
                br.close();
            }
        } else {
            throw new MessagingException("No message set for this MailImpl.");
        }