/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.geronimo.javamail.store.imap.connection;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;

import javax.mail.Address;
import javax.mail.AuthenticationFailedException;
import javax.mail.FetchProfile;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.MethodNotSupportedException;
import javax.mail.Quota;
import javax.mail.Session;
import javax.mail.UIDFolder;
import javax.mail.URLName;

import javax.mail.internet.InternetHeaders;

import javax.mail.search.SearchTerm;

import org.apache.geronimo.javamail.authentication.AuthenticatorFactory;
import org.apache.geronimo.javamail.authentication.ClientAuthenticator;
import org.apache.geronimo.javamail.authentication.LoginAuthenticator;
import org.apache.geronimo.javamail.authentication.PlainAuthenticator;
import org.apache.geronimo.javamail.store.imap.ACL;
import org.apache.geronimo.javamail.store.imap.Rights;

import org.apache.geronimo.javamail.util.CommandFailedException;
import org.apache.geronimo.javamail.util.InvalidCommandException;
import org.apache.geronimo.javamail.util.MailConnection;
import org.apache.geronimo.javamail.util.ProtocolProperties;
import org.apache.geronimo.javamail.util.TraceInputStream;
import org.apache.geronimo.javamail.util.TraceOutputStream;
import org.apache.geronimo.mail.util.Base64;

/**
 * Simple implementation of IMAP transport.  Just does plain RFC977-ish
 * delivery.
 * <p/>
 * There is no way to indicate failure for a given recipient (it's possible to have a
 * recipient address rejected).  The sun impl throws exceptions even if others successful),
 * but maybe we do a different way...
 * <p/>
 *
 * @version $Rev$ $Date$
 */
public class IMAPConnection extends MailConnection {

    protected static final String CAPABILITY_LOGIN_DISABLED = "LOGINDISABLED";

    // The connection pool we're a member of.  This keeps holds most of the
    // connnection parameter information for us.
    protected IMAPConnectionPool pool;

    // special input stream for reading individual response lines.
    protected IMAPResponseStream reader;

    // connection pool connections.
    protected long lastAccess = 0;
    // our handlers for any untagged responses
    protected LinkedList responseHandlers = new LinkedList();
    // the list of queued untagged responses.
    protected List queuedResponses = new LinkedList();
    // this is set on if we had a forced disconnect situation from
    // the server.
    protected boolean closed = false;

    /**
     * Normal constructor for an IMAPConnection() object.
     *
     * @param props  The protocol properties abstraction containing our
     *               property modifiers.
     * @param pool
     */
    public IMAPConnection(ProtocolProperties props, IMAPConnectionPool pool) {
        super(props);
        this.pool = pool;
    }


    /**
     * Connect to the server and do the initial handshaking.
     *
     * @exception MessagingException
     */
    public boolean protocolConnect(String host, int port, String authid, String realm, String username, String password) throws MessagingException {
        this.serverHost = host;
        this.serverPort = port;
        this.realm = realm;
        this.authid = authid;
        this.username = username;
        this.password = password;

        boolean preAuthorized = false;

        try {
            // create socket and connect to server.
            getConnection();

            // we need to ask the server what its capabilities are.  This can be done
            // before we login.
            getCapability();
            // do a preauthoriziation check.
            if (extractResponse("PREAUTH") != null) {
                preAuthorized = true;
            }

            // make sure we process these now
            processPendingResponses();
            
            boolean requireTLS = props.getBooleanProperty(MAIL_STARTTLS_REQUIRED, false);
            boolean enableTLS = props.getBooleanProperty(MAIL_STARTTLS_ENABLE, false);
            boolean serverSupportsTLS = hasCapability(CAPABILITY_STARTTLS);

            // if we're not already using an SSL connection, and we have permission to issue STARTTLS or its even required
            // try to setup a SSL connection
            if (!sslConnection && (enableTLS || requireTLS)) {
                
                //if the server does not support TLS check if its required.
                //If true then throw an error, if not establish a non SSL connection
                if(requireTLS && !serverSupportsTLS) {
                    throw new MessagingException("Server doesn't support required transport level security");
                } else if (serverSupportsTLS){
                    // tell the server of our intention to start a TLS session
                    sendSimpleCommand("STARTTLS");
    
                    // The connection is then handled by the superclass level.
                    getConnectedTLSSocket();
    
                    // create the special reader for pulling the responses.
                    reader = new IMAPResponseStream(inputStream);
    
                    // the IMAP spec states that the capability response is independent of login state or
                    // user, but I'm not sure I believe that to be the case.  It doesn't hurt to refresh
                    // the information again after establishing a secure connection.
                    getCapability();
                    // and we need to repeat this check.
                    if (extractResponse("PREAUTH") != null) {
                        preAuthorized = true;
                    }
                } else {
                    if (debug) {
                        debugOut("STARTTLS is enabled but not required and server does not support it. So we establish a connection without transport level security");
                    }
                }
                
            }

            // damn, no login required.
            if (preAuthorized) {
                return true;
            }

            // go login with the server
            return login();
        } catch (IOException e) {
            if (debug) {
                debugOut("I/O exception establishing connection", e);
            }
            throw new MessagingException("Connection error", e);
        }
        finally {
            // make sure the queue is cleared
            processPendingResponses();
        }
    }

    /**
     * Update the last access time for the connection.
     */
    protected void updateLastAccess() {
        lastAccess = System.currentTimeMillis();
    }

    /**
     * Test if the connection has been sitting idle for longer than
     * the set timeout period.
     *
     * @param timeout The allowed "freshness" interval.
     *
     * @return True if the connection has been active within the required
     *         interval, false if it has been sitting idle for too long.
     */
    public boolean isStale(long timeout) {
        return (System.currentTimeMillis() - lastAccess) > timeout;
    }


    /**
     * Close the connection.  On completion, we'll be disconnected from
     * the server and unable to send more data.
     *
     * @exception MessagingException
     */
    public void close() throws MessagingException {
        // if we're already closed, get outta here.
        if (socket == null) {
            return;
        }
        try {
            // say goodbye
            logout();
        } finally {
            // and close up the connection.  We do this in a finally block to make sure the connection
            // is shut down even if quit gets an error.
            closeServerConnection();
            // get rid of our response processor too.
            reader = null;
        }
    }


    /**
     * Create a transport connection object and connect it to the
     * target server.
     *
     * @exception MessagingException
     */
    protected void getConnection() throws IOException, MessagingException
    {
        // do all of the non-protocol specific set up.  This will get our socket established
        // and ready use.
        super.getConnection();
        // create the special reader for pulling the responses.
        reader = new IMAPResponseStream(inputStream);

        // set the initial access time stamp
        updateLastAccess();
    }


    /**
     * Process a simple command/response sequence between the
     * client and the server.  These are commands where the
     * client is expecting them to "just work", and also will not
     * directly process the reply information.  Unsolicited untagged
     * responses are dispatched to handlers, and a MessagingException
     * will be thrown for any non-OK responses from the server.
     *
     * @param data   The command data we're writing out.
     *
     * @exception MessagingException
     */
    public void sendSimpleCommand(String data) throws MessagingException {
        // create a command object and issue the command with that.
        IMAPCommand command = new IMAPCommand(data);
        sendSimpleCommand(command);
    }


    /**
     * Process a simple command/response sequence between the
     * client and the server.  These are commands where the
     * client is expecting them to "just work", and also will not
     * directly process the reply information.  Unsolicited untagged
     * responses are dispatched to handlers, and a MessagingException
     * will be thrown for any non-OK responses from the server.
     *
     * @param data   The command data we're writing out.
     *
     * @exception MessagingException
     */
    public void sendSimpleCommand(IMAPCommand data) throws MessagingException {
        // the command sending process will raise exceptions for bad responses....
        // we just need to send the command and forget about it.
        sendCommand(data);
    }


    /**
     * Sends a  command down the socket, returning the server response.
     *
     * @param data   The String form of the command.
     *
     * @return The tagged response information that terminates the command interaction.
     * @exception MessagingException
     */
    public IMAPTaggedResponse sendCommand(String data) throws MessagingException {
        IMAPCommand command = new IMAPCommand(data);
        return sendCommand(command);
    }


    /**
     * Sends a  command down the socket, returning the server response.
     *
     * @param data   An IMAPCommand object with the prepared command information.
     *
     * @return The tagged (or continuation) response information that terminates the
     *         command response sequence.
     * @exception MessagingException
     */
    public synchronized IMAPTaggedResponse sendCommand(IMAPCommand data) throws MessagingException {
        // check first
        checkConnected();
        try {
            // have the command write the command data.  This also prepends a tag.
            data.writeTo(outputStream, this);
            outputStream.flush();
            // update the activity timestamp
            updateLastAccess();
            // get the received response
            return receiveResponse();
        } catch (IOException e) {
            throw new MessagingException(e.toString(), e);
        }
    }


    /**
     * Sends a  message down the socket and terminates with the
     * appropriate CRLF
     *
     * @param data   The string data to send.
     *
     * @return An IMAPTaggedResponse item returned from the server.
     * @exception MessagingException
     */
    public IMAPTaggedResponse sendLine(String data) throws MessagingException {
        try {
            return sendLine(data.getBytes("ISO8859-1"));
        } catch (UnsupportedEncodingException e) {
            // should never happen
            return null;
        }
    }


    /**
     * Sends a  message down the socket and terminates with the
     * appropriate CRLF
     *
     * @param data   The array of data to send to the server.
     *
     * @return The response item returned from the IMAP server.
     * @exception MessagingException
     */
    public IMAPTaggedResponse sendLine(byte[] data) throws MessagingException {
        return sendLine(data, 0, data.length);
    }


    /**
     * Sends a  message down the socket and terminates with the
     * appropriate CRLF
     *
     * @param data   The source data array.
     * @param offset The offset within the data array.
     * @param length The length of data to send.
     *
     * @return The response line returned from the IMAP server.
     * @exception MessagingException
     */
    public synchronized IMAPTaggedResponse sendLine(byte[] data, int offset, int length) throws MessagingException {
        // check first
        checkConnected();

        try {
            outputStream.write(data, offset, length);
            outputStream.write(CR);
            outputStream.write(LF);
            outputStream.flush();
            // update the activity timestamp
            updateLastAccess();
            return receiveResponse();
        } catch (IOException e) {
            throw new MessagingException(e.toString(), e);
        }
    }


    /**
     * Get a reply line for an IMAP command.
     *
     * @return An IMAP reply object from the stream.
     */
    public IMAPTaggedResponse receiveResponse() throws MessagingException {
        while (true) {
            // read and parse a response from the server.
            IMAPResponse response = reader.readResponse();
            // The response set is terminated by either a continuation response or a
            // tagged response (we only have a single command active at one time).
            if (response instanceof IMAPTaggedResponse) {
                // update the access time stamp for later timeout processing.
                updateLastAccess();
                IMAPTaggedResponse tagged = (IMAPTaggedResponse)response;
                // we turn these into exceptions here, which means the issuer doesn't have to
                // worry about checking status.
                if (tagged.isBAD()) {
                    throw new InvalidCommandException("Unexpected command IMAP command error");
                }
                else if (tagged.isNO()) {
                    throw new CommandFailedException("Unexpected error executing IMAP command");
                }
                return tagged;
            }
            else {
                // all other unsolicited responses are either async status updates or
                // additional elements of a command we just sent.  These will be processed
                // either during processing of the command response, or at the end of the
                // current command processing.
                queuePendingResponse((IMAPUntaggedResponse)response);
            }
        }
    }


    /**
     * Get the servers capabilities from the wire....
     */
    public void getCapability() throws MessagingException {
        sendCommand("CAPABILITY");
        // get the capabilities from the response.
        IMAPCapabilityResponse response = (IMAPCapabilityResponse)extractResponse("CAPABILITY");
        capabilities = response.getCapabilities();
        authentications = response.getAuthentications();
    }

    /**
     * Logs out from the server.
     */
    public void logout() throws MessagingException {
        // We can just send the command and generally ignore the
        // status response.
        sendCommand("LOGOUT");
    }

    /**
     * Deselect a mailbox when a folder returns a connection.
     *
     * @exception MessagingException
     */
    public void closeMailbox() throws MessagingException {
        // We can just send the command and generally ignore the
        // status response.
        sendCommand("CLOSE");
    }


    /**
     * Authenticate with the server, if necessary (or possible).
     *
     * @return true if we were able to authenticate correctly, false for authentication failures.
     * @exception MessagingException
     */
    protected boolean login() throws MessagingException
    {
        // if no username or password, fail this immediately.
        // the base connect property should resolve a username/password combo for us and
        // try again.
        if (username == null || password == null) {
            return false;
        }

        // are we permitted to use SASL mechanisms?
        if (props.getBooleanProperty(MAIL_SASL_ENABLE, false)) {
            // we might be enable for SASL, but the client and the server might
            // not have any supported mechanisms in common.  Try again with another
            // mechanism.
            if (processSaslAuthentication()) {
                return true;
            }
        }

        // see if we're allowed to try plain.
        if (!props.getBooleanProperty(MAIL_PLAIN_DISABLE, false) && supportsMechanism(AUTHENTICATION_PLAIN)) {
            return processPlainAuthentication();
        }

        // see if we're allowed to try login.
        if (!props.getBooleanProperty(MAIL_LOGIN_DISABLE, false) && supportsMechanism(AUTHENTICATION_LOGIN)) {
            // no authzid capability with this authentication method.
            return processLoginAuthentication();
        }

        // the server can choose to disable the LOGIN command.  If not disabled, try
        // using LOGIN rather than AUTHENTICATE.
        if (!hasCapability(CAPABILITY_LOGIN_DISABLED)) {
            return processLogin();
        }

        throw new MessagingException("No supported LOGIN methods enabled");
    }


    /**
     * Process SASL-type authentication.
     *
     * @return Returns true if the server support a SASL authentication mechanism and
     * accepted reponse challenges.
     * @exception MessagingException
     */
    protected boolean processSaslAuthentication() throws MessagingException {
        // if unable to get an appropriate authenticator, just fail it.
        ClientAuthenticator authenticator = getSaslAuthenticator();
        if (authenticator == null) {
            return false;
        }

        // go process the login.
        return processLogin(authenticator);
    }

    protected ClientAuthenticator getSaslAuthenticator() {
        return AuthenticatorFactory.getAuthenticator(props, selectSaslMechanisms(), serverHost, username, password, authid, realm);
    }

    /**
     * Process SASL-type PLAIN authentication.
     *
     * @return Returns true if the login is accepted.
     * @exception MessagingException
     */
    protected boolean processPlainAuthentication() throws MessagingException {
        // go process the login.
        return processLogin(new PlainAuthenticator(authid, username, password));
    }


    /**
     * Process SASL-type LOGIN authentication.
     *
     * @return Returns true if the login is accepted.
     * @exception MessagingException
     */
    protected boolean processLoginAuthentication() throws MessagingException {
        // go process the login.
        return processLogin(new LoginAuthenticator(username, password));
    }


    /**
     * Process a LOGIN using the LOGIN command instead of AUTHENTICATE.
     *
     * @return true if the command succeeded, false for any authentication failures.
     * @exception MessagingException
     */
    protected boolean processLogin() throws MessagingException {
        // arguments are "LOGIN userid password"
        IMAPCommand command = new IMAPCommand("LOGIN");
        command.appendAtom(username);
        command.appendAtom(password);

        // go issue the command
        try {
            sendCommand(command);
        } catch (CommandFailedException e) {
            // we'll get a NO response for a rejected login
            return false;
        }
        // seemed to work ok....
        return true;
    }


    /**
     * Process a login using the provided authenticator object.
     *
     * NB:  This method is synchronized because we have a multi-step process going on
     * here.  No other commands should be sent to the server until we complete.
     *
     * @return Returns true if the server support a SASL authentication mechanism and
     * accepted reponse challenges.
     * @exception MessagingException
     */
    protected synchronized boolean processLogin(ClientAuthenticator authenticator) throws MessagingException {
        if (debug) {
            debugOut("Authenticating for user: " + username + " using " + authenticator.getMechanismName());
        }

        IMAPCommand command = new IMAPCommand("AUTHENTICATE");
        // and tell the server which mechanism we're using.
        command.appendAtom(authenticator.getMechanismName());
        // send the command now

        try {
            IMAPTaggedResponse response = sendCommand(command);

            // now process the challenge sequence.  We get a 235 response back when the server accepts the
            // authentication, and a 334 indicates we have an additional challenge.
            while (true) {
                // this should be a continuation reply, if things are still good.
                if (response.isContinuation()) {
                    // we're passed back a challenge value, Base64 encoded.
                    byte[] challenge = response.decodeChallengeResponse();

                    // have the authenticator evaluate and send back the encoded response.
                    response = sendLine(Base64.encode(authenticator.evaluateChallenge(challenge)));
                }
                else {
                    // there are only two choices here, OK or a continuation.  OK means
                    // we've passed muster and are in.
                    return true;
                }
            }
        } catch (CommandFailedException e ) {
            // a failure at any point in this process will result in a "NO" response.
            // That causes an exception to get thrown, so just fail the login
            // if we get one.
            return false;
        }
    }


    /**
     * Return the server host for this connection.
     *
     * @return The String name of the server host.
     */
    public String getHost() {
        return serverHost;
    }


    /**
     * Attach a handler for untagged responses to this connection.
     *
     * @param h      The new untagged response handler.
     */
    public synchronized void addResponseHandler(IMAPUntaggedResponseHandler h) {
        responseHandlers.add(h);
    }


    /**
     * Remove a response handler from the connection.
     *
     * @param h      The handler to remove.
     */
    public synchronized void removeResponseHandler(IMAPUntaggedResponseHandler h) {
        responseHandlers.remove(h);
    }


    /**
     * Add a response to the pending untagged response queue.
     *
     * @param response The response to add.
     */
    public synchronized void queuePendingResponse(IMAPUntaggedResponse response) {
        queuedResponses.add(response);
    }

    /**
     * Process any untagged responses in the queue.  This will clear out
     * the queue, and send each response to the registered
     * untagged response handlers.
     */
    public void processPendingResponses() throws MessagingException {
        List pendingResponses = null;
        List handlerList = null;

        synchronized(this) {
            if (queuedResponses.isEmpty()) {
                return;
            }
            pendingResponses = queuedResponses;
            queuedResponses = new LinkedList();
            // get a copy of the response handlers so we can
            // release the connection lock before broadcasting
            handlerList = (List)responseHandlers.clone();
        }

        for (int i = 0; i < pendingResponses.size(); i++) {
            IMAPUntaggedResponse response = (IMAPUntaggedResponse)pendingResponses.get(i);
            for (int j = 0; j < handlerList.size(); j++) {
                // broadcast to each handler.  If a handler returns true, then it
                // handled whatever this message required and we should skip sending
                // it to other handlers.
                IMAPUntaggedResponseHandler h = (IMAPUntaggedResponseHandler)handlerList.get(j);
                if (h.handleResponse(response)) {
                    break;
                }
            }
        }
    }

    /**
     * Extract a single response from the pending queue that
     * match a give keyword type.  All matching responses
     * are removed from the pending queue.
     *
     * @param type   The string name of the keyword.
     *
     * @return A List of all matching queued responses.
     */
    public IMAPUntaggedResponse extractResponse(String type) {
        Iterator i = queuedResponses.iterator();
        while (i.hasNext()) {
            IMAPUntaggedResponse response = (IMAPUntaggedResponse)i.next();
            // if this is of the target type, move it to the response set.
            if (response.isKeyword(type)) {
                i.remove();
                return response;
            }
        }
        return null;
    }

    /**
     * Extract all responses from the pending queue that
     * match a give keyword type.  All matching responses
     * are removed from the pending queue.
     *
     * @param type   The string name of the keyword.
     *
     * @return A List of all matching queued responses.
     */
    public List extractResponses(String type) {
        List responses = new ArrayList();

        Iterator i = queuedResponses.iterator();
        while (i.hasNext()) {
            IMAPUntaggedResponse response = (IMAPUntaggedResponse)i.next();
            // if this is of the target type, move it to the response set.
            if (response.isKeyword(type)) {
                i.remove();
                responses.add(response);
            }
        }
        return responses;
    }


    /**
     * Extract all responses from the pending queue that
     * are "FETCH" responses for a given message number.  All matching responses
     * are removed from the pending queue.
     *
     * @param type   The string name of the keyword.
     *
     * @return A List of all matching queued responses.
     */
    public List extractFetchResponses(int sequenceNumber) {
        List responses = new ArrayList();

        Iterator i = queuedResponses.iterator();
        while (i.hasNext()) {
            IMAPUntaggedResponse response = (IMAPUntaggedResponse)i.next();
            // if this is of the target type, move it to the response set.
            if (response.isKeyword("FETCH")) {
                IMAPFetchResponse fetch = (IMAPFetchResponse)response;
                // a response for the correct message number?
                if (fetch.sequenceNumber == sequenceNumber) {
                    // pluck these from the list and add to the response set.
                    i.remove();
                    responses.add(response);
                }
            }
        }
        return responses;
    }

    /**
     * Extract a fetch response data item from the queued elements.
     *
     * @param sequenceNumber
     *               The message number we're interested in.  Fetch responses for other messages
     *               will be skipped.
     * @param type   The type of body element we need. It is assumed that only one item for
     *               the given message number will exist in the queue.  The located item will
     *               be returned, and that fetch response will be removed from the pending queue.
     *
     * @return The target data item, or null if a match is not found.
     */
    protected IMAPFetchDataItem extractFetchDataItem(long sequenceNumber, int type)
    {
        Iterator i = queuedResponses.iterator();
        while (i.hasNext()) {
            IMAPUntaggedResponse response = (IMAPUntaggedResponse)i.next();
            // if this is of the target type, move it to the response set.
            if (response.isKeyword("FETCH")) {
                IMAPFetchResponse fetch = (IMAPFetchResponse)response;
                // a response for the correct message number?
                if (fetch.sequenceNumber == sequenceNumber) {
                    // does this response have the item we're looking for?
                    IMAPFetchDataItem item = fetch.getDataItem(type);
                    if (item != null) {
                        // remove this from the pending queue and return the
                        // located item
                        i.remove();
                        return item;
                    }
                }
            }
        }
        // not located, sorry
        return null;
    }

    /**
     * Extract a all fetch responses that contain a given data item.
     *
     * @param type   The type of body element we need. It is assumed that only one item for
     *               the given message number will exist in the queue.  The located item will
     *               be returned, and that fetch response will be removed from the pending queue.
     *
     * @return A List of all matching Fetch responses.
     */
    protected List extractFetchDataItems(int type)
    {
        Iterator i = queuedResponses.iterator();
        List items = new ArrayList();

        while (i.hasNext()) {
            IMAPUntaggedResponse response = (IMAPUntaggedResponse)i.next();
            // if this is of the target type, move it to the response set.
            if (response.isKeyword("FETCH")) {
                IMAPFetchResponse fetch = (IMAPFetchResponse)response;
                // does this response have the item we're looking for?
                IMAPFetchDataItem item = fetch.getDataItem(type);
                if (item != null) {
                    // remove this from the pending queue and return the
                    // located item
                    i.remove();
                    // we want the fetch response, not the data item, because
                    // we're going to require the message sequence number information
                    // too.
                    items.add(fetch);
                }
            }
        }
        // return whatever we have.
        return items;
    }

    /**
     * Make sure we have the latest status information available.  We
     * retreive this by sending a NOOP command to the server, and
     * processing any untagged responses we get back.
     */
    public void updateMailboxStatus() throws MessagingException {
        sendSimpleCommand("NOOP");
    }


    /**
     * check to see if this connection is truely alive.
     *
     * @param timeout The timeout value to control how often we ping
     *                the server to see if we're still good.
     *
     * @return true if the server is responding to requests, false for any
     *         connection errors.  This will also update the folder status
     *         by processing returned unsolicited messages.
     */
    public synchronized boolean isAlive(long timeout) {
        long lastUsed = System.currentTimeMillis() - lastAccess;
        if (lastUsed < timeout) {
            return true;
        }

        try {
            sendSimpleCommand("NOOP");
            return true;
        } catch (MessagingException e) {
            // the NOOP command will throw a MessagingException if we get anything
            // other than an OK response back from the server.
        }
        return false;
    }


    /**
     * Issue a fetch command to retrieve the message ENVELOPE structure.
     *
     * @param sequenceNumber The sequence number of the message.
     *
     * @return The IMAPResponse item containing the ENVELOPE information.
     */
    public synchronized List fetchEnvelope(int sequenceNumber) throws MessagingException {
        IMAPCommand command = new IMAPCommand("FETCH");
        command.appendInteger(sequenceNumber);
        command.startList();
        command.appendAtom("ENVELOPE INTERNALDATE RFC822.SIZE");
        command.endList();

        // we want all of the envelope information about the message, which involves multiple FETCH chunks.
        sendCommand(command);
        // these are fairly involved sets, so the caller needs to handle these.
        // we just return all of the FETCH results matching the target message number.
        return extractFetchResponses(sequenceNumber);
    }

    /**
     * Issue a FETCH command to retrieve the message BODYSTRUCTURE structure.
     *
     * @param sequenceNumber The sequence number of the message.
     *
     * @return The IMAPBodyStructure item for the message.
     *         All other untagged responses are queued for processing.
     */
    public synchronized IMAPBodyStructure fetchBodyStructure(int sequenceNumber) throws MessagingException {
        IMAPCommand command = new IMAPCommand("FETCH");
        command.appendInteger(sequenceNumber);
        command.startList();
        command.appendAtom("BODYSTRUCTURE");
        command.endList();

        // we want all of the envelope information about the message, which involves multiple FETCH chunks.
        sendCommand(command);
        // locate the response from this
        IMAPBodyStructure bodyStructure = (IMAPBodyStructure)extractFetchDataItem(sequenceNumber, IMAPFetchDataItem.BODYSTRUCTURE);

        if (bodyStructure == null) {
            throw new MessagingException("No BODYSTRUCTURE information received from IMAP server");
        }
        // and return the body structure directly.
        return bodyStructure;
    }


    /**
     * Issue a FETCH command to retrieve the message RFC822.HEADERS structure containing the message headers (using PEEK).
     *
     * @param sequenceNumber The sequence number of the message.
     *
     * @return The IMAPRFC822Headers item for the message.
     *         All other untagged responses are queued for processing.
     */
    public synchronized InternetHeaders fetchHeaders(int sequenceNumber, String part) throws MessagingException {
        IMAPCommand command = new IMAPCommand("FETCH");
        command.appendInteger(sequenceNumber);
        command.startList();
        command.appendAtom("BODY.PEEK");
        command.appendBodySection(part, "HEADER");
        command.endList();

        // we want all of the envelope information about the message, which involves multiple FETCH chunks.
        sendCommand(command);
        IMAPInternetHeader header = (IMAPInternetHeader)extractFetchDataItem(sequenceNumber, IMAPFetchDataItem.HEADER);

        if (header == null) {
            throw new MessagingException("No HEADER information received from IMAP server");
        }
        // and return the body structure directly.
        return header.headers;
    }


    /**
     * Issue a FETCH command to retrieve the message text
     *
     * @param sequenceNumber The sequence number of the message.
     *
     * @return The IMAPMessageText item for the message.
     *         All other untagged responses are queued for processing.
     */
    public synchronized IMAPMessageText fetchText(int sequenceNumber) throws MessagingException {
        IMAPCommand command = new IMAPCommand("FETCH");
        command.appendInteger(sequenceNumber);
        command.startList();
        command.appendAtom("BODY.PEEK");
        command.appendBodySection("TEXT");
        command.endList();

        // we want all of the envelope information about the message, which involves multiple FETCH chunks.
        sendCommand(command);
        IMAPMessageText text = (IMAPMessageText)extractFetchDataItem(sequenceNumber, IMAPFetchDataItem.TEXT);

        if (text == null) {
            throw new MessagingException("No TEXT information received from IMAP server");
        }
        // and return the body structure directly.
        return text;
    }


    /**
     * Issue a FETCH command to retrieve the message text
     *
     * @param sequenceNumber The sequence number of the message.
     *
     * @return The IMAPMessageText item for the message.
     *         All other untagged responses are queued for processing.
     */
    public synchronized IMAPMessageText fetchBodyPartText(int sequenceNumber, String section) throws MessagingException {
        IMAPCommand command = new IMAPCommand("FETCH");
        command.appendInteger(sequenceNumber);
        command.startList();
        command.appendAtom("BODY.PEEK");
        command.appendBodySection(section, "TEXT");
        command.endList();

        // we want all of the envelope information about the message, which involves multiple FETCH chunks.
        sendCommand(command);
        IMAPMessageText text = (IMAPMessageText)extractFetchDataItem(sequenceNumber, IMAPFetchDataItem.TEXT);

        if (text == null) {
            throw new MessagingException("No TEXT information received from IMAP server");
        }
        // and return the body structure directly.
        return text;
    }


    /**
     * Issue a FETCH command to retrieve the entire message body in one shot.
     * This may also be used to fetch an embedded message part as a unit.
     *
     * @param sequenceNumber
     *                The sequence number of the message.
     * @param section The section number to fetch.  If null, the entire body of the message
     *                is retrieved.
     *
     * @return The IMAPBody item for the message.
     *         All other untagged responses are queued for processing.
     * @exception MessagingException
     */
    public synchronized IMAPBody fetchBody(int sequenceNumber, String section) throws MessagingException {
        IMAPCommand command = new IMAPCommand("FETCH");
        command.appendInteger(sequenceNumber);
        command.startList();
        command.appendAtom("BODY.PEEK");
        // no part name here, only the section identifier.  This will fetch
        // the entire body, with all of the bits in place.
        command.appendBodySection(section, null);
        command.endList();

        // we want all of the envelope information about the message, which involves multiple FETCH chunks.
        sendCommand(command);
        IMAPBody body = (IMAPBody)extractFetchDataItem(sequenceNumber, IMAPFetchDataItem.BODY);

        if (body == null) {
            throw new MessagingException("No BODY information received from IMAP server");
        }
        // and return the body structure directly.
        return body;
    }


    /**
     * Fetch the message content.  This sorts out which method should be used
     * based on the server capability.
     *
     * @param sequenceNumber
     *               The sequence number of the target message.
     *
     * @return The byte[] content information.
     * @exception MessagingException
     */
    public byte[] fetchContent(int sequenceNumber) throws MessagingException {
        // fetch the text item and return the data
        IMAPMessageText text = fetchText(sequenceNumber);
        return text.getContent();
    }


    /**
     * Fetch the message content.  This sorts out which method should be used
     * based on the server capability.
     *
     * @param sequenceNumber
     *               The sequence number of the target message.
     *
     * @return The byte[] content information.
     * @exception MessagingException
     */
    public byte[] fetchContent(int sequenceNumber, String section) throws MessagingException {
        if (section == null) {
            IMAPMessageText text = fetchText(sequenceNumber);
            return text.getContent();
        } else {
            IMAPBody body = fetchBody(sequenceNumber, section);
            return body.getContent();
        }
    }


    /**
     * Send an LIST command to the IMAP server, returning all LIST
     * response information.
     *
     * @param mailbox The reference mailbox name sent on the command.
     * @param pattern The match pattern used on the name.
     *
     * @return A List of all LIST response information sent back from the server.
     */
    public synchronized List list(String mailbox, String pattern) throws MessagingException {
        IMAPCommand command = new IMAPCommand("LIST");

        // construct the command, encoding the tokens as required by the content.
        command.appendEncodedString(mailbox);
        command.appendEncodedString(pattern);

        sendCommand(command);

        // pull out the ones we're interested in
        return extractResponses("LIST");
    }


    /**
     * Send an LSUB command to the IMAP server, returning all LSUB
     * response information.
     *
     * @param mailbox The reference mailbox name sent on the command.
     * @param pattern The match pattern used on the name.
     *
     * @return A List of all LSUB response information sent back from the server.
     */
    public List listSubscribed(String mailbox, String pattern) throws MessagingException {
        IMAPCommand command = new IMAPCommand("LSUB");

        // construct the command, encoding the tokens as required by the content.
        command.appendEncodedString(mailbox);
        command.appendEncodedString(pattern);

        sendCommand(command);
        // pull out the ones we're interested in
        return extractResponses("LSUB");
    }


    /**
     * Subscribe to a give mailbox.
     *
     * @param mailbox The desired mailbox name.
     *
     * @exception MessagingException
     */
    public void subscribe(String mailbox) throws MessagingException {
        IMAPCommand command = new IMAPCommand("SUBSCRIBE");
        // add on the encoded mailbox name, as the appropriate token type.
        command.appendEncodedString(mailbox);

        // send this, and ignore the response.
        sendSimpleCommand(command);
    }


    /**
     * Unsubscribe from a mailbox.
     *
     * @param mailbox The mailbox to remove.
     *
     * @exception MessagingException
     */
    public void unsubscribe(String mailbox) throws MessagingException {
        IMAPCommand command = new IMAPCommand("UNSUBSCRIBE");
        // add on the encoded mailbox name, as the appropriate token type.
        command.appendEncodedString(mailbox);

        // send this, and ignore the response.
        sendSimpleCommand(command);
    }


    /**
     * Create a mailbox.
     *
     * @param mailbox The desired new mailbox name (fully qualified);
     *
     * @exception MessagingException
     */
    public void createMailbox(String mailbox) throws MessagingException {
        IMAPCommand command = new IMAPCommand("CREATE");
        // add on the encoded mailbox name, as the appropriate token type.
        command.appendEncodedString(mailbox);

        // send this, and ignore the response.
        sendSimpleCommand(command);
    }


    /**
     * Delete a mailbox.
     *
     * @param mailbox The target mailbox name (fully qualified);
     *
     * @exception MessagingException
     */
    public void deleteMailbox(String mailbox) throws MessagingException {
        IMAPCommand command = new IMAPCommand("DELETE");
        // add on the encoded mailbox name, as the appropriate token type.
        command.appendEncodedString(mailbox);

        // send this, and ignore the response.
        sendSimpleCommand(command);
    }


    /**
     * Rename a mailbox.
     *
     * @param mailbox The target mailbox name (fully qualified);
     *
     * @exception MessagingException
     */
    public void renameMailbox(String oldName, String newName) throws MessagingException {
        IMAPCommand command = new IMAPCommand("RENAME");
        // add on the encoded mailbox name, as the appropriate token type.
        command.appendEncodedString(oldName);
        command.appendEncodedString(newName);

        // send this, and ignore the response.
        sendSimpleCommand(command);
    }


    /**
     * Retrieve a complete set of status items for a mailbox.
     *
     * @param mailbox The mailbox name.
     *
     * @return An IMAPMailboxStatus item filled in with the STATUS responses.
     * @exception MessagingException
     */
    public synchronized IMAPMailboxStatus getMailboxStatus(String mailbox) throws MessagingException {
        IMAPCommand command = new IMAPCommand("STATUS");

        // construct the command, encoding the tokens as required by the content.
        command.appendEncodedString(mailbox);
        // request all of the status items
        command.append(" (MESSAGES RECENT UIDNEXT UIDVALIDITY UNSEEN)");

        sendCommand(command);

        // now harvest each of the respon
        IMAPMailboxStatus status = new IMAPMailboxStatus();
        status.mergeSizeResponses(extractResponses("EXISTS"));
        status.mergeSizeResponses(extractResponses("RECENT"));
        status.mergeOkResponses(extractResponses("UIDNEXT"));
        status.mergeOkResponses(extractResponses("UIDVALIDITY"));
        status.mergeOkResponses(extractResponses("UNSEEN"));
        status.mergeStatus((IMAPStatusResponse)extractResponse("STATUS"));
        status.mergeStatus((IMAPPermanentFlagsResponse)extractResponse("PERMANENTFLAGS"));

        return status;
    }


    /**
     * Select a mailbox, returning the accumulated status information
     * about the mailbox returned with the response.
     *
     * @param mailbox  The desired mailbox name.
     * @param readOnly The open mode.  If readOnly is true, the mailbox is opened
     *                 using EXAMINE rather than SELECT.
     *
     * @return A status object containing the mailbox particulars.
     * @exception MessagingException
     */
    public synchronized IMAPMailboxStatus openMailbox(String mailbox, boolean readOnly) throws MessagingException {
        IMAPCommand command = new IMAPCommand();

        // if readOnly is required, we use EXAMINE to switch to the mailbox rather than SELECT.
        // This returns the same response information, but the mailbox will not accept update operations.
        if (readOnly) {
            command.appendAtom("EXAMINE");
        }
        else {
            command.appendAtom("SELECT");
        }

        // construct the command, encoding the tokens as required by the content.
        command.appendEncodedString(mailbox);

        // issue the select
        IMAPTaggedResponse response = sendCommand(command);

        IMAPMailboxStatus status = new IMAPMailboxStatus();
        // set the mode to the requested open mode.
        status.mode = readOnly ? Folder.READ_ONLY : Folder.READ_WRITE;

        // the server might disagree on the mode, so check to see if
        // it's telling us READ-ONLY.
        if (response.hasStatus("READ-ONLY")) {
            status.mode = Folder.READ_ONLY;
        }

        // some of these are required, some are optional.
        status.mergeFlags((IMAPFlagsResponse)extractResponse("FLAGS"));
        status.mergeStatus((IMAPSizeResponse)extractResponse("EXISTS"));
        status.mergeStatus((IMAPSizeResponse)extractResponse("RECENT"));
        status.mergeStatus((IMAPOkResponse)extractResponse("UIDVALIDITY"));
        status.mergeStatus((IMAPOkResponse)extractResponse("UNSEEN"));
        status.mergeStatus((IMAPPermanentFlagsResponse)extractResponse("PERMANENTFLAGS"));
        // mine the response for status information about the selected mailbox.
        return status;
    }


    /**
     * Tells the IMAP server to expunge messages marked for deletion.
     * The server will send us an untagged EXPUNGE message back for
     * each deleted message.  For explicit expunges we request, we'll
     * grabbed the untagged responses here, rather than force them to
     * be handled as pending responses.  The caller will handle the
     * updates directly.
     *
     * @exception MessagingException
     */
    public synchronized List expungeMailbox() throws MessagingException {
        // send the message, and make sure we got an OK response
        sendCommand("EXPUNGE");
        // extract all of the expunged responses and return.
        return extractResponses("EXPUNGED");
    }

    public int[] searchMailbox(SearchTerm term) throws MessagingException {
        return searchMailbox("ALL", term);
    }

    /**
     * Send a search to the IMAP server using the specified
     * messages selector and search term.  This figures out what
     * to do with CHARSET on the SEARCH command.
     *
     * @param messages The list of messages (comma-separated numbers or "ALL").
     * @param term     The desired search criteria
     *
     * @return Returns an int[] array of message numbers for all matched messages.
     * @exception MessagingException
     */
    public int[] searchMailbox(String messages, SearchTerm term) throws MessagingException {
        // don't use a charset by default, but we need to look at the data to see if we have a problem.
        String charset = null;

        if (IMAPCommand.checkSearchEncoding(term)) {
            // not sure exactly how to decide what to use here.  Two immediate possibilities come to mind,
            // UTF-8 or the MimeUtility.getDefaultJavaCharset() value.  Running a small test against the
            // Sun impl shows them sending a CHARSET value of UTF-8, so that sounds like the winner.  I don't
            // believe there's anything in the CAPABILITY response that would tell us what to use.
            charset = "UTF-8";
        }

        return searchMailbox(messages, term, charset);
    }

    /**
     * Send a search to the IMAP server using the specified
     * messages selector and search term.
     *
     * @param messages The list of messages (comma-separated numbers or "ALL").
     * @param charset  The charset specifier to send to the server.  If null, then
     *                 the CHARSET keyword is omitted.
     * @param term     The desired search criteria
     *
     * @return Returns an int[] array of message numbers for all matched messages.
     * @exception MessagingException
     */
    public synchronized int[] searchMailbox(String messages, SearchTerm term, String charset) throws MessagingException {
        IMAPCommand command = new IMAPCommand("SEARCH");

        // if we have an explicit charset to use, append that.
        if (charset != null) {
            command.appendAtom("CHARSET");
            command.appendAtom(charset);
        }

        // now go through the process of translating the javamail SearchTerm objects into
        // the IMAP command sequence.  The SearchTerm sequence may be a complex tree of comparison terms,
        // so this is not a simple process.
        command.appendSearchTerm(term, charset);
        // need to append the message set
        command.appendAtom(messages);

        // now issue the composed command.
        sendCommand(command);

        // get the list of search responses
        IMAPSearchResponse hits = (IMAPSearchResponse)extractResponse("SEARCH");
        // and return the message hits
        return hits.messageNumbers;
    }


    /**
     * Append a message to a mailbox, given the direct message data.
     *
     * @param mailbox The target mailbox name.
     * @param messageFlags
     *                The initial flag set for the appended message.
     * @param messageDate
     *                The received date the message is created with,
     * @param messageData
     *                The RFC822 Message data stored on the server.
     *
     * @exception MessagingException
     */
    public void appendMessage(String mailbox, Date messageDate, Flags messageFlags, byte[] messageData) throws MessagingException {
        IMAPCommand command = new IMAPCommand("APPEND");

        // the mailbox is encoded.
        command.appendEncodedString(mailbox);

        if (messageFlags != null) {
            // the flags are pulled from an existing object.  We can set most flag values, but the servers
            // reserve RECENT for themselves.  We need to force that one off.
            messageFlags.remove(Flags.Flag.RECENT);
            // and add the flag list to the commmand.
            command.appendFlags(messageFlags);
        }

        if (messageDate != null) {
            command.appendDate(messageDate);
        }

        // this gets appended as a literal.
        command.appendLiteral(messageData);
        // just send this as a simple command...we don't deal with the response other than to verifiy
        // it was ok.
        sendSimpleCommand(command);
    }

    /**
     * Fetch the flag set for a given message sequence number.
     *
     * @param sequenceNumber
     *               The message sequence number.
     *
     * @return The Flags defined for this message.
     * @exception MessagingException
     */
    public synchronized Flags fetchFlags(int sequenceNumber) throws MessagingException {
        // we want just the flag item here.
        sendCommand("FETCH " + String.valueOf(sequenceNumber) + " (FLAGS)");
        // get the return data item, and get the flags from within it
        IMAPFlags flags = (IMAPFlags)extractFetchDataItem(sequenceNumber, IMAPFetchDataItem.FLAGS);
        return flags.flags;
    }


    /**
     * Set the flags for a range of messages.
     *
     * @param messageSet The set of message numbers.
     * @param flags      The new flag settings.
     * @param set        true if the flags should be set, false for a clear operation.
     *
     * @return A list containing all of the responses with the new flag values.
     * @exception MessagingException
     */
    public synchronized List setFlags(String messageSet, Flags flags, boolean set) throws MessagingException {
        IMAPCommand command = new IMAPCommand("STORE");
        command.appendAtom(messageSet);
        // the command varies depending on whether this is a set or clear operation
        if (set) {
            command.appendAtom("+FLAGS");
        }
        else {
            command.appendAtom("-FLAGS");
        }

        // append the flag set
        command.appendFlags(flags);

        // we want just the flag item here.
        sendCommand(command);
        // we should have a FETCH response for each of the updated messages.  Return this
        // response, and update the message numbers.
        return extractFetchDataItems(IMAPFetchDataItem.FLAGS);
    }


    /**
     * Set the flags for a single message.
     *
     * @param sequenceNumber
     *               The sequence number of target message.
     * @param flags  The new flag settings.
     * @param set    true if the flags should be set, false for a clear operation.
     *
     * @exception MessagingException
     */
    public synchronized Flags setFlags(int sequenceNumber, Flags flags, boolean set) throws MessagingException {
        IMAPCommand command = new IMAPCommand("STORE");
        command.appendInteger(sequenceNumber);
        // the command varies depending on whether this is a set or clear operation
        if (set) {
            command.appendAtom("+FLAGS");
        }
        else {
            command.appendAtom("-FLAGS");
        }

        // append the flag set
        command.appendFlags(flags);

        // we want just the flag item here.
        sendCommand(command);
        // get the return data item, and get the flags from within it
        IMAPFlags flagResponse = (IMAPFlags)extractFetchDataItem(sequenceNumber, IMAPFetchDataItem.FLAGS);
        return flagResponse.flags;
    }


    /**
     * Copy a range of messages to a target mailbox.
     *
     * @param messageSet The set of message numbers.
     * @param target     The target mailbox name.
     *
     * @exception MessagingException
     */
    public void copyMessages(String messageSet, String target) throws MessagingException {
        IMAPCommand command = new IMAPCommand("COPY");
        // the auth command initiates the handshaking.
        command.appendAtom(messageSet);
        // the mailbox is encoded.
        command.appendEncodedString(target);
        // just send this as a simple command...we don't deal with the response other than to verifiy
        // it was ok.
        sendSimpleCommand(command);
    }


    /**
     * Fetch the message number for a give UID.
     *
     * @param uid    The target UID
     *
     * @return An IMAPUid object containing the mapping information.
     */
    public synchronized IMAPUid getSequenceNumberForUid(long uid) throws MessagingException {
        IMAPCommand command = new IMAPCommand("UID FETCH");
        command.appendLong(uid);
        command.appendAtom("(UID)");

        // this situation is a little strange, so it deserves a little explanation.
        // We need the message sequence number for this message from a UID value.
        // we're going to send a UID FETCH command, requesting the UID value back.
        // That seems strange, but the * nnnn FETCH response for the request will
        // be tagged with the message sequence number.  THAT'S the information we
        // really want, and it will be included in the IMAPUid object.

        sendCommand(command);
        // ok, now we need to search through these looking for a FETCH response with a UID element.
        List responses = extractResponses("FETCH");

        // we're looking for a fetch response with a UID data item with the UID information
        // inside of it.
        for (int i = 0; i < responses.size(); i++) {
            IMAPFetchResponse response = (IMAPFetchResponse)responses.get(i);
            IMAPUid item = (IMAPUid)response.getDataItem(IMAPFetchDataItem.UID);
            // is this the response we're looking for?  The information we
            // need is the message number returned with the response, which is
            // also contained in the UID item.
            if (item != null && item.uid == uid) {
                return item;
            }
            // not one meant for us, add it back to the pending queue.
            queuePendingResponse(response);
        }
        // didn't find this one
        return null;
    }


    /**
     * Fetch the message numbers for a consequetive range
     * of UIDs.
     *
     * @param start  The start of the range.
     * @param end    The end of the uid range.
     *
     * @return A list of UID objects containing the mappings.
     */
    public synchronized List getSequenceNumbersForUids(long start, long end) throws MessagingException {
        IMAPCommand command = new IMAPCommand("UID FETCH");
        // send the request for the range "start:end" so we can fetch all of the info
        // at once.
        command.appendLong(start);
        command.append(":");
        // not the special range marker?  Just append the
        // number.  The LASTUID value needs to be "*" on the command.
        if (end != UIDFolder.LASTUID) {
            command.appendLong(end);
        }
        else {
            command.append("*");
        }
        command.appendAtom("(UID)");

        // this situation is a little strange, so it deserves a little explanation.
        // We need the message sequence number for this message from a UID value.
        // we're going to send a UID FETCH command, requesting the UID value back.
        // That seems strange, but the * nnnn FETCH response for the request will
        // be tagged with the message sequence number.  THAT'S the information we
        // really want, and it will be included in the IMAPUid object.

        sendCommand(command);
        // ok, now we need to search through these looking for a FETCH response with a UID element.
        List responses = extractResponses("FETCH");

        List uids = new ArrayList((int)(end - start + 1));

        // we're looking for a fetch response with a UID data item with the UID information
        // inside of it.
        for (int i = 0; i < responses.size(); i++) {
            IMAPFetchResponse response = (IMAPFetchResponse)responses.get(i);
            IMAPUid item = (IMAPUid)response.getDataItem(IMAPFetchDataItem.UID);
            // is this the response we're looking for?  The information we
            // need is the message number returned with the response, which is
            // also contained in the UID item.
            if (item != null) {
                uids.add(item);
            }
            else {
                // not one meant for us, add it back to the pending queue.
                queuePendingResponse(response);
            }
        }
        // return the list of uids we located.
        return uids;
    }


    /**
     * Fetch the UID value for a target message number
     *
     * @param sequenceNumber
     *               The target message number.
     *
     * @return An IMAPUid object containing the mapping information.
     */
    public synchronized IMAPUid getUidForSequenceNumber(int sequenceNumber) throws MessagingException {
        IMAPCommand command = new IMAPCommand("FETCH");
        command.appendInteger(sequenceNumber);
        command.appendAtom("(UID)");

        // similar to the other fetches, but without the strange bit.  We're starting
        // with the message number in this case.

        sendCommand(command);

        // ok, now we need to search through these looking for a FETCH response with a UID element.
        return (IMAPUid)extractFetchDataItem(sequenceNumber, IMAPFetchDataItem.UID);
    }


    /**
     * Retrieve the user name space info from the server.
     *
     * @return An IMAPNamespace response item with the information.  If the server
     *         doesn't support the namespace extension, an empty one is returned.
     */
    public synchronized IMAPNamespaceResponse getNamespaces() throws MessagingException {
        // if no namespace capability, then return an empty
        // response, which will trigger the default behavior.
        if (!hasCapability("NAMESPACE")) {
            return new IMAPNamespaceResponse();
        }
        // no arguments on this command, so just send an hope it works.
        sendCommand("NAMESPACE");

        // this should be here, since it's a required response when the
        // command worked.  Just extract, and return.
        return (IMAPNamespaceResponse)extractResponse("NAMESPACE");
    }


    /**
     * Prefetch message information based on the request profile.  We'll return
     * all of the fetch information to the requesting Folder, which will sort
     * out what goes where.
     *
     * @param messageSet The set of message numbers we need to fetch.
     * @param profile    The profile of the required information.
     *
     * @return All FETCH responses resulting from the command.
     * @exception MessagingException
     */
    public synchronized List fetch(String messageSet, FetchProfile profile) throws MessagingException {
        IMAPCommand command = new IMAPCommand("FETCH");
        command.appendAtom(messageSet);
        // this is the set of items to append
        command.appendFetchProfile(profile);

        // now send the fetch command, which will likely send back a lot of "FETCH" responses.
        // Suck all of those reponses out of the queue and send them back for processing.
        sendCommand(command);
        // we can have a large number of messages here, so just grab all of the fetches
        // we get back, and let the Folder sort out who gets what.
        return extractResponses("FETCH");
    }


    /**
     * Set the ACL rights for a mailbox.  This replaces
     * any existing ACLs defined.
     *
     * @param mailbox The target mailbox.
     * @param acl     The new ACL to be used for the mailbox.
     *
     * @exception MessagingException
     */
    public synchronized void setACLRights(String mailbox, ACL acl) throws MessagingException {
        IMAPCommand command = new IMAPCommand("SETACL");
        command.appendEncodedString(mailbox);

        command.appendACL(acl);

        sendSimpleCommand(command);
    }


    /**
     * Add a set of ACL rights to a mailbox.
     *
     * @param mailbox The mailbox to alter.
     * @param acl     The ACL to add.
     *
     * @exception MessagingException
     */
    public synchronized void addACLRights(String mailbox, ACL acl) throws MessagingException {
        if (!hasCapability("ACL")) {
            throw new MethodNotSupportedException("ACL not available from this IMAP server");
        }
        IMAPCommand command = new IMAPCommand("SETACL");
        command.appendEncodedString(mailbox);

        command.appendACL(acl, "+");

        sendSimpleCommand(command);
    }


    /**
     * Remove an ACL from a given mailbox.
     *
     * @param mailbox The mailbox to alter.
     * @param acl     The particular ACL to revoke.
     *
     * @exception MessagingException
     */
    public synchronized void removeACLRights(String mailbox, ACL acl) throws MessagingException {
        if (!hasCapability("ACL")) {
            throw new MethodNotSupportedException("ACL not available from this IMAP server");
        }
        IMAPCommand command = new IMAPCommand("SETACL");
        command.appendEncodedString(mailbox);

        command.appendACL(acl, "-");

        sendSimpleCommand(command);
    }


    /**
     * Get the ACL rights assigned to a given mailbox.
     *
     * @param mailbox The target mailbox.
     *
     * @return The an array of ACL items describing the access
     *         rights to the mailbox.
     * @exception MessagingException
     */
    public synchronized ACL[] getACLRights(String mailbox) throws MessagingException {
        if (!hasCapability("ACL")) {
            throw new MethodNotSupportedException("ACL not available from this IMAP server");
        }
        IMAPCommand command = new IMAPCommand("GETACL");
        command.appendEncodedString(mailbox);

        // now send the GETACL command, which will return a single ACL untagged response.
        sendCommand(command);
        // there should be just a single ACL response back from this command.
        IMAPACLResponse response = (IMAPACLResponse)extractResponse("ACL");
        return response.acls;
    }


    /**
     * Get the current user's ACL rights to a given mailbox.
     *
     * @param mailbox The target mailbox.
     *
     * @return The Rights associated with this mailbox.
     * @exception MessagingException
     */
    public synchronized Rights getMyRights(String mailbox) throws MessagingException {
        if (!hasCapability("ACL")) {
            throw new MethodNotSupportedException("ACL not available from this IMAP server");
        }
        IMAPCommand command = new IMAPCommand("MYRIGHTS");
        command.appendEncodedString(mailbox);

        // now send the MYRIGHTS command, which will return a single MYRIGHTS untagged response.
        sendCommand(command);
        // there should be just a single MYRIGHTS response back from this command.
        IMAPMyRightsResponse response = (IMAPMyRightsResponse)extractResponse("MYRIGHTS");
        return response.rights;
    }


    /**
     * List the ACL rights that a particular user has
     * to a mailbox.
     *
     * @param mailbox The target mailbox.
     * @param name    The user we're querying.
     *
     * @return An array of rights the use has to this mailbox.
     * @exception MessagingException
     */
    public synchronized Rights[] listACLRights(String mailbox, String name) throws MessagingException {
        if (!hasCapability("ACL")) {
            throw new MethodNotSupportedException("ACL not available from this IMAP server");
        }
        IMAPCommand command = new IMAPCommand("LISTRIGHTS");
        command.appendEncodedString(mailbox);
        command.appendString(name);

        // now send the GETACL command, which will return a single ACL untagged response.
        sendCommand(command);
        // there should be just a single ACL response back from this command.
        IMAPListRightsResponse response = (IMAPListRightsResponse)extractResponse("LISTRIGHTS");
        return response.rights;
    }


    /**
     * Delete an ACL item for a given user name from
     * a target mailbox.
     *
     * @param mailbox The mailbox we're altering.
     * @param name    The user name.
     *
     * @exception MessagingException
     */
    public synchronized void deleteACL(String mailbox, String name) throws MessagingException {
        if (!hasCapability("ACL")) {
            throw new MethodNotSupportedException("ACL not available from this IMAP server");
        }
        IMAPCommand command = new IMAPCommand("DELETEACL");
        command.appendEncodedString(mailbox);
        command.appendString(name);

        // just send the command.  No response to handle.
        sendSimpleCommand(command);
    }

    /**
     * Fetch the quota root information for a target mailbox.
     *
     * @param mailbox The mailbox of interest.
     *
     * @return An array of quotas describing all of the quota roots
     *         that apply to the target mailbox.
     * @exception MessagingException
     */
    public synchronized Quota[] fetchQuotaRoot(String mailbox) throws MessagingException {
        if (!hasCapability("QUOTA")) {
            throw new MethodNotSupportedException("QUOTA not available from this IMAP server");
        }
        IMAPCommand command = new IMAPCommand("GETQUOTAROOT");
        command.appendEncodedString(mailbox);

        // This will return a single QUOTAROOT response, plust a series of QUOTA responses for
        // each root names in the first response.
        sendCommand(command);
        // we don't really need this, but pull it from the response queue anyway.
        extractResponse("QUOTAROOT");

        // now get the real meat of the matter
        List responses = extractResponses("QUOTA");

        // now copy all of the returned quota items into the response array.
        Quota[] quotas = new Quota[responses.size()];
        for (int i = 0; i < quotas.length; i++) {
            IMAPQuotaResponse q = (IMAPQuotaResponse)responses.get(i);
            quotas[i] = q.quota;
        }

        return quotas;
    }

    /**
     * Fetch QUOTA information from a named QUOTE root.
     *
     * @param root   The target root name.
     *
     * @return An array of Quota items associated with that root name.
     * @exception MessagingException
     */
    public synchronized Quota[] fetchQuota(String root) throws MessagingException {
        if (!hasCapability("QUOTA")) {
            throw new MethodNotSupportedException("QUOTA not available from this IMAP server");
        }
        IMAPCommand command = new IMAPCommand("GETQUOTA");
        command.appendString(root);

        // This will return a single QUOTAROOT response, plust a series of QUOTA responses for
        // each root names in the first response.
        sendCommand(command);

        // now get the real meat of the matter
        List responses = extractResponses("QUOTA");

        // now copy all of the returned quota items into the response array.
        Quota[] quotas = new Quota[responses.size()];
        for (int i = 0; i < quotas.length; i++) {
            IMAPQuotaResponse q = (IMAPQuotaResponse)responses.get(i);
            quotas[i] = q.quota;
        }

        return quotas;
    }

    /**
     * Set a Quota item for the currently accessed
     * userid/folder resource.
     *
     * @param quota  The new QUOTA information.
     *
     * @exception MessagingException
     */
    public synchronized void setQuota(Quota quota) throws MessagingException {
        if (!hasCapability("QUOTA")) {
            throw new MethodNotSupportedException("QUOTA not available from this IMAP server");
        }
        IMAPCommand command = new IMAPCommand("GETQUOTA");
        // this gets appended as a list of resource values
        command.appendQuota(quota);

        // This will return a single QUOTAROOT response, plust a series of QUOTA responses for
        // each root names in the first response.
        sendCommand(command);
        // we don't really need this, but pull it from the response queue anyway.
        extractResponses("QUOTA");
    }


    /**
     * Test if this connection has a given capability.
     *
     * @param capability The capability name.
     *
     * @return true if this capability is in the list, false for a mismatch.
     */
    public boolean hasCapability(String capability) {
        if (capabilities == null) {
            return false;
        }
        return capabilities.containsKey(capability);
    }

    /**
     * Tag this connection as having been closed by the
     * server.  This will not be returned to the
     * connection pool.
     */
    public void setClosed() {
        closed = true;
    }

    /**
     * Test if the connnection has been forcibly closed.
     *
     * @return True if the server disconnected the connection.
     */
    public boolean isClosed() {
        return closed;
    }
}

