/**
 * 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 store    The store we're associated with (source of parameter values).
     * @param host     The target host name of the IMAP server.
     * @param port     The target listening port of the server.  Defaults to 119 if
     *                 the port is specified as -1.
     * @param username The login user name (can be null unless authentication is
     *                 required).
     * @param password Password associated with the userid account.  Can be null if
     *                 authentication is not required.
     * @param sslConnection
     *                 True if this is targetted as an SSLConnection.
     * @param debug    The session debug flag.
     */
    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(); 

            // if we're not already using an SSL connection, and we have permission to issue STARTTLS, AND
            // the server supports this, then switch to TLS mode before continuing.
            if (!sslConnection && props.getBooleanProperty(MAIL_STARTTLS_ENABLE, false) && hasCapability(CAPABILITY_STARTTLS)) {
                // if the server supports TLS, then use it for the connection.
                // on our connection.
                
                // 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; 
                }
            }
            
            // 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 {
        return sendLine(data.getBytes()); 
    }
    

    /**
     * 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(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 {
        // fetch the text item and return the data 
        IMAPMessageText text = fetchBodyPartText(sequenceNumber, section);
        return text.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; 
    }
}

