Package org.apache.geronimo.mail

Source Code of org.apache.geronimo.mail.AbstractFolder

/**
*
* Copyright 2003-2004 The Apache Software Foundation
*
*  Licensed 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.mail;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Store;
import javax.mail.URLName;

/**
* Apache implementation of a generic {@link Folder}. May be subclassed for optimisation for specific protocols.
* This stores messages using an internal {@link List}, and allows messages to be cached inside the folder.
* Note that the messages do not have to be present or fully loaded; it is possible that a message
* will only contain the message ID and be loaded dynamically on request.
* <p>
* Whilst it is possible for other implementations to override {@link Folder} directly, this provides common
* methods that allow for easier implementation. Subclasses should implement the abstract methods
* from {@link Folder} and the <code>doXxxx()</code> that this requires in order to facilitate creation
* of future folder types.
* @version $Rev: 46019 $ $Date: 2004-09-14 03:56:06 -0600 (Tue, 14 Sep 2004) $
*/
public abstract class AbstractFolder extends Folder {
    /**
     * Used for converting a list into a folder
     */
    private static final Message[] MESSAGE_ARRAY = new Message[0];
    /**
     * The list that holds the messages for this folder.
     * Note that due to a list being implemented, it is not possible to have (say) message 1 cached and message 3 cached, without
     * also caching message 2. If this is changed to provide a SortedSet based on Integer keys, this may be more efficient.
     */
    // TODO Investigate migration to a SortedSet. Implementations should not assume that this is a list.
    private List _messages = new LinkedList();
    /**
     * The name of this folder.
     */
    private URLName _name;
    /**
     * Create a new folder associated with the given {@link Store}
     * @param store the {@link Store} this folder is associated with
     * @param name the name of this folder
     */
    public AbstractFolder(Store store, URLName name) {
        super(store);
        _name = name;
    }

    /**
     * Runs through the array of messages and appends them onto the folder using {@link #add(Message)}.
     * @param messages the array of messages to add.
     */
    public void appendMessages(Message[] messages) throws MessagingException {
        for (int i = 0; i < messages.length; i++) {
            Message message = messages[i];
            _messages.add(message);
        }
    }

    /**
     * Closes the folder, and if <code>expunge</code>, then automatically expunges prior to closure.
     * Afterwards calls doClose() as a hook to the underlying implementation to do the real close operation.
     */
    public void close(boolean expunge) throws MessagingException {
        if (expunge) {
            expunge();
        }
        doClose();
    }

    /* (non-Javadoc)
     * @see javax.mail.Folder#delete(boolean)
     */
    public boolean delete(boolean recurse) throws MessagingException {
        _messages = new LinkedList();
        // TODO This is implemented badly; it doesn't delete the messages from the folder!
        for (int i = 0; i < _messages.size(); i++) {
            doDelete(i);
        }
        return true;
    }

    /**
     * Implemented by the provider, to close the folder. An expunge will already have
     * been performed if required.
     * @throws MessagingException if an error occurs during closure.
     */
    protected abstract void doClose() throws MessagingException;
    /**
     * Implemented by subclasses to actually delete a message from the store. This is then removed from the
     * folder's message cache.
     * @param id the message number to delete
     * @return the newly-created message from the store
     * @throws MessagingException in case of any error
     */
    protected abstract void doDelete(int id) throws MessagingException;

    /**
     * Implemented by subclasses to actually load a message from the store. This is then cached in
     * the itnernal folder.
     * Note that the message returned does not need to be fully loaded; it can be a placeholder with
     * the message id only and dynamically access the rest of the message when required.
     * @param id the message number to use
     * @return the newly-created message from the store
     * @throws MessagingException in case of any error
     */
    protected abstract Message doGetMessage(int id) throws MessagingException;

    /**
     * Implemented by subclasses to perform a rename operation. Called by renameTo(),
     * and if successful, the name is update.
     * @param newName the new name to use
     */
    protected abstract void doOpen(int newMode) throws MessagingException;
    /**
     * Implemented by subclasses to perform a rename operation. Called by renameTo(),
     * and if successful, the name is update.
     * @param newName the new name to use
     * @return true if the folder is renamed; false otherwise.
     */
    protected abstract boolean doRenameTo(Folder newName);

    /**
     * Renumber message with new ID after an expunge occurs.
     * Since the Message#setMessageNumber is protected, there cannot be an
     * implementation that provides it. However, subclasses that use
     * their own implementation of Message (e.g. POP3Message) can set up
     * the setMessageNumber to be protected, and thus available in the
     * local package. This method implementation is likely to look like:
     *
     * <pre>
     *   protected void doRenumberMessageTo(Message message, int id) throws MessagingException {
     *     ((POP3Message)message).setMessageNumber(id);
     *   }
     * </pre>
     *
     * Note that this cannot be done generically in the superclass since there is no way
     * of making the <code>setMessageNumber()</code> method visible to this class without
     * violating the JavaMail spec.
     * @param message the message to renumber
     * @param id the message id
     */
    protected abstract void doRenumberMessageTo(Message message, int id)
        throws MessagingException;

    /**
     * Runs through a list of messages, and removes them from the internal list
     * of messages. Calls
     */
    public Message[] expunge() throws MessagingException {
        Iterator it = _messages.iterator();
        List result = new LinkedList();
        while (it.hasNext()) {
            Message message = (Message) it.next();
            if (message.isSet(Flags.Flag.DELETED)) {
                it.remove();
                result.add(message);
            }
        }
        // run through and renumber the messages
        for (int i = 0; i < _messages.size(); i++) {
            Message message = (Message) _messages.get(i);
            doRenumberMessageTo(message, i);
            //            message.setMessageNumber(i);
        }
        return (Message[]) result.toArray(MESSAGE_ARRAY);
    }

    /**
     * Returns the full URLName of this folder
     * @return the full URLName of this folder
     */
    public String getFullName() {
        return _name.toString();
    }

    /* (non-Javadoc)
     * @see javax.mail.Folder#getMessage(int)
     */
    public Message getMessage(int id) throws MessagingException {
        // TODO Put in faulting to dynamically load message if not present
        return (Message) _messages.get(id);
    }

    /**
     * Returns just the name portion of the URLName
     */
    public String getName() {
        return _name.getFile();
    }

    /**
     * Uses '<code>/</code>' as the separator. This may be overriden by subclases, but is a sensible default.
     */
    public char getSeparator() throws MessagingException {
        return '/';
    }

    /**
     * Returns {@link HOLDS_MESSAGES}. Override if the server supports folders {@link HOLDS_FOLDERS}
     * instead/as well.
     */
    public int getType() throws MessagingException {
        return HOLDS_MESSAGES;
    }

    /* (non-Javadoc)
     * @see javax.mail.Folder#hasNewMessages()
     */
    public boolean hasNewMessages() throws MessagingException {
        // TODO Implement
        return false;
    }

    /* (non-Javadoc)
     * @see javax.mail.Folder#list(java.lang.String)
     */
    public Folder[] list(String pattern) throws MessagingException {
        return null;
    }

    /* (non-Javadoc)
     * @see javax.mail.Folder#open(int)
     */
    public void open(int newMode) throws MessagingException {
        doOpen(newMode);
        mode = newMode;
        // if the open works, then do the assignment; otherwise, leave as-is
    }

    /* (non-Javadoc)
     * @see javax.mail.Folder#renameTo(javax.mail.Folder)
     */
    public boolean renameTo(Folder newName) throws MessagingException {
        if (doRenameTo(newName)) {
            _name = ((AbstractFolder) newName)._name;
            return true;
        } else {
            return false;
        }
    }

}
TOP

Related Classes of org.apache.geronimo.mail.AbstractFolder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.