/**
 * 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;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
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.Map;
import java.util.NoSuchElementException;
import java.util.Vector;

import javax.mail.*;
import javax.mail.event.ConnectionEvent;
import javax.mail.event.FolderEvent;
import javax.mail.event.MessageChangedEvent;
import javax.mail.search.FlagTerm;
import javax.mail.search.SearchTerm;

import org.apache.geronimo.javamail.store.imap.connection.IMAPConnection;
import org.apache.geronimo.javamail.store.imap.connection.IMAPFetchDataItem;
import org.apache.geronimo.javamail.store.imap.connection.IMAPFetchResponse;
import org.apache.geronimo.javamail.store.imap.connection.IMAPFlags;
import org.apache.geronimo.javamail.store.imap.connection.IMAPListResponse;
import org.apache.geronimo.javamail.store.imap.connection.IMAPMailboxStatus;
import org.apache.geronimo.javamail.store.imap.connection.IMAPSizeResponse;
import org.apache.geronimo.javamail.store.imap.connection.IMAPUid;
import org.apache.geronimo.javamail.store.imap.connection.IMAPUntaggedResponse;
import org.apache.geronimo.javamail.store.imap.connection.IMAPUntaggedResponseHandler;

/**
 * The base IMAP implementation of the javax.mail.Folder
 * This is a base class for both the Root IMAP server and each IMAP group folder.
 * @see javax.mail.Folder
 *
 * @version $Rev$
 */
public class IMAPFolder extends Folder implements UIDFolder, IMAPUntaggedResponseHandler {

    /**
     * Special profile item used for fetching SIZE and HEADER information.
     * These items are extensions that Sun has added to their IMAPFolder immplementation. 
     * We're supporting the same set. 
     */
    public static class FetchProfileItem extends FetchProfile.Item {
        public static final FetchProfileItem HEADERS = new FetchProfileItem("HEADERS");
        public static final FetchProfileItem SIZE = new FetchProfileItem("SIZE");

        protected FetchProfileItem(String name) {
            super(name);
        }
    }
    
    // marker that we don't know the separator yet for this folder. 
    // This occurs when we obtain a folder reference from the 
    // default folder.  At that point, we've not queried the 
    // server for specifics yet. 
    static final protected char UNDETERMINED = 0; 
    
    // our attached session
    protected Session session;
    // retrieved messages, mapped by sequence number.
    protected LinkedList messages;
    // mappings of UIDs to retrieved messages.
    protected Map uidCache;

    // the separator the server indicates is used as the hierarchy separator
    protected char separator;
    // the "full" name of the folder.  This is the fully qualified path name for the folder returned by
    // the IMAP server.  Elements of the hierarchy are delimited by "separator" characters.
    protected String fullname;
    // the name of this folder.  The is the last element of the fully qualified name.
    protected String name;
    // the folder open state
	protected boolean folderOpen = false;
    // the type information on what the folder can hold
    protected int folderType;
    // the subscription status
    protected boolean subscribed = false;

    // the message identifier ticker, used to assign message numbers. 
    protected int nextMessageID = 1; 
    // the current count of messages in our cache. 
    protected int maxSequenceNumber = 0;  
    // the reported count of new messages (updated as a result of untagged message resposes)
    protected int recentMessages = -1;
    // the reported count of unseen messages
    protected int unseenMessages = 0;
    // the uidValidity value reported back from the server
    protected long uidValidity = 0;
    // the uidNext value reported back from the server
    protected long uidNext = 0;
    // the persistent flags we save in the store
    protected Flags permanentFlags;
    // the settable flags the server reports back to us
    protected Flags availableFlags;
    // Our cached status information.  We will only hold this for the timeout interval.
    protected IMAPMailboxStatus cachedStatus;
    // Folder information retrieved from the server.  Good info here indicates the 
    // folder exists. 
    protected IMAPListResponse listInfo; 
    // the configured status cache timeout value.
    protected long statusCacheTimeout;
    // the last time we took a status snap shot.
    protected long lastStatusTimeStamp;
    // Our current connection.  We get one of these when opened, and release it when closed. 
    // We do this because for any folder (and message) operations, the folder must be selected on 
    // the connection.  
    // Note, however, that there are operations which will require us to borrow a connection 
    // temporarily because we need to touch the server when the folder is not open.  In those 
    // cases, we grab a connection, then immediately return it to the pool. 
    protected IMAPConnection currentConnection; 
    
    

    /**
     * Super class constructor the base IMAPFolder class.
     * 
     * @param store     The javamail store this folder is attached to.
     * @param fullname  The fully qualified name of this folder.
     * @param separator The separtor character used to delimit the different
     *                  levels of the folder hierarchy.  This is used to
     *                  decompose the full name into smaller parts and
     *                  create the names of subfolders.
     */
	protected IMAPFolder(IMAPStore store, String fullname, char separator) {
		super(store);
		this.session = store.getSession();
        this.fullname = fullname;
        this.separator = separator;
        // get the status timeout value from the folder. 
        statusCacheTimeout = store.statusCacheTimeout; 
	}

    /**
     * Retrieve the folder name.  This is the simple folder
     * name at the its hiearchy level.  This can be invoked when the folder is closed.
     * 
     * @return The folder's name.
     */
	public String getName() {
        // At the time we create the folder, we might not know the separator character yet. 
        // Because of this we need to delay creating the name element until 
        // it's required.  
        if (name == null) {
            // extract the name from the full name
            int lastLevel = -1; 
            try {
                lastLevel = fullname.lastIndexOf(getSeparator());
            } catch (MessagingException e) {
                // not likely to occur, but the link could go down before we 
                // get this.  Just assume a failure to locate the character 
                // occurred. 
            }
            if (lastLevel == -1) {
                name = fullname;
            }
            else {
                name = fullname.substring(lastLevel + 1);
            }
        }
        return name;
	}

    /**
     * Retrieve the folder's full name (including hierarchy information).
     * This can be invoked when the folder is closed.
     *
     * @return The full name value.
     */
	public String getFullName() {
        return fullname;
	}



    /**
     * Return the parent for this folder; if the folder is at the root of a heirarchy
     * this returns null.
     * This can be invoked when the folder is closed.
     *
     * @return this folder's parent
     * @throws MessagingException
     */
	public Folder getParent() throws MessagingException {
        // NB:  We need to use the method form because the separator 
        // might not have been retrieved from the server yet. 
        char separator = getSeparator(); 
        // we don't hold a reference to the parent folder, as that would pin the instance in memory 
        // as long as any any leaf item in the hierarchy is still open.  
        int lastLevel = fullname.lastIndexOf(separator);
        // no parent folder?  Get the root one from the Store.
        if (lastLevel == -1) {
            return ((IMAPStore)store).getDefaultFolder();
        }
        else {
            // create a folder for the parent.
            return new IMAPFolder((IMAPStore)store, fullname.substring(0, lastLevel), separator);
        }
	}


    /**
     * Check to see if this folder physically exists in the store.
     * This can be invoked when the folder is closed.
     *
     * @return true if the folder really exists
     * @throws MessagingException if there was a problem accessing the store
     */
    public synchronized boolean exists() throws MessagingException {
        IMAPConnection connection = getConnection(); 
        try {
            return checkExistance(connection); 
        } finally {
            releaseConnection(connection); 
        }
    }
    
    /**
     * Internal routine for checking existance using an 
     * already obtained connection.  Used for situations
     * where the list information needs updating but 
     * we'd end up acquiring a new connection because 
     * the folder isn't open yet. 
     * 
     * @param connection The connection to use.
     * 
     * @return true if the folder exists, false for non-existence.
     * @exception MessagingException
     */
    private boolean checkExistance(IMAPConnection connection) throws MessagingException {
        // get the list response for this folder.
        List responses = connection.list("", fullname);
        // NB, this grabs the latest information and updates 
        // the type information also.  Note also that we need to  
        // use the mailbox name, not the full name.  This is so 
        // the namespace folders will return the correct response. 
        listInfo = findListResponse(responses, getMailBoxName());

        if (listInfo == null) {
            return false;
        }

        // update the type information from the status.
        folderType = 0;
        if (!listInfo.noinferiors) {
            folderType |= HOLDS_FOLDERS;
        }
        if (!listInfo.noselect) {
            folderType |= HOLDS_MESSAGES;
        }

        // also update the separator information.  This will allow 
        // use to skip a call later 
        separator = listInfo.separator;
        // this can be omitted in the response, so assume a default 
        if (separator == '\0') {
            separator = '/';
        }

        // updated ok, so it must be there.
        return true;
    }
    


    /**
     * Return a list of folders from this Folder's namespace that match the supplied pattern.
     * Patterns may contain the following wildcards:
     * <ul><li>'%' which matches any characater except hierarchy delimiters</li>
     * <li>'*' which matches any character including hierarchy delimiters</li>
     * </ul>
     * This can be invoked when the folder is closed.
     * 
     * @param pattern the pattern to search for
     * 
     * @return a possibly empty array containing Folders that matched the pattern
     * @throws MessagingException
     *                if there was a problem accessing the store
     */
    public synchronized Folder[] list(String pattern) throws MessagingException {
        // go filter the folders based on the pattern.  The server does most of the
        // heavy lifting on the pattern matching.
        return filterFolders(pattern, false);
    }


    /**
     * Return a list of folders to which the user is subscribed and which match the supplied pattern.
     * If the store does not support the concept of subscription then this should match against
     * all folders; the default implementation of this method achieves this by defaulting to the
     * {@link #list(String)} method.
     * 
     * @param pattern the pattern to search for
     * 
     * @return a possibly empty array containing subscribed Folders that matched the pattern
     * @throws MessagingException
     *                if there was a problem accessing the store
     */
    public synchronized Folder[] listSubscribed(String pattern) throws MessagingException {
        // go filter the folders based on the pattern.  The server does most of the
        // heavy lifting on the pattern matching.
        return filterFolders(pattern, true);
    }


    /**
     * Return the character used by this folder's Store to separate path components.
     *
     * @return the name separater character
     * @throws MessagingException if there was a problem accessing the store
     */
	public synchronized char getSeparator() throws MessagingException {
        // not determined yet, we need to ask the server for the information 
        if (separator == UNDETERMINED) {
            IMAPConnection connection = getConnection(); 
            try {
                List responses = connection.list("", fullname);
                IMAPListResponse info = findListResponse(responses, fullname);

                // if we didn't get any hits, then we just assume a reasonable default. 
                if (info == null) {
                    separator = '/';
                }
                else {
                    separator = info.separator;
                    // this can be omitted in the response, so assume a default 
                    if (separator == '\0') {
                        separator = '/';
                    }
                }
            } finally {
                releaseConnection(connection); 
            }
        }
        return separator;
	}


    /**
     * Return whether this folder can hold just messages or also
     * subfolders.  
     *
     * @return The combination of Folder.HOLDS_MESSAGES and Folder.HOLDS_FOLDERS, depending 
     * on the folder capabilities. 
     * @exception MessagingException
     */
	public int getType() throws MessagingException {
        // checking the validity will update the type information 
        // if it succeeds. 
        checkFolderValidity();
		return folderType;
	}
    

    /**
     * Create a new folder capable of containing subfolder and/or messages as
     * determined by the type parameter. Any hierarchy defined by the folder
     * name will be recursively created.
     * If the folder was sucessfully created, a {@link FolderEvent#CREATED CREATED FolderEvent}
     * is sent to all FolderListeners registered with this Folder or with the Store.
     * 
     * @param newType the type, indicating if this folder should contain subfolders, messages or both
     * 
     * @return true if the folder was sucessfully created
     * @throws MessagingException
     *                if there was a problem accessing the store
     */
	public synchronized boolean create(int newType) throws MessagingException {
        IMAPConnection connection = getConnection(); 
        try {

            // by default, just create using the fullname.  
            String newPath = fullname;

            // if this folder is expected to only hold additional folders, we need to
            // add a separator on to the end when we create this.
            if ((newType & HOLDS_MESSAGES) == 0) {
                newPath = fullname + separator;
            }
            try {
                // go create this
                connection.createMailbox(newPath);
                // verify this exists...also updates some of the status 
                boolean reallyCreated = checkExistance(connection); 
                // broadcast a creation event.
                notifyFolderListeners(FolderEvent.CREATED);
                return reallyCreated; 
            } catch (MessagingException e) {
                //TODO add folder level debug logging.
            }
            // we have a failure
            return false;
        } finally {
            releaseConnection(connection); 
        }
	}
    

    /**
     * Return the subscription status of this folder.
     *
     * @return true if the folder is marked as subscribed, false for
     *         unsubscribed.
     */
    public synchronized boolean isSubscribed() {
        try {
            IMAPConnection connection = getConnection(); 
            try {
                // get the lsub response for this folder.
                List responses = connection.listSubscribed("", fullname);

                IMAPListResponse response = findListResponse(responses, fullname);
                if (response == null) {
                    return false;
                }
                else {
                    // a NOSELECT flag response indicates the mailbox is no longer 
                    // selectable, so it's also no longer subscribed to. 
                    return !response.noselect; 
                }
            } finally {
                releaseConnection(connection); 
            }
        } catch (MessagingException e) {
            // Can't override to throw a MessagingException on this method, so 
            // just swallow any exceptions and assume false is the answer. 
        }
        return false; 
    }


    /**
     * Set or clear the subscription status of a file.
     *
     * @param flag
     *            The new subscription state.
     */
    public synchronized void setSubscribed(boolean flag) throws MessagingException {
        IMAPConnection connection = getConnection(); 
        try {             
            if (flag) {
                connection.subscribe(fullname);
            }
            else {
                connection.unsubscribe(fullname);
            }
        } finally {
            releaseConnection(connection); 
        }
    }

    /**
     * Check to see if this Folder conatins messages with the {@link Flag.RECENT} flag set.
     * This can be used when the folder is closed to perform a light-weight check for new mail;
     * to perform an incremental check for new mail the folder must be opened.
     *
     * @return true if the Store has recent messages
     * @throws MessagingException if there was a problem accessing the store
     */
	public synchronized boolean hasNewMessages() throws MessagingException {
        // the folder must exist for this to work.
        checkFolderValidity();
        
        // get the freshest status information.
        refreshStatus(true);
        // return the indicator from the message state.
        return recentMessages > 0;
	}

    /**
     * Get the Folder determined by the supplied name; if the name is relative
     * then it is interpreted relative to this folder. This does not check that
     * the named folder actually exists.
     *
     * @param name the name of the folder to return
     * @return the named folder
     * @throws MessagingException if there was a problem accessing the store
     */
    public Folder getFolder(String name) throws MessagingException {
        // this must be a real, valid folder to hold a subfolder
        checkFolderValidity(); 
        if (!holdsFolders()) {
            throw new MessagingException("Folder " + fullname + " cannot hold subfolders"); 
        }
        // our separator does not get determined until we ping the server for it.  We 
        // might need to do that now, so we need to use the getSeparator() method to retrieve this. 
        char separator = getSeparator(); 
        
        return new IMAPFolder((IMAPStore)store, fullname + separator + name, separator);
    }
    

    /**
     * Delete this folder and possibly any subfolders. This operation can only be
     * performed on a closed folder.
     * If recurse is true, then all subfolders are deleted first, then any messages in
     * this folder are removed and it is finally deleted; {@link FolderEvent#DELETED}
     * events are sent as appropriate.
     * If recurse is false, then the behaviour depends on the folder type and store
     * implementation as followd:
     * <ul>
     * <li>If the folder can only conrain messages, then all messages are removed and
     * then the folder is deleted; a {@link FolderEvent#DELETED} event is sent.</li>
     * <li>If the folder can onlu contain subfolders, then if it is empty it will be
     * deleted and a {@link FolderEvent#DELETED} event is sent; if the folder is not
     * empty then the delete fails and this method returns false.</li>
     * <li>If the folder can contain both subfolders and messages, then if the folder
     * does not contain any subfolders, any messages are deleted, the folder itself
     * is deleted and a {@link FolderEvent#DELETED} event is sent; if the folder does
     * contain subfolders then the implementation may choose from the following three
     * behaviors:
     * <ol>
     * <li>it may return false indicting the operation failed</li>
     * <li>it may remove all messages within the folder, send a {@link FolderEvent#DELETED}
     * event, and then return true to indicate the delete was performed. Note this does
     * not delete the folder itself and the {@link #exists()} operation for this folder
     * will return true</li>
     * <li>it may remove all messages within the folder as per the previous option; in
     * addition it may change the type of the Folder to only HOLDS_FOLDERS indictaing
     * that messages may no longer be added</li>
     * </li>
     * </ul>
     * FolderEvents are sent to all listeners registered with this folder or
     * with the Store.
     *
     * @param recurse whether subfolders should be recursively deleted as well
     * @return true if the delete operation succeeds
     * @throws MessagingException if there was a problem accessing the store
     */
	public synchronized boolean delete(boolean recurse) throws MessagingException {
        // we must be in the closed state.
        checkClosed();

        // if recursive, get the list of subfolders and delete them first.
        if (recurse) {

            Folder[] subfolders = list();
            for (int i = 0; i < subfolders.length; i++) {
                // this is a recursive delete also
                subfolders[i].delete(true);
            }
        }

        IMAPConnection connection = getConnection(); 
        try {
            // delete this one now.
            connection.deleteMailbox(fullname);
            // this folder no longer exists on the server.
            listInfo = null;

            // notify interested parties about the deletion.
            notifyFolderListeners(FolderEvent.DELETED);
            return true;

        } catch (MessagingException e) {
            // ignored
        } finally {
            releaseConnection(connection); 
        }
        return false;
	}


    /**
     * Rename this folder; the folder must be closed.
     * If the rename is successfull, a {@link FolderEvent#RENAMED} event is sent to
     * all listeners registered with this folder or with the store.
     *
     * @param newName the new name for this folder
     * @return true if the rename succeeded
     * @throws MessagingException if there was a problem accessing the store
     */
	public synchronized boolean renameTo(Folder f) throws MessagingException {
        // we must be in the closed state.
        checkClosed();
        // but we must also exist
        checkFolderValidity();

        IMAPConnection connection = getConnection(); 
        try {
            // delete this one now.
            connection.renameMailbox(fullname, f.getFullName());
            // we renamed, so get a fresh set of status 
            refreshStatus(false); 

            // notify interested parties about the deletion.
            notifyFolderRenamedListeners(f);
            return true;
        } catch (MessagingException e) {
            // ignored
        } finally {
            releaseConnection(connection); 
        }
        return false;
	}


    /**
     * Open this folder; the folder must be able to contain messages and
     * must currently be closed. If the folder is opened successfully then
     * a {@link ConnectionEvent#OPENED} event is sent to listeners registered
     * with this Folder.
     * <p/>
     * Whether the Store allows multiple connections or if it allows multiple
     * writers is implementation defined.
     *
     * @param mode READ_ONLY or READ_WRITE
     * @throws MessagingException if there was a problem accessing the store
     */
	public synchronized void open(int mode) throws MessagingException {

        // we use a synchronized block rather than use a synchronized method so that we
        // can notify the event listeners while not holding the lock.
        synchronized(this) {
            // can only be performed on a closed folder
            checkClosed();
            // ask the store to kindly hook us up with a connection.
            // We're going to hang on to this until we're closed, so store it in 
            // the Folder field.  We need to make sure our mailbox is selected while 
            // we're working things. 
            currentConnection = ((IMAPStore)store).getFolderConnection(this); 
            // we need to make ourselves a handler of unsolicited responses 
            currentConnection.addResponseHandler(this); 
            // record our open mode
            this.mode = mode;


            try {
                // try to open, which gives us a lot of initial mailbox state.
                IMAPMailboxStatus status = currentConnection.openMailbox(fullname, mode == Folder.READ_ONLY);

                // not available in the requested mode?
                if (status.mode != mode) {
                    // trying to open READ_WRITE and this isn't available?
                    if (mode == READ_WRITE) {
                        throw new ReadOnlyFolderException(this, "Cannot open READ_ONLY folder in READ_WRITE mode");
                    }
                }
                
                // save this status and when we got it for later updating. 
                cachedStatus = status; 
                // mark when we got this
                lastStatusTimeStamp = System.currentTimeMillis();

                // now copy the status information over and flip over the open sign.
                this.mode = status.mode;
                maxSequenceNumber = status.messages;
                recentMessages = status.recentMessages;
                uidValidity = status.uidValidity;
                uidNext = status.uidNext;

                availableFlags = status.availableFlags;
                permanentFlags = status.permanentFlags;

                // create a our caches
                messages = new LinkedList(); 
                uidCache = new HashMap();
                // this is a real pain, but because we need to track updates 
                // to message sequence numbers while the folder is open, the 
                // messages list needs to be populated with Message objects 
                // to keep track of things.  The IMAPMessage objects will not 
                // retrieve information from the server until required, so they're
                // relatively lightweight at this point. 
                populateMessageCache(); 

                // we're open for business folks!
                folderOpen = true;
                notifyConnectionListeners(ConnectionEvent.OPENED);
            } finally {
                // NB:  this doesn't really release this, but it does drive 
                // the processing of any unsolicited responses. 
                releaseConnection(currentConnection); 
            }
        }
	}
    
    
    /**
     * Populate the message cache with dummy messages, ensuring we're filled 
     * up to the server-reported number of messages. 
     * 
     * @exception MessagingException
     */
    protected void populateMessageCache() {
        // spin through the server-reported number of messages and add a dummy one to 
        // the cache.  The message number is assigned from the id counter, the 
        // sequence number is the cache position + 1. 
        for (int i = messages.size(); i < maxSequenceNumber; i++) {
            messages.add(new IMAPMessage(this, ((IMAPStore)store), nextMessageID++, i+1));  
        }
    }
    

    /**
     * Close this folder; it must already be open.
     * A  @link ConnectionEvent#CLOSED} event is sent to all listeners registered
     {* 
     * with this folder.
     *
     * @param expunge whether to expunge all deleted messages
     * @throws MessagingException if there was a problem accessing the store; the folder is still closed
     */
	public synchronized void close(boolean expunge) throws MessagingException {
		// Can only be performed on an open folder
		checkOpen();
        cleanupFolder(expunge, false); 
	}
    
    
    /**
     * Do folder cleanup.  This is used both for normal
     * close operations, and adnormal closes where the
     * server has sent us a BYE message.
     * 
     * @param expunge Indicates whether open messages should be expunged.
     * @param disconnected
     *                The disconnected flag.  If true, the server has cut
     *                us off, which means our connection can not be returned
     *                to the connection pool.
     * 
     * @exception MessagingException
     */
    protected void cleanupFolder(boolean expunge, boolean disconnected) throws MessagingException {
		folderOpen = false;
        uidCache = null; 
        messages = null; 
        // if we have a connection active at the moment
        if (currentConnection != null) {
            // was this a forced disconnect by the server?
            if (disconnected) {
                currentConnection.setClosed(); 
            }
            else {
                // The CLOSE operation depends on what mode was used to select the mailbox.  
                // If we're open in READ-WRITE mode, we used a SELECT operation.  When CLOSE 
                // is issued, any deleted messages will be expunged.  If we've been asked not 
                // to expunge the messages, we have a problem.  The solution is to reselect the 
                // mailbox using EXAMINE, which will not expunge messages when closed.  
                if (mode == READ_WRITE && !expunge) {
                    // we can ignore the result...we're just switching modes. 
                    currentConnection.openMailbox(fullname, true);
                }
                
                // have this close the selected mailbox 
                currentConnection.closeMailbox(); 
            }
            currentConnection.removeResponseHandler(this); 
            // we need to release the connection to the Store once we're closed 
            ((IMAPStore)store).releaseFolderConnection(this, currentConnection); 
            currentConnection = null; 
        }
		notifyConnectionListeners(ConnectionEvent.CLOSED);
    }

    
    /**
     * Tests the open status of the folder.
     *
     * @return true if the folder is open, false otherwise.
     */
	public boolean isOpen() {
		return folderOpen;
	}

    /**
     * Get the permanentFlags
     *
     * @return The set of permanent flags we support (only SEEN).
     */
	public synchronized Flags getPermanentFlags() {
        if (permanentFlags != null) {
            // we need a copy of our master set.
            return new Flags(permanentFlags);
        }
        else {
            // a null return is expected if not there. 
            return null; 
        }
	}


    /**
     * Return the number of messages this folder contains.
     * If this operation is invoked on a closed folder, the implementation
     * may choose to return -1 to avoid the expense of opening the folder.
     *
     * @return the number of messages, or -1 if unknown
     * @throws MessagingException if there was a problem accessing the store
     */
	public synchronized int getMessageCount() throws MessagingException {
        checkFolderValidity();

        // if we haven't opened the folder yet, we might not have good status information.
        // go request some, which updates the folder fields also.
        refreshStatus(false);
		return maxSequenceNumber;
	}

    /**
     * Return the numbew of messages in this folder that have the {@link Flag.RECENT} flag set.
     * If this operation is invoked on a closed folder, the implementation
     * may choose to return -1 to avoid the expense of opening the folder.
     * The default implmentation of this method iterates over all messages
     * in the folder; subclasses should override if possible to provide a more
     * efficient implementation.
     * 
     * NB:  This is an override of the default Folder implementation, which 
     * examines each of the messages in the folder.  IMAP has more efficient 
     * mechanisms for grabbing the information. 
     *
     * @return the number of new messages, or -1 if unknown
     * @throws MessagingException if there was a problem accessing the store
     */
    public synchronized int getNewMessageCount() throws MessagingException {
        // the folder must be a real one for this to work. 
        checkFolderValidity(); 
        // now get current status from the folder 
        refreshStatus(false); 
        // this should be current now. 
        return recentMessages; 
    }



    /**
     * Return the number of messages in this folder that do not have the {@link Flag.SEEN} flag set.
     * If this operation is invoked on a closed folder, the implementation
     * may choose to return -1 to avoid the expense of opening the folder.
     * The default implmentation of this method iterates over all messages
     * in the folder; subclasses should override if possible to provide a more
     * efficient implementation.
     * 
     * NB:  This is an override of the default Folder implementation, which 
     * examines each of the messages in the folder.  IMAP has more efficient 
     * mechanisms for grabbing the information. 
     *
     * @return the number of new messages, or -1 if unknown
     * @throws MessagingException if there was a problem accessing the store
     */
	public synchronized int getUnreadMessageCount() throws MessagingException {
        checkFolderValidity();
        // if we haven't opened the folder yet, we might not have good status information.
        // go request some, which updates the folder fields also.
        if (!folderOpen) {
            refreshStatus(false);
        }
        else {
            // if we have an open connection, then search the folder for any messages
            // marked UNSEEN.

            // UNSEEN is a false test on SEEN using the search criteria.
            SearchTerm criteria = new FlagTerm(new Flags(Flags.Flag.SEEN), false);
            
            // ask the store to kindly hook us up with a connection.
            IMAPConnection connection = getConnection(); 
            try {
                // search using the connection directly rather than calling our search() method so we don't
                // need to instantiate each of the matched messages.  We're really only interested in the count
                // right now.
                int[] matches = connection.searchMailbox(criteria);
                // update the unseen count.
                unseenMessages = matches == null ? 0 : matches.length;
            } finally {
                releaseConnection(connection); 
            }
        }
        // return our current message count.
		return unseenMessages;
	}



    /**
     * Return the number of messages in this folder that have the {@link Flag.DELETED} flag set.
     * If this operation is invoked on a closed folder, the implementation
     * may choose to return -1 to avoid the expense of opening the folder.
     * The default implmentation of this method iterates over all messages
     * in the folder; subclasses should override if possible to provide a more
     * efficient implementation.
     *
     * @return the number of new messages, or -1 if unknown
     * @throws MessagingException if there was a problem accessing the store
     */
	public synchronized int getDeletedMessageCount() throws MessagingException {
        checkFolderValidity();

        // if we haven't opened the folder yet, we might not have good status information.
        // go request some, which updates the folder fields also.
        if (!folderOpen) {
            // the status update doesn't return deleted messages.  These can only be obtained by
            // searching an open folder.  Just return a bail-out response
            return -1;
        }
        else {
            // if we have an open connection, then search the folder for any messages
            // marked DELETED.

            // UNSEEN is a false test on SEEN using the search criteria.
            SearchTerm criteria = new FlagTerm(new Flags(Flags.Flag.DELETED), true);
            
            // ask the store to kindly hook us up with a connection.
            IMAPConnection connection = getConnection(); 
            try {
                // search using the connection directly rather than calling our search() method so we don't
                // need to instantiate each of the matched messages.  We're really only interested in the count
                // right now.
                int[] matches = connection.searchMailbox(criteria);
                return matches == null ? 0 : matches.length;
            } finally {
                releaseConnection(connection); 
            }
        }
	}


    /**
     * Retrieve the message with the specified index in this Folder;
     * messages indices start at 1 not zero.
     * Clients should note that the index for a specific message may change
     * if the folder is expunged; {@link Message} objects should be used as
     * references instead.
     * 
     * @param msgNum The message sequence number of the target message.
     * 
     * @return the message
     * @throws MessagingException
     *                if there was a problem accessing the store
     */
    public synchronized Message getMessage(int msgNum) throws MessagingException {
        // Can only be performed on an Open folder
        checkOpen();
        // Check the validity of the message number.  This may require pinging the server to
        // see if there are new messages in the folder.
        checkMessageValidity(msgNum);
        // ok, if the message number is within range, we should have this in the 
        // messages list.  Just return the element. 
        return (Message)messages.get(msgNum - 1); 
    }


    /**
     * Retrieve a range of messages for this folder.
     * messages indices start at 1 not zero.
     * 
     * @param start  Index of the first message to fetch, inclusive.
     * @param end    Index of the last message to fetch, inclusive.
     * 
     * @return An array of the fetched messages.
     * @throws MessagingException
     *                if there was a problem accessing the store
     */
    public synchronized Message[] getMessages(int start, int end) throws MessagingException {
        // Can only be performed on an Open folder
        checkOpen();
        Message[] messageRange = new Message[end - start + 1];
        
        for (int i = 0; i < messageRange.length; i++) {
            // NB:  getMessage() requires values that are origin 1, so there's 
            // no need to adjust the value by other than the start position. 
            messageRange[i] = getMessage(start + i);
        }
        return messageRange; 
    }


    /**
     * Append the supplied messages to this folder. A {@link MessageCountEvent} is sent
     * to all listeners registered with this folder when all messages have been appended.
     * If the array contains a previously expunged message, it must be re-appended to the Store
     * and implementations must not abort this operation.
     * 
     * @param msgs   The array of messages to append to the folder.
     * 
     * @throws MessagingException
     *                if there was a problem accessing the store
     */
	public synchronized void appendMessages(Message[] msgs) throws MessagingException {
        checkFolderValidity(); 
        for (int i = 0; i < msgs.length; i++) {
            Message msg = msgs[i]; 
            
            appendMessage(msg); 
        }
	}

    /**
     * Hint to the store to prefetch information on the supplied messages.
     * Subclasses should override this method to provide an efficient implementation;
     * the default implementation in this class simply returns.
     *
     * @param messages messages for which information should be fetched
     * @param profile  the information to fetch
     * @throws MessagingException if there was a problem accessing the store
     * @see FetchProfile
     */
    public void fetch(Message[] messages, FetchProfile profile) throws MessagingException {
        
        // we might already have the information being requested, so ask each of the 
        // messages in the list to evaluate itself against the profile.  We'll only ask 
        // the server to send information that's required. 
        List fetchSet = new ArrayList(); 
        
        for (int i = 0; i < messages.length; i++) {
            Message msg = messages[i]; 
            // the message is missing some of the information still.  Keep this in the list. 
            // even if the message is only missing one piece of information, we still fetch everything. 
            if (((IMAPMessage)msg).evaluateFetch(profile)) {
                fetchSet.add(msg); 
            }
        }
        
        // we've got everything already, no sense bothering the server 
        if (fetchSet.isEmpty()) {
            return;
        }
        // ask the store to kindly hook us up with a connection.
        IMAPConnection connection = getConnection(); 
        try {
            // ok, from this point onward, we don't want any threads messing with the 
            // message cache.  A single processed EXPUNGE could make for a very bad day 
            synchronized(this) {
                // get the message set for this 
                String messageSet = generateMessageSet(fetchSet); 
                // fetch all of the responses 
                List responses = connection.fetch(messageSet, profile); 
                
                // IMPORTANT:  We must do our updates while synchronized to keep the 
                // cache from getting updated underneath us.   This includes 
                // not releasing the connection until we're done to delay processing any 
                // pending expunge responses.  
                for (int i = 0; i < responses.size(); i++) {
                    IMAPFetchResponse response = (IMAPFetchResponse)responses.get(i); 
                    Message msg = getMessage(response.getSequenceNumber()); 
                    // Belt and Braces.  This should never be false. 
                    if (msg != null) {
                        // have the message apply this to itself. 
                        ((IMAPMessage)msg).updateMessageInformation(response); 
                    }
                }
            }
        } finally {
            releaseConnection(connection); 
        }
        return;
    }

    /**
     * Set flags on the messages to the supplied value; all messages must belong to this folder.
     * This method may be overridden by subclasses that can optimize the setting
     * of flags on multiple messages at once; the default implementation simply calls
     * {@link Message#setFlags(Flags, boolean)} for each supplied messages.
     * 
     * @param messages whose flags should be set
     * @param flags    the set of flags to modify
     * @param set      Indicates whether the flags should be set or cleared.
     * 
     * @throws MessagingException
     *                if there was a problem accessing the store
     */
    public void setFlags(Message[] messages, Flags flags, boolean set) throws MessagingException {
        // this is a list of messages for the change broadcast after the update 
        List updatedMessages = new ArrayList(); 
        
        synchronized(this) {
            // the folder must be open and writeable.
            checkOpenReadWrite();

            // now make sure these are settable flags.
            if (!availableFlags.contains(flags))
            {
                throw new MessagingException("The IMAP server does not support changing of this flag set");
            }

            // turn this into a set of message numbers
            String messageSet = generateMessageSet(messages);
            // if all of the messages have been expunged, nothing to do.
            if (messageSet == null) {
                return;
            }
            // ask the store to kindly hook us up with a connection.
            IMAPConnection connection = getConnection(); 

            try {
                // and have the connection set this
                List responses = connection.setFlags(messageSet, flags, set);
                // retrieve each of the messages from our cache, and do the flag update.
                // we need to keep the list so we can broadcast a change update event 
                // when we're finished. 
                for (int i = 0; i < responses.size(); i++) {
                    IMAPFetchResponse response = (IMAPFetchResponse)responses.get(i); 

                    // get the updated message and update the internal state. 
                    Message message = getMessage(response.sequenceNumber); 
                    // this shouldn't happen, but it might have been expunged too. 
                    if (message != null) {
                        ((IMAPMessage)message).updateMessageInformation(response); 
                        updatedMessages.add(message); 
                    }     
                }
            } finally {
                releaseConnection(connection); 
            }
        }
        
        // ok, we're no longer holding the lock.  Now go broadcast the update for each 
        // of the affected messages. 
        for (int i = 0; i < updatedMessages.size(); i++) {
            Message message = (Message)updatedMessages.get(i); 
            notifyMessageChangedListeners(MessageChangedEvent.FLAGS_CHANGED, message);
        }
    }

    
    /**
     * Set flags on a range of messages to the supplied value.
     * This method may be overridden by subclasses that can optimize the setting
     * of flags on multiple messages at once; the default implementation simply
     * gets each message and then calls {@link Message#setFlags(Flags, boolean)}.
     * 
     * @param start  first message end set
     * @param end    last message end set
     * @param flags  the set of flags end modify
     * @param value  Indicates whether the flags should be set or cleared.
     * 
     * @throws MessagingException
     *                if there was a problem accessing the store
     */
    public synchronized void setFlags(int start, int end, Flags flags, boolean value) throws MessagingException {
        Message[] msgs = new Message[end - start + 1]; 
        
        for (int i = start; i <= end; i++) {
            msgs[i] = getMessage(i);
        }
        // go do a bulk set operation on these messages 
        setFlags(msgs, flags, value); 
    }

    /**
     * Set flags on a set of messages to the supplied value.
     * This method may be overridden by subclasses that can optimize the setting
     * of flags on multiple messages at once; the default implementation simply
     * gets each message and then calls {@link Message#setFlags(Flags, boolean)}.
     * 
     * @param ids    the indexes of the messages to set
     * @param flags  the set of flags end modify
     * @param value  Indicates whether the flags should be set or cleared.
     * 
     * @throws MessagingException
     *                if there was a problem accessing the store
     */
    public synchronized void setFlags(int ids[], Flags flags, boolean value) throws MessagingException {
        Message[] msgs = new Message[ids.length]; 
        
        for (int i = 0; i <ids.length; i++) {
            msgs[i] = getMessage(ids[i]);
        }
        // go do a bulk set operation on these messages 
        setFlags(msgs, flags, value); 
    }

    
    /**
     * Copy the specified messages to another folder.
     * The default implementation simply appends the supplied messages to the
     * target folder using {@link #appendMessages(Message[])}.
     * @param messages the messages to copy
     * @param folder the folder to copy to
     * @throws MessagingException if there was a problem accessing the store
     */
    public synchronized void copyMessages(Message[] messages, Folder folder) throws MessagingException {
        // the default implementation just appends the messages to the target.  If 
        // we're copying between two folders of the same store, we can get the server to 
        // do most of the work for us without needing to fetch all of the message data.  
        // If we're dealing with two different Store instances, we need to do this the 
        // hardway.
        if (getStore() != folder.getStore()) {
            super.copyMessages(messages, folder); 
            return; 
        }

        // turn this into a set of message numbers
        String messageSet = generateMessageSet(messages);
        // if all of the messages have been expunged, nothing to do.
        if (messageSet == null) {
            return;
        }
        // ask the store to kindly hook us up with a connection.
        IMAPConnection connection = getConnection(); 

        try {
            // ask the server to copy this information over to the other mailbox. 
            connection.copyMessages(messageSet, folder.getFullName()); 
        } finally {
            releaseConnection(connection); 
        }
    }

    

    /**
     * Permanently delete all supplied messages that have the DELETED flag set from the Store.
     * The original message indices of all messages actually deleted are returned and a
     * {@link MessageCountEvent} event is sent to all listeners with this folder. The expunge
     * may cause the indices of all messaged that remain in the folder to change.
     *
     * @return the original indices of messages that were actually deleted
     * @throws MessagingException if there was a problem accessing the store
     */
	public synchronized Message[] expunge() throws MessagingException {
        // must be open to do this.
        checkOpen();
        // and changes need to be allowed
        checkReadWrite();

        // ask the store to kindly hook us up with a connection.
        IMAPConnection connection = getConnection(); 
        List expunges = null;

        try {
            // send the expunge notification.  This operation results in "nn EXPUNGE" responses getting returned
            // for each expunged messages.  These will be dispatched to our response handler, which will process
            // the expunge operation.  We could process this directly, but we may have received asynchronous
            // expunge messages that also marked messages as expunged.
            expunges = connection.expungeMailbox();
        } finally {
            releaseConnection(connection); 
        }

        // we get one EXPUNGE message for each message that's expunged.  They MUST be processed in 
        // order, as the message sequence numbers represent a relative position that takes into account 
        // previous expunge operations.  For example, if message sequence numbers 5, 6, and 7 are 
        // expunged, we receive 3 expunge messages, all indicating that message 5 has been expunged. 
        Message[] messages = new Message[expunges.size()]; 

        // now we need to protect the internal structures
        synchronized (this) {
            // expunge all of the messages from the message cache.  This keeps the sequence 
            // numbers up to-date. 
            for (int i = 0; i < expunges.size(); i++) {
                IMAPSizeResponse response = (IMAPSizeResponse)expunges.get(i); 
                messages[i] = expungeMessage(response.getSize()); 
            }
        }
        // if we have messages that have been removed, broadcast the notification.
        if (messages.length > 0) {
            notifyMessageRemovedListeners(true, messages);
        }

        // note, we're expected to return an array in all cases, even if the expunged count was zero.
        return messages;
	}



    /**
     * Search the supplied messages for those that match the supplied criteria;
     * messages must belong to this folder.
     * The default implementation iterates through the messages, returning those
     * whose {@link Message#match(javax.mail.search.SearchTerm)} method returns true;
     * subclasses may provide a more efficient implementation.
     *
     * @param term the search criteria
     * @param messages the messages to search
     * @return an array containing messages that match the criteria
     * @throws MessagingException if there was a problem accessing the store
     */
    public synchronized Message[] search(SearchTerm term) throws MessagingException {
        // only allowed on open folders
        checkOpen();

        // ask the store to kindly hook us up with a connection.
        IMAPConnection connection = getConnection(); 

        try {
            // just search everything
            int[] messageNumbers = connection.searchMailbox(term);
            return resolveMessages(messageNumbers);
        } finally {
            releaseConnection(connection); 
        }
    }



    /**
     * Search the supplied messages for those that match the supplied criteria;
     * messages must belong to this folder.
     * The default implementation iterates through the messages, returning those
     * whose {@link Message#match(javax.mail.search.SearchTerm)} method returns true;
     * subclasses may provide a more efficient implementation.
     *
     * @param term the search criteria
     * @param messages the messages to search
     * @return an array containing messages that match the criteria
     * @throws MessagingException if there was a problem accessing the store
     */
    public synchronized Message[] search(SearchTerm term, Message[] messages) throws MessagingException {
        // only allowed on open folders
        checkOpen();

        // turn this into a string specifier for these messages.  We'll weed out the expunged messages first.
        String messageSet = generateMessageSet(messages);

        // If we have no "live" messages to search, just return now.  We're required to return a non-null
        // value, so give an empy array back.
        if (messageSet == null) {
            return new Message[0];
        }

        // ask the store to kindly hook us up with a connection.
        IMAPConnection connection = getConnection(); 

        try {

            // now go do the search.
            int[] messageNumbers = connection.searchMailbox(messageSet, term);
            return resolveMessages(messageNumbers);
        } finally {
            releaseConnection(connection); 
        }
    }

    /**
     * Get the UID validity value for this Folder.
     * 
     * @return The current UID validity value, as a long. 
     * @exception MessagingException
     */
    public synchronized long getUIDValidity() throws MessagingException
    {
        // get the latest status to make sure we have the  
        // most current. 
        refreshStatus(true); 
        return uidValidity; 
    }

    /**
     * Retrieve a message using the UID rather than the 
     * message sequence number.  Returns null if the message
     * doesn't exist.
     * 
     * @param uid    The target UID.
     * 
     * @return the Message object.  Returns null if the message does
     *         not exist.
     * @exception MessagingException
     */
    public synchronized Message getMessageByUID(long uid) throws MessagingException
    {
        // only allowed on open folders
        checkOpen();
        
        Long key = new Long(uid); 
        // first check to see if we have a cached value for this 
        synchronized(messages) {
            Message msg = (Message)uidCache.get(key); 
            if (msg != null) {
                return msg; 
            }
        }

        // ask the store to kindly hook us up with a connection.
        IMAPConnection connection = getConnection(); 

        try {
            // locate the message identifier 
            IMAPUid imapuid = connection.getSequenceNumberForUid(uid);
            // if nothing is returned, the message doesn't exist 
            if (imapuid == null) {
                return null; 
            }
            
            
            // retrieve the actual message object and place this in the UID cache
            return retrieveMessageByUid(key, imapuid.messageNumber); 
        } finally {
            releaseConnection(connection); 
        }
    }

    /**
     * Get a series of messages using a UID range.  The 
     * special value LASTUID can be used to mark the 
     * last available message.
     * 
     * @param start  The start of the UID range.
     * @param end    The end of the UID range.  The special value
     *               LASTUID can be used to request all messages up
     *               to the last UID.
     * 
     * @return An array containing all of the messages in the 
     *         range.
     * @exception MessagingException
     */
    public synchronized Message[] getMessagesByUID(long start, long end) throws MessagingException
    {
        // only allowed on open folders
        checkOpen();
        // ask the store to kindly hook us up with a connection.
        IMAPConnection connection = getConnection(); 

        try {
            // locate the message identifier 
            List uids = connection.getSequenceNumbersForUids(start, end);
            Message[] msgs = new Message[uids.size()];
            
            // fill in each of the messages based on the returned value 
            for (int i = 0; i < msgs.length; i++) {
                IMAPUid uid = (IMAPUid)uids.get(i); 
                msgs[i] = retrieveMessageByUid(new Long(uid.uid), uid.messageNumber);
            }
            
            return msgs; 
        } finally {
            releaseConnection(connection); 
        }
        
        
    }

    /**
     * Retrieve a set of messages by explicit UIDs.  If 
     * any message in the list does not exist, null 
     * will be returned for the corresponding item.
     * 
     * @param ids    An array of UID values to be retrieved.
     * 
     * @return An array of Message items the same size as the ids
     *         argument array.  This array will contain null
     *         entries for any UIDs that do not exist.
     * @exception MessagingException
     */
    public synchronized Message[] getMessagesByUID(long[] ids) throws MessagingException
    {
        // only allowed on open folders
        checkOpen();
        
        Message[] msgs = new Message[ids.length];
        
        for (int i = 0; i < msgs.length; i++) {
            msgs[i] = getMessageByUID(ids[i]); 
        }
        
        return msgs; 
    }

    /**
     * Retrieve the UID for a message from this Folder.
     * The argument Message MUST belong to this Folder
     * instance, otherwise a NoSuchElementException will 
     * be thrown.
     * 
     * @param message The target message.
     * 
     * @return The UID associated with this message.
     * @exception MessagingException
     */
    public synchronized long getUID(Message message) throws MessagingException
    {
        // verify this actually is in this folder. 
        checkMessageFolder(message); 
        IMAPMessage msg = (IMAPMessage)message; 
        
        // we might already know this bit of information 
        if (msg.getUID() != -1) {
            return msg.getUID(); 
        }

        // ask the store to kindly hook us up with a connection.
        IMAPConnection connection = getConnection(); 

        try {
            // locate the message identifier 
            IMAPUid imapuid = connection.getUidForSequenceNumber(msg.getMessageNumber());
            // if nothing is returned, the message doesn't exist 
            if (imapuid == null) {
                return -1;
            }
            // cache this information now that we've gotten it. 
            addToUidCache(new Long(imapuid.uid), getMessage(imapuid.messageNumber));
            // return the UID information. 
            return imapuid.uid; 
        } finally {
            releaseConnection(connection); 
        }
    }
    
    /**
     * Retrieve a message from a UID/message mapping.
     * 
     * @param key       The UID key used for the mapping.
     * @param msgNumber The message sequence number.
     * 
     * @return The Message object corresponding to the message.
     * @exception MessagingException
     */
    protected synchronized Message retrieveMessageByUid(Long key, int msgNumber) throws MessagingException
    {
        synchronized (messages) {
            // first check the cache...this might have already been added. 
            Message msg = (Message)uidCache.get(key); 
            if (msg != null) {
                return msg; 
            }
            
            // retrieve the message by sequence number 
            msg = getMessage(msgNumber); 
            // add this to our UID mapping cache. 
            addToUidCache(key, msg); 
            return msg; 
        }
    }
    
    
    /**
     * Add a message to the UID mapping cache, ensuring that 
     * the UID value is updated.
     * 
     * @param key    The UID key.
     * @param msg    The message to add.
     */
    protected void addToUidCache(Long key, Message msg) {  
        synchronized (messages) {
            ((IMAPMessage)msg).setUID(key.longValue());  
            uidCache.put(key, msg); 
        }
    }
    
    
    /**
     * Append a single message to the IMAP Folder.
     * 
     * @param msg    The message to append.
     * 
     * @exception MessagingException
     */
    protected synchronized void appendMessage(Message msg) throws MessagingException 
    {
        // sort out the dates.  If no received date, use the sent date. 
        Date date = msg.getReceivedDate(); 
        if (date == null) {
            date = msg.getSentDate(); 
        }
        
        Flags flags = msg.getFlags(); 
        
        // convert the message into an array of bytes we can attach as a literal. 
        ByteArrayOutputStream out = new ByteArrayOutputStream(); 
        
        try {
            msg.writeTo(out); 
        } catch (IOException e) {
        }
        
        // now issue the append command 
        IMAPConnection connection = getConnection(); 
        try {
            connection.appendMessage(getFullName(), date, flags, out.toByteArray()); 
        } finally {
            releaseConnection(connection); 
        }
    }

    
    /**
     * Retrieve the list of matching groups from the IMAP server using the LIST
     * or LSUB command. The server does the wildcard matching for us.
     *
     * @param pattern
     *            The pattern string (in wildmat format) used to match.
     *
     * @return An array of folders for the matching groups.
     */
    protected synchronized Folder[] filterFolders(String pattern, boolean subscribed) throws MessagingException {
        IMAPConnection connection = getConnection(); 
        // this is used to filter out our own folder from the search 
        String root = fullname + getSeparator();
        
        List responses = null;
        try {             


            if (subscribed) {
                // get the lsub response for this folder.
                responses = connection.listSubscribed(root, pattern);
            }
            else {
                // grab using the LIST command.
                responses = connection.list(root, pattern);
            }
        } finally {
            releaseConnection(connection); 
        }

        List folders = new ArrayList();

        for (int i = 0; i < responses.size(); i++) {
            IMAPListResponse response = (IMAPListResponse)responses.get(i);
            // if a full wildcard is specified, the root folder can be returned too.  Make sure we
            // filter that one out.
            if (!response.mailboxName.equals(root)) {
                IMAPFolder folder = new IMAPFolder((IMAPStore)store, response.mailboxName, response.separator);
                folders.add(folder);
            }
        }

        // convert into an array and return
        return (Folder[])folders.toArray(new Folder[folders.size()]);
    }


    /**
     * Test if a folder can hold sub folders.
     *
     * @return True if the folder is allowed to have subfolders.
     */
    protected synchronized boolean holdsFolders() throws MessagingException {
        checkFolderValidity();
        return (folderType & HOLDS_FOLDERS) != 0;
    }


    /**
     * Validate that a target message number is considered valid
     * by the IMAP server.  If outside of the range we currently
     * are a ware of, we'll ping the IMAP server to see if there
     * have been any updates.
     *
     * @param messageNumber
     *               The message number we're checking.
     *
     * @exception MessagingException
     */
    protected void checkMessageValidity(int messageNumber) throws MessagingException {
        // lower range for a message is 1.
        if (messageNumber < 1) {
            throw new MessagingException("Invalid message number for IMAP folder: " + messageNumber);
        }
        // if within our current known range, we'll accept this
        if (messageNumber <= maxSequenceNumber) {
            return;
        }
        
        IMAPConnection connection = getConnection(); 

        synchronized (this) {
            try {
                // ping the server to see if there's any updates to process.  The updates are handled
                // by the response handlers.
                connection.updateMailboxStatus();
            } finally {
                releaseConnection(connection); 
            }
        }

        // still out of range?
        if (messageNumber > maxSequenceNumber) {
            throw new MessagingException("Message " + messageNumber + " does not exist on server");
        }
    }


	/**
	 * Below is a list of convenience methods that avoid repeated checking for a
	 * value and throwing an exception
	 */

    /**
     * Ensure the folder is open.  Throws a MessagingException
     * if not in the correct state for the operation.
     * 
     * @exception IllegalStateException
     */
    protected void checkOpen() throws IllegalStateException {
		if (!folderOpen){
		    throw new IllegalStateException("Folder is not Open");
		}
    }

    /**
     * Ensure the folder is not open for operations
     * that require the folder to be closed.
     * 
     * @exception IllegalStateException
     */
    protected void checkClosed() throws IllegalStateException {
		if (folderOpen){
		    throw new IllegalStateException("Folder is Open");
		}
    }

    /**
     * Ensure that the folder is open for read/write mode before doing
     * an operation that would make a change.
     *
     * @exception IllegalStateException
     */
    protected void checkReadWrite() throws IllegalStateException {
        if (mode != READ_WRITE) {
		    throw new IllegalStateException("Folder is opened READY_ONLY");
        }
    }


    /**
     * Check that the folder is open and in read/write mode.
     *
     * @exception IllegalStateException
     */
    protected void checkOpenReadWrite() throws IllegalStateException {
        checkOpen();
        checkReadWrite();
    }



    /**
     * Notify the message changed listeners that a 
     * message contained in the folder has been updated.
     * 
     * @param type   The type of update made to the message.
     * @param m      The message that was updated.
     * 
     * @see javax.mail.Folder#notifyMessageChangedListeners(int, javax.mail.Message)
     */
    public void notifyMessageChangedListeners(int type, Message m) {
    	super.notifyMessageChangedListeners(type, m);
    }

    
    /**
     * Retrieve the connection attached to this folder.  Throws an
     * exception if we don't have an active connection.
     *
     * @return The current connection object.
     * @exception MessagingException
     */
    protected synchronized IMAPConnection getConnection() throws MessagingException {
        // don't have an open connection yet?  Just request a pool connection. 
        if (currentConnection == null) {
            // request a connection from the central store. 
            IMAPConnection connection = ((IMAPStore)store).getFolderConnection(this);  
            // we need to make ourselves a handler of unsolicited responses 
            connection.addResponseHandler(this); 
            return connection;
        }
        // we have a connection for our use.  Just return it. 
        return currentConnection; 
    }
    
    
    /**
     * Release our connection back to the Store.
     * 
     * @param connection The connection to release.
     * 
     * @exception MessagingException
     */
    protected void releaseConnection(IMAPConnection connection) throws MessagingException {
        // This is a bit of a pain.  We need to delay processing of the 
        // unsolicited responses until after each user of the connection has 
        // finished processing the expected responses.  We need to do this because 
        // the unsolicited responses may include EXPUNGED messages.  The EXPUNGED 
        // messages will alter the message sequence numbers for the messages in the 
        // cache.  Processing the EXPUNGED messages too early will result in 
        // updates getting applied to the wrong message instances.  So, as a result, 
        // we delay that stage of the processing until all expected responses have 
        // been handled.  
        
        // process any pending messages before returning. 
        connection.processPendingResponses(); 
        // if no cached connection or this is somehow different from the cached one, just 
        // return it. 
        if (currentConnection == null || connection != currentConnection) {
            connection.removeResponseHandler(this); 
            ((IMAPStore)store).releaseFolderConnection(this, connection);  
        }
        // if we're open, then we don't have to worry about returning this connection 
        // to the Store.  This is set up perfectly for our use right now. 
    }
    
    
    /**
     * Obtain a connection object for a Message attached to this Folder.  This 
     * will be the Folder's connection, which is only available if the Folder 
     * is currently open.
     * 
     * @return The connection object for the Message instance to use. 
     * @exception MessagingException
     */
    synchronized IMAPConnection getMessageConnection() throws MessagingException {
        // if we're not open, the messages can't communicate either
        if (currentConnection == null) {
            throw new FolderClosedException(this, "No Folder connections available"); 
        }
        // return the current Folder connection.  At this point, we'll be sharing the 
        // connection between the Folder and the Message (and potentially, other messages).  The 
        // command operations on the connection are synchronized so only a single command can be 
        // issued at one time. 
        return currentConnection; 
    }
    
    
    /**
     * Release the connection object back to the Folder instance.  
     * 
     * @param connection The connection being released.
     * 
     * @exception MessagingException
     */
    void releaseMessageConnection(IMAPConnection connection) throws MessagingException {
        // release it back to ourselves...this will drive unsolicited message processing. 
        releaseConnection(connection); 
    }


    /**
     * Refresh the status information on this folder.
     * 
     * @param force  Force a status refresh always.
     * 
     * @exception MessagingException
     */
    protected void refreshStatus(boolean force) throws MessagingException {
        // first check that any cached status we've received has gotten a little moldy.
        if (cachedStatus != null) {
            // if not forcing, check the time out. 
            if (!force) {
                if (statusCacheTimeout > 0) {
                    long age = System.currentTimeMillis() - lastStatusTimeStamp;
                    if (age < statusCacheTimeout) {
                        return;                 
                    }
                }
            }
            // make sure the stale information is cleared out.
            cachedStatus = null;
        }
        
        IMAPConnection connection = getConnection(); 
        try {
            // ping the server for the list information for this folder
            cachedStatus = connection.getMailboxStatus(fullname);
            // mark when we got this
            lastStatusTimeStamp = System.currentTimeMillis();
        } finally {
            releaseConnection(connection); 
        }

        // refresh the internal state from the message information
        maxSequenceNumber = cachedStatus.messages;
        recentMessages = cachedStatus.recentMessages;
        unseenMessages = cachedStatus.unseenMessages;
        uidValidity = cachedStatus.uidValidity;
    }


    /**
     * Process an EXPUNGE response for a message, removing the
     * message from the message cache.
     * 
     * @param sequenceNumber
     *               The sequence number for the expunged message.
     * 
     * @return The Message object corresponding to this expunged
     *         message.
     * @exception MessagingException
     */
    protected synchronized Message expungeMessage(int sequenceNumber) throws MessagingException {
        // we need to remove this from our message list.  Deletion of a message by 
        // sequence number shifts the sequence numbers of every message after 
        // the target.  So we, need to remove the message, update its status, then 
        // update the sequence numbers of every message after that.  This is a serious 
        // pain!
        
        Message expungedMessage = (Message)messages.remove(sequenceNumber - 1); 
        // mark the message as expunged. 
        ((IMAPMessage)expungedMessage).setExpunged(true); 
        
        // update the message sequence numbers for every message after the 
        // expunged one.  NB.  The sequence number is the cache index + 1
        for (int i = sequenceNumber - 1; i < messages.size(); i++) {
            IMAPMessage message = (IMAPMessage)messages.get(i); 
            message.setSequenceNumber(i + 1); 
        }
        
        // have we retrieved a UID for this message?  If we have, then it's in the UID cache and
        // needs removal from there also
        long uid = ((IMAPMessage)expungedMessage).getUID();
        if (uid >= 0) {
            uidCache.remove(new Long(uid));
        }

        // adjust the message count downward
        maxSequenceNumber--;
        return expungedMessage; 
    }


    /**
     * Resolve an array of message numbers into an array of the
     * referenced messages.
     *
     * @param messageNumbers
     *               The array of message numbers (can be null).
     *
     * @return An array of Message[] containing the resolved messages from
     *         the list.  Returns a zero-length array if there are no
     *         messages to resolve.
     * @exception MessagingException
     */
    protected Message[] resolveMessages(int[] messageNumbers) throws MessagingException {
        // the connection search returns a null pointer if nothing was found, just convert this into a
        // null array.
        if (messageNumbers == null) {
            return new Message[0];
        }

        Message[] messages = new Message[messageNumbers.length];

        // retrieve each of the message numbers in turn.
        for (int i = 0; i < messageNumbers.length; i++) {
            messages[i] = getMessage(messageNumbers[i]);
        }

        return messages;
    }
    
    /**
     * Generate a message set string from a List of messages rather than an 
     * array.
     * 
     * @param messages The List of messages.
     * 
     * @return The evaluated message set string. 
     * @exception MessagingException
     */
    protected String generateMessageSet(List messages) throws MessagingException {
        Message[] msgs = (Message[])messages.toArray(new Message[messages.size()]); 
        return generateMessageSet(msgs); 
    }


    /**
     * Take an array of messages and generate a String <message set>
     * argument as specified by RFC 2060.  The message set argument
     * is a comma-separated list of message number ranges.  A
     * single element range is just one number.  A longer range is
     * a pair of numbers separated by a ":".  The generated string
     * should not have any blanks.  This will attempt to locate
     * consequetive ranges of message numbers, but will only do this
     * for messages that are already ordered in the array (i.e., we
     * don't try to sort).  Expunged messages are excluded from the
     * search, since they don't exist anymore.  A valid search string
     * will look something like this:
     *
     *    "3,6:10,15,21:35"
     *
     * @param messages The array of messages we generate from.
     *
     * @return A string formatted version of these message identifiers that
     *         can be used on an IMAP command.
     */
    protected String generateMessageSet(Message[] messages) throws MessagingException {
        StringBuffer set = new StringBuffer();

        for (int i = 0; i < messages.length; i++) {
            // first scan the list looking for a "live" message.
            IMAPMessage start = (IMAPMessage)messages[i];
            if (!start.isExpunged()) {

                // we can go ahead and add this to the list now.  If we find this is the start of a
                // range, we'll tack on the ":end" bit once we find the last message in the range.
                if (set.length() != 0) {
                    // only append the comma if not the first element of the list
                    set.append(',');
                }

                // append the first number.  NOTE:  We append this directly rather than 
                // use appendInteger(), which appends it using atom rules. 
                set.append(Integer.toString(start.getSequenceNumber()));

                // ok, we have a live one.  Now scan the list from here looking for the end of
                // a range of consequetive messages.
                int endIndex = -1; ;
                // get the number we're checking against.
                int previousSequence = start.getSequenceNumber();
                for (int j = i + 1; j < messages.length; j++) {
                    IMAPMessage message = (IMAPMessage)messages[j];
                    if (!message.isExpunged()) {
                        // still consequetive?
                        if (message.getSequenceNumber() == previousSequence + 1) {
                            // step this for the next check.
                            previousSequence++;
                            // record this as the current end of the range.
                            endIndex = j;
                        }
                        else {
                            // found a non-consequetive one, stop here
                            break;
                        }
                    }
                }

                // have a range end point?  Add the range specifier and step the loop index point
                // to skip over this
                if (endIndex != -1) {
                    // pick up the scan at the next location
                    i = endIndex;

                    set.append(':');
                    set.append(Integer.toString(((IMAPMessage)messages[endIndex]).getSequenceNumber()));
                }
            }
        }

        // return null for an empty list. This is possible because either an empty array has been handed to
        // us or all of the messages in the array have been expunged.
        if (set.length() == 0) {
            return null;
        }
        return set.toString();
    }
    
    /**
     * Verify that this folder exists on the server before 
     * performning an operation that requires a valid 
     * Folder instance. 
     * 
     * @exception MessagingException
     */
    protected void checkFolderValidity() throws MessagingException {
        // if we are holding a current listinfo response, then 
        // we have chached existance information.  In that case, 
        // all of our status is presumed up-to-date and we can go 
        // with that.  If we don't have the information, then we 
        // ping the server for it. 
        if (listInfo == null && !exists()) {
            throw new FolderNotFoundException(this, "Folder " + fullname + " not found on server"); 
        }
    }
    
    
    /**
     * Check if a Message is properly within the target 
     * folder. 
     * 
     * @param msg    The message we're checking.
     * 
     * @exception MessagingException
     */
    protected void checkMessageFolder(Message msg) throws MessagingException {
        if (msg.getFolder() != this) {
            throw new NoSuchElementException("Message is not within the target Folder"); 
        }
    }


    /**
     * Search a list of LIST responses for one containing information
     * for a particular mailbox name.
     *
     * @param responses The list of responses.
     * @param name      The desired mailbox name.
     *
     * @return The IMAPListResponse information for the requested name.
     */
    protected IMAPListResponse findListResponse(List responses, String name) {
        for (int i = 0; i < responses.size(); i++) {
            IMAPListResponse response = (IMAPListResponse)responses.get(i);
            if (response.mailboxName.equals(name)) {
                return response;
            }
        }
        return null;
    }
    
    
    /**
     * Protected class intended for subclass overrides.  For normal folders, 
     * the mailbox name is fullname.  For Namespace root folders, the mailbox
     * name is the prefix + separator.  
     * 
     * @return The string name to use as the mailbox name for exists() and issubscribed() 
     *         calls.
     */
    protected String getMailBoxName() {
        return fullname; 
    }
    
    /**
     * Handle an unsolicited response from the server.  Most unsolicited responses 
     * are replies to specific commands sent to the server.  The remainder must 
     * be handled by the Store or the Folder using the connection.  These are 
     * critical to handle, as events such as expunged messages will alter the 
     * sequence numbers of the live messages.  We need to keep things in sync.
     * 
     * @param response The UntaggedResponse to process.
     * 
     * @return true if we handled this response and no further handling is required.  false
     *         means this one wasn't one of ours.
     */
    public boolean handleResponse(IMAPUntaggedResponse response) {
        // "you've got mail".  The message count has been updated.  There 
        // are two posibilities.  Either there really are new messages, or 
        // this is an update following an expunge.  If there are new messages, 
        // we need to update the message cache and broadcast the change to 
        // any listeners.
        if (response.isKeyword("EXISTS")) {
            // we need to update our cache, and also retrieve the new messages and 
            // send them out in a broadcast update. 
            int oldCount = maxSequenceNumber; 
            maxSequenceNumber = ((IMAPSizeResponse)response).getSize(); 
            populateMessageCache();  
            // has the size grown?  We have to send the "you've got mail" announcement. 
            if (oldCount < maxSequenceNumber) {
                try {
                    Message[] messages = getMessages(oldCount + 1, maxSequenceNumber); 
                    notifyMessageAddedListeners(messages); 
                } catch (MessagingException e) {
                    // should never happen in this context 
                }
            }
            return true; 
        }
        // "you had mail".  A message was expunged from the server.  This MUST 
        // be processed immediately, as any subsequent expunge messages will 
        // shift the message numbers as a result of previous messages getting 
        // removed.  We need to keep our internal cache in sync with the server. 
        else if (response.isKeyword("EXPUNGE")) {
            int messageNumber = ((IMAPSizeResponse)response).getSize(); 
            try {
                Message message = expungeMessage(messageNumber); 

                // broadcast the message update. 
                notifyMessageRemovedListeners(false, new Message[] {message}); 
            } catch (MessagingException e) {
            }
            // we handled this one. 
            return true; 
        }
        // just an update of recently arrived stuff?  Just update the field. 
        else if (response.isKeyword("RECENT")) {
            recentMessages = ((IMAPSizeResponse)response).getSize();  
            return true; 
        }
        // The spec is not particularly clear what types of unsolicited 
        // FETCH response can be sent.  The only one that is specifically 
        // spelled out is flag updates.  If this is one of those, then 
        // handle it. 
        else if (response.isKeyword("FETCH")) {
            IMAPFetchResponse fetch = (IMAPFetchResponse)response;            
            IMAPFlags flags = (IMAPFlags)fetch.getDataItem(IMAPFetchDataItem.FLAGS); 
            // if this is a flags response, get the message and update 
            if (flags != null) {
                try {
                    // get the updated message and update the internal state. 
                    IMAPMessage message = (IMAPMessage)getMessage(fetch.sequenceNumber); 
                    // this shouldn't happen, but it might have been expunged too. 
                    if (message != null) {
                        message.updateMessageInformation(fetch); 
                    }
                    notifyMessageChangedListeners(MessageChangedEvent.FLAGS_CHANGED, message);
                } catch (MessagingException e) {
                }
                return true; 
            }
        }
        // this is a BYE response on our connection.  This forces us to close, but 
        // when we return the connection, the pool needs to get rid of it. 
        else if (response.isKeyword("BYE")) {
            // this is essentially a close event.  We need to clean everything up 
            // and make sure our connection is not returned to the general pool. 
            try {
                cleanupFolder(false, true); 
            } catch (MessagingException e) {
            }
            return true; 
        }
        
        // not a response the folder knows how to deal with. 
        return false; 
    }
    
// The following set of methods are extensions that exist in the Sun implementation.  They     
// match the Sun version in intent, but are not 100% compatible because the Sun implementation     
// uses com.sun.* class instances as opposed to the org.apache.geronimo.* classes.     
    
    
    
    /**
     *   Remove an entry from the access control list for this folder.
     * 
     * @param acl    The ACL element to remove.
     * 
     * @exception MessagingException
     */
    public synchronized void removeACL(ACL acl) throws MessagingException {
        // ask the store to kindly hook us up with a connection.
        IMAPConnection connection = getConnection(); 

        try {
            // the connection does the heavy lifting 
            connection.removeACLRights(fullname, acl); 
        } finally {
            releaseConnection(connection); 
        }
    }
    
    
    /**
     *   Add an entry to the access control list for this folder.
     * 
     * @param acl    The new ACL to add.
     */
    public synchronized void addACL(ACL acl) throws MessagingException {
        // ask the store to kindly hook us up with a connection.
        IMAPConnection connection = getConnection(); 

        try {
            // the connection does the heavy lifting 
            connection.setACLRights(fullname, acl); 
        } finally {
            releaseConnection(connection); 
        }
    }
    
    
    /**
     * Add Rights to a given ACL entry.
     * 
     * @param acl    The target ACL to update.
     * 
     * @exception MessagingException
     */
    public synchronized void addRights(ACL acl) throws MessagingException {
        // ask the store to kindly hook us up with a connection.
        IMAPConnection connection = getConnection(); 

        try {
            // the connection does the heavy lifting 
            connection.addACLRights(fullname, acl); 
        } finally {
            releaseConnection(connection); 
        }
    }
    
    
    /**
     * Remove ACL Rights from a folder.
     * 
     * @param acl    The ACL describing the Rights to remove.
     * 
     * @exception MessagingException
     */
    public synchronized void removeRights(ACL acl) throws MessagingException {
        // ask the store to kindly hook us up with a connection.
        IMAPConnection connection = getConnection(); 

        try {
            // the connection does the heavy lifting 
            connection.removeACLRights(fullname, acl); 
        } finally {
            releaseConnection(connection); 
        }
    }
    
    
    /**
     *   List the rights associated with a given name.
     * 
     * @param name   The user name for the Rights.
     * 
     * @return The set of Rights associated with the user name.
     * @exception MessagingException
     */
    public synchronized Rights[] listRights(String name) throws MessagingException {
        // ask the store to kindly hook us up with a connection.
        IMAPConnection connection = getConnection(); 

        try {
            // the connection does the heavy lifting 
            return connection.listACLRights(fullname, name); 
        } finally {
            releaseConnection(connection); 
        }
    }
    
    
    /**
     *   List the rights for the currently authenticated user.
     * 
     * @return The set of Rights for the current user.
     * @exception MessagingException
     */
    public synchronized Rights myRights() throws MessagingException {
        // ask the store to kindly hook us up with a connection.
        IMAPConnection connection = getConnection(); 

        try {
            // the connection does the heavy lifting 
            return connection.getMyRights(fullname); 
        } finally {
            releaseConnection(connection); 
        }
    }
    
    /**
     * Get the quota values assigned to the current folder.
     * 
     * @return The Quota information for the folder.
     * @exception MessagingException
     */
    public synchronized Quota[] getQuota() throws MessagingException {
        // ask the store to kindly hook us up with a connection.
        IMAPConnection connection = getConnection(); 

        try {
            // the connection does the heavy lifting 
            return connection.fetchQuotaRoot(fullname); 
        } finally {
            releaseConnection(connection); 
        }
    }
    
    /**
     * Set the quota value for a quota root
     * 
     * @param quota  The new quota information to set.
     * 
     * @exception MessagingException
     */
    public synchronized void setQuota(Quota quota) throws MessagingException {
        // ask the store to kindly hook us up with a connection.
        IMAPConnection connection = getConnection(); 

        try {
            // the connection does the heavy lifting 
            connection.setQuota(quota); 
        } finally {
            releaseConnection(connection); 
        }
    }
    
    /**
     * Get the set of attributes defined for the folder
     * as the set of capabilities returned when the folder 
     * was opened.
     * 
     * @return The set of attributes associated with the folder.
     * @exception MessagingException
     */
    public synchronized String[] getAttributes() throws MessagingException {
        // if we don't have the LIST command information for this folder yet, 
        // call exists() to force this to be updated so we can return. 
        if (listInfo == null) {
            // return a null reference if this is not valid. 
            if (!exists()) {
                return null; 
            }
        }
        // return a copy of the attributes array. 
        return (String[])listInfo.attributes.clone(); 
    }
}

