/*
 * 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.pop3;
 
import java.io.PrintStream; 
import java.util.LinkedList;
import java.util.List;

import javax.mail.AuthenticationFailedException;
import javax.mail.Folder;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.URLName;

import org.apache.geronimo.javamail.store.pop3.connection.POP3Connection; 
import org.apache.geronimo.javamail.store.pop3.connection.POP3ConnectionPool; 
import org.apache.geronimo.javamail.util.ProtocolProperties;

/**
 * POP3 implementation of javax.mail.Store POP protocol spec is implemented in
 * org.apache.geronimo.javamail.store.pop3.POP3Connection
 * 
 * @version $Rev: 693530 $ $Date: 2008-09-09 13:57:23 -0400 (Tue, 09 Sep 2008) $
 */

public class POP3Store extends Store {
    protected static final int DEFAULT_POP3_PORT = 110;
    protected static final int DEFAULT_POP3_SSL_PORT = 995;
    
    
    // our accessor for protocol properties and the holder of 
    // protocol-specific information 
    protected ProtocolProperties props; 
    // our connection object    
    protected POP3ConnectionPool connectionPool; 
    // our session provided debug output stream.
    protected PrintStream debugStream;
    // the debug flag 
    protected boolean debug; 
    // the root folder 
    protected POP3RootFolder root; 
    // until we're connected, we're closed 
    boolean closedForBusiness = true; 
    protected LinkedList openFolders = new LinkedList(); 
    
    
    public POP3Store(Session session, URLName name) {
        this(session, name, "pop3", DEFAULT_POP3_PORT, false);
    }

    /**
     * Common constructor used by the POP3Store and POP3SSLStore classes
     * to do common initialization of defaults.
     *
     * @param session
     *            The host session instance.
     * @param name
     *            The URLName of the target.
     * @param protocol
     *            The protocol type ("pop3"). This helps us in
     *            retrieving protocol-specific session properties.
     * @param defaultPort
     *            The default port used by this protocol. For pop3, this will
     *            be 110. The default for pop3 with ssl is 995.
     * @param sslConnection
     *            Indicates whether an SSL connection should be used to initial
     *            contact the server. This is different from the STARTTLS
     *            support, which switches the connection to SSL after the
     *            initial startup.
     */
    protected POP3Store(Session session, URLName name, String protocol, int defaultPort, boolean sslConnection) {
        super(session, name);
        
        // create the protocol property holder.  This gives an abstraction over the different 
        // flavors of the protocol. 
        props = new ProtocolProperties(session, protocol, sslConnection, defaultPort); 

        // get our debug settings
        debugStream = session.getDebugOut();
        debug = session.getDebug(); 
        // the connection pool manages connections for the stores, folder, and message usage. 
        connectionPool = new POP3ConnectionPool(this, props); 
    }


    /**
     * Return a Folder object that represents the root of the namespace for the current user.
     *
     * Note that in some store configurations (such as IMAP4) the root folder might
     * not be the INBOX folder.
     *
     * @return the root Folder
     * @throws MessagingException if there was a problem accessing the store
     */
	public Folder getDefaultFolder() throws MessagingException {
		checkConnectionStatus();
        // if no root yet, create a root folder instance. 
        if (root == null) {
            return new POP3RootFolder(this);
        }
        return root;
	}

    /**
     * Return the Folder corresponding to the given name.
     * The folder might not physically exist; the {@link Folder#exists()} method can be used
     * to determine if it is real.
     * 
     * @param name   the name of the Folder to return
     * 
     * @return the corresponding folder
     * @throws MessagingException
     *                if there was a problem accessing the store
     */
	public Folder getFolder(String name) throws MessagingException {
        return getDefaultFolder().getFolder(name);
	}

    
    /**
     * Return the folder identified by the URLName; the URLName must refer to this Store.
     * Implementations may use the {@link URLName#getFile()} method to determined the folder name.
     * 
     * @param url
     * 
     * @return the corresponding folder
     * @throws MessagingException
     *                if there was a problem accessing the store
     */
	public Folder getFolder(URLName url) throws MessagingException {
        return getDefaultFolder().getFolder(url.getFile());
	}

    
    /**
     * @see javax.mail.Service#protocolConnect(java.lang.String, int,
     *      java.lang.String, java.lang.String)
     */
    protected synchronized boolean protocolConnect(String host, int port, String username, String password) throws MessagingException {
        
        if (debug) {
            debugOut("Connecting to server " + host + ":" + port + " for user " + username);
        }

        // the connection pool handles all of the details here. 
        if (connectionPool.protocolConnect(host, port, username, password)) 
        {
            // the store is now open 
            closedForBusiness = false; 
            return true; 
        }
        return false; 
    }
    
    
    /**
     * Get a connection for the store. 
     * 
     * @return The request connection object. 
     * @exception MessagingException
     */
    protected POP3Connection getConnection() throws MessagingException {
        return connectionPool.getConnection(); 
    }
    
    /**
     * Return a connection back to the connection pool after 
     * it has been used for a request. 
     * 
     * @param connection The return connection.
     * 
     * @exception MessagingException
     */
    protected void releaseConnection(POP3Connection connection) throws MessagingException {
        connectionPool.releaseConnection(connection); 
    }
    
    /**
     * Get a connection object for a folder to use. 
     * 
     * @param folder The requesting folder (always the inbox for POP3).
     * 
     * @return An active POP3Connection. 
     * @exception MessagingException
     */
    synchronized POP3Connection getFolderConnection(POP3Folder folder) throws MessagingException {
        POP3Connection connection = connectionPool.getConnection(); 
        openFolders.add(folder);
        return connection; 
    }
    
    /**
     * Release a connection object after a folder is 
     * finished with a request. 
     * 
     * @param folder     The requesting folder.
     * @param connection
     * 
     * @exception MessagingException
     */
    synchronized void releaseFolderConnection(POP3Folder folder, POP3Connection connection) throws MessagingException {
        openFolders.remove(folder); 
        // return this back to the pool 
        connectionPool.releaseConnection(connection); 
    }
    
    /**
     * Close all open folders.  We have a small problem here with a race condition.  There's no safe, single
     * synchronization point for us to block creation of new folders while we're closing.  So we make a copy of
     * the folders list, close all of those folders, and keep repeating until we're done.
     */
    protected void closeOpenFolders() {
        // we're no longer accepting additional opens.  Any folders that open after this point will get an
        // exception trying to get a connection.
        closedForBusiness = true;

        while (true) {
            List folders = null;

            // grab our lock, copy the open folders reference, and null this out.  Once we see a null
            // open folders ref, we're done closing.
            synchronized(connectionPool) {
                folders = openFolders;
                openFolders = new LinkedList();
            }

            // null folder, we're done
            if (folders.isEmpty()) {
                return;
            }
            // now close each of the open folders.
            for (int i = 0; i < folders.size(); i++) {
                POP3Folder folder = (POP3Folder)folders.get(i);
                try {
                    folder.close(false);
                } catch (MessagingException e) {
                }
            }
        }
    }
    

    /**
     * @see javax.mail.Service#isConnected()
     */
    public boolean isConnected() {
        // the connect() method of the super class checks here first.  If the connected flag 
        // is off, then it's too early for use to try to get a connection and verify we still 
        // have a live one.  
        if (!super.isConnected()) {
            return false; 
        }
        try {
            POP3Connection connection = getConnection(); 
            // a null connection likely means we had a failure establishing a 
            // new connection to the POP3 server.  
            if (connection == null) {
                return false; 
            }
            try {
                // make sure the server is really there 
                connection.pingServer(); 
                return true; 
            }
            finally {
                // return the connection to the pool when finished 
                if (connection != null) {
                    releaseConnection(connection); 
                }
            }
        } catch (MessagingException e) {
        }
        return false; 
    }

    /**
     * Close the store, and any open folders associated with the 
     * store. 
     * 
     * @exception MessagingException
     */
	public synchronized void close() throws MessagingException{
        // if already closed, nothing to do. 
        if (closedForBusiness) {
            return; 
        }
        
        // close the folders first, then shut down the Store. 
        closeOpenFolders();
        
        connectionPool.close(); 
        connectionPool = null; 

		// make sure we do the superclass close operation first so 
        // notification events get broadcast properly. 
		super.close();
	}

    /**
     * Check the status of our connection. 
     * 
     * @exception MessagingException
     */
    private void checkConnectionStatus() throws MessagingException {
        if (!this.isConnected()) {
            throw new MessagingException("Not connected ");
        }
    }

    /**
     * Internal debug output routine.
     *
     * @param value  The string value to output.
     */
    void debugOut(String message) {
        debugStream.println("POP3Store DEBUG: " + message);
    }

    /**
     * Internal debugging routine for reporting exceptions.
     *
     * @param message A message associated with the exception context.
     * @param e       The received exception.
     */
    void debugOut(String message, Throwable e) {
        debugOut("Received exception -> " + message);
        debugOut("Exception message -> " + e.getMessage());
        e.printStackTrace(debugStream);
    }
    
    /**
     * Finalizer to perform IMAPStore() cleanup when 
     * no longer in use. 
     * 
     * @exception Throwable
     */
    protected void finalize() throws Throwable {
        super.finalize(); 
        close(); 
    }
}
