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

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

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import javax.mail.MessagingException; 
import javax.mail.Session;
import javax.mail.Store;

import javax.mail.StoreClosedException;

import org.apache.geronimo.javamail.store.imap.IMAPStore; 
import org.apache.geronimo.javamail.util.ProtocolProperties; 

public class IMAPConnectionPool {

    protected static final String MAIL_PORT = "port";
    protected static final String MAIL_POOL_SIZE = "connectionpoolsize";
    protected static final String MAIL_POOL_TIMEOUT = "connectionpooltimeout";
    protected static final String MAIL_SEPARATE_STORE_CONNECTION = "separatestoreconnection";
    
    protected static final String MAIL_SASL_REALM = "sasl.realm"; 
    protected static final String MAIL_AUTHORIZATIONID = "sasl.authorizationid"; 

    // 45 seconds, by default.
    protected static final int DEFAULT_POOL_TIMEOUT = 45000;
    protected static final String DEFAULT_MAIL_HOST = "localhost";
    
    protected static final int MAX_CONNECTION_RETRIES = 3; 
    protected static final int MAX_POOL_WAIT = 500; 


    // Our hosting Store instance
    protected IMAPStore store;
    // our Protocol abstraction 
    protected ProtocolProperties props; 
    // our list of created connections
    protected List poolConnections = new ArrayList();
    // our list of available connections 
    protected List availableConnections = new ArrayList();
    
    // the dedicated Store connection (if we're configured that way)
    protected IMAPConnection storeConnection = null;
    
    // our dedicated Store connection attribute
    protected boolean dedicatedStoreConnection;
    // the size of our connection pool (by default, we only keep a single connection in the pool)
    protected int poolSize = 1;
    // the connection timeout property
    protected long poolTimeout;
    // our debug flag
    protected boolean debug;

    // the target host
    protected String host;
    // the target server port.
    protected int port;
    // the username we connect with
    protected String username;
    // the authentication password.
    protected String password;
    // the SASL realm name 
    protected String realm; 
    // the authorization id.  With IMAP, it's possible to 
    // log on with another's authorization. 
    protected String authid; 
    // Turned on when the store is closed for business. 
    protected boolean closed = false; 
    // the connection capabilities map
    protected Map capabilities; 

    /**
     * Create a connection pool associated with a give IMAPStore instance.  The
     * connection pool manages handing out connections for both the Store and
     * Folder and Message usage.
     * 
     * Depending on the session properties, the Store may be given a dedicated
     * connection, or will share connections with the Folders.  Connections may
     * be requested from either the Store or Folders.  Messages must request
     * their connections from their hosting Folder, and only one connection is
     * allowed per folder.
     * 
     * @param store  The Store we're creating the pool for.
     * @param props  The property bundle that defines protocol properties
     *               that alter the connection behavior.
     */
    public IMAPConnectionPool(IMAPStore store, ProtocolProperties props) {
        this.store = store;
        this.props = props; 

        // get the pool size.  By default, we just use a single connection that's 
        // shared among Store and all of the Folders.  Since most apps that use 
        // javamail tend to be single-threaded, this generally poses no great hardship. 
        poolSize = props.getIntProperty(MAIL_POOL_SIZE, 1);
        // get the timeout property.  Default is 45 seconds.
        poolTimeout = props.getIntProperty(MAIL_POOL_TIMEOUT, DEFAULT_POOL_TIMEOUT);
        // we can create a dedicated connection over and above the pool set that's 
        // reserved for the Store instance to use. 
        dedicatedStoreConnection = props.getBooleanProperty(MAIL_SEPARATE_STORE_CONNECTION, false);
        // if we have a dedicated pool connection, we allocated that from the pool.  Add this to 
        // the total pool size so we don't find ourselves stuck if the pool size is 1. 
        if (dedicatedStoreConnection) {
            poolSize++; 
        }
    }


    /**
     * Manage the initial connection to the IMAP server.  This is the first 
     * point where we obtain the information needed to make an actual server 
     * connection.  Like the Store protocolConnect method, we return false 
     * if there's any sort of authentication difficulties. 
     * 
     * @param host     The host of the IMAP server.
     * @param port     The IMAP server connection port.
     * @param user     The connection user name.
     * @param password The connection password.
     * 
     * @return True if we were able to connect and authenticate correctly. 
     * @exception MessagingException
     */
    public synchronized boolean protocolConnect(String host, int port, String username, String password) throws MessagingException {
        // NOTE:  We don't check for the username/password being null at this point.  It's possible that 
        // the server will send back a PREAUTH response, which means we don't need to go through login 
        // processing.  We'll need to check the capabilities response after we make the connection to decide 
        // if logging in is necesssary. 
        
        // save this for subsequent connections.  All pool connections will use this info.
        // if the port is defaulted, then see if we have something configured in the session.
        // if not configured, we just use the default default.
        if (port == -1) {
            // check for a property and fall back on the default if it's not set.
            port = props.getIntProperty(MAIL_PORT, props.getDefaultPort());
            // it's possible that -1 might have been explicitly set, so one last check. 
            if (port == -1) {
                port = props.getDefaultPort(); 
            }
        }
    	
    	// Before we do anything, let's make sure that we succesfully received a host
    	if ( host == null ) {
    		host = DEFAULT_MAIL_HOST;
    	}
        
        this.host = host;
        this.port = port;
        this.username = username;
        this.password = password;
        
        // make sure we have the realm information 
        realm = props.getProperty(MAIL_SASL_REALM); 
        // get an authzid value, if we have one.  The default is to use the username.
        authid = props.getProperty(MAIL_AUTHORIZATIONID, username);

        // go create a connection and just add it to the pool.  If there is an authenticaton error, 
        // return the connect failure, and we may end up trying again. 
        IMAPConnection connection = createPoolConnection(); 
        if (connection == null) {
            return false; 
        }
        // save the capabilities map from the first connection. 
        capabilities = connection.getCapabilities(); 
        // if we're using a dedicated store connection, remove this from the pool and
        // reserve it for the store.
        if (dedicatedStoreConnection)  
        {  
            storeConnection = connection;
            // make sure this is hooked up to the store. 
            connection.addResponseHandler(store); 
        }
        else {
            // just put this back in the pool.  It's ready for anybody to use now. 
            synchronized(this) {
                availableConnections.add(connection); 
            }
        }
        // we're connection, authenticated, and ready to go. 
        return true; 
    }

    /**
     * Creates an authenticated pool connection and adds it to
     * the connection pool.  If there is an existing connection
     * already in the pool, this returns without creating a new
     * connection.
     *
     * @exception MessagingException
     */
    protected IMAPConnection createPoolConnection() throws MessagingException {
        IMAPConnection connection = new IMAPConnection(props, this);
        if (!connection.protocolConnect(host, port, authid, realm, username, password)) {
            // we only add live connections to the pool.  Sever the connections and 
            // allow it to go free. 
            connection.closeServerConnection(); 
            return null; 
        }
        
        // add this to the master list.  We do NOT add this to the 
        // available queue because we're handing this out. 
        synchronized(this) {
            // uh oh, we closed up shop while we were doing this...clean it up a 
            // get out of here 
            if (closed) {
                connection.close(); 
                throw new StoreClosedException(store, "No Store connections available"); 
            }
            
            poolConnections.add(connection);
        }
        // return that connection 
        return connection; 
    }


    /**
     * Get a connection from the pool.  We try to retrieve a live
     * connection, but we test the connection's liveness before
     * returning one.  If we don't have a viable connection in
     * the pool, we'll create a new one.  The returned connection
     * will be in the authenticated state already.
     *
     * @return An IMAPConnection object that is connected to the server.
     */
    protected IMAPConnection getConnection() throws MessagingException {
        int retryCount = 0; 
        
        // To keep us from falling into a futile failure loop, we'll only allow 
        // a set number of connection failures. 
        while (retryCount < MAX_CONNECTION_RETRIES) {
            // first try for an already created one.  If this returns 
            // null, then we'll probably have to make a new one. 
            IMAPConnection connection = getPoolConnection(); 
            // cool, we got one, the hard part is done.  
            if (connection != null) {
                return connection; 
            }
            // ok, create a new one.  This *should* work, but the server might 
            // have gone down, or other problem may occur. If we have a problem, 
            // retry the entire process...but only for a bit.  No sense 
            // being stubborn about it. 
            connection = createPoolConnection(); 
            if (connection != null) {
                return connection; 
            }
            // step the retry count 
            retryCount++; 
        }
        
        throw new MessagingException("Unable to get connection to IMAP server"); 
    }
    
    /**
     * Obtain a connection from the existing connection pool.  If none are 
     * available, and we've reached the connection pool limit, we'll wait for 
     * some other thread to return one.  It generally doesn't take too long, as 
     * they're usually only held for the time required to execute a single 
     * command.   If we're not at the pool limit, return null, which will signal 
     * the caller to go ahead and create a new connection outside of the 
     * lock. 
     * 
     * @return Either an active connection instance, or null if the caller should go 
     *         ahead and try to create a new connection.
     * @exception MessagingException
     */
    protected synchronized IMAPConnection getPoolConnection() throws MessagingException {
        // if the pool is closed, we can't process this 
        if (closed) {
            throw new StoreClosedException(store, "No Store connections available"); 
        }
        
        // we'll retry this a few times if the connection pool is full, but 
        // after that, we'll just create a new connection. 
        for (int i = 0; i < MAX_CONNECTION_RETRIES; i++) {
            Iterator it = availableConnections.iterator(); 
            while (it.hasNext()) {
                IMAPConnection connection = (IMAPConnection)it.next(); 
                // live or dead, we're going to remove this from the 
                // available list. 
                it.remove(); 
                if (connection.isAlive(poolTimeout)) {
                    // return the connection to the requestor 
                    return connection; 
                }
                else {
                    // remove this from the pool...it's toast. 
                    poolConnections.remove(connection); 
                    // make sure this cleans up after itself. 
                    connection.closeServerConnection(); 
                }
            }

            // we've not found something usable in the pool.  Now see if 
            // we're allowed to add another connection, or must just wait for 
            // someone else to return one. 

            if (poolConnections.size() >= poolSize) {
                // check to see if we've been told to shutdown before waiting
                if (closed) {
                    throw new StoreClosedException(store, "No Store connections available"); 
                }
                // we need to wait for somebody to return a connection 
                // once woken up, we'll spin around and try to snag one from 
                // the pool again.
                try {
                    wait(MAX_POOL_WAIT);
                } catch (InterruptedException e) {
                }
                
                // check to see if we've been told to shutdown while we waited
                if (closed) {
                    throw new StoreClosedException(store, "No Store connections available"); 
                }
            }
            else {
                // exit out and create a new connection.  Since 
                // we're going to be outside the synchronized block, it's possible 
                // we'll go over our pool limit.  We'll take care of that when connections start 
                // getting returned. 
                return null; 
            }
        }
        // we've hit the maximum number of retries...just create a new connection. 
        return null; 
    }
    
    /**
     * Return a connection to the connection pool.
     * 
     * @param connection The connection getting returned.
     * 
     * @exception MessagingException
     */
    protected void returnPoolConnection(IMAPConnection connection) throws MessagingException
    {
        synchronized(this) {
            // If we're still within the bounds of our connection pool, 
            // just add this to the active list and send out a notification 
            // in case somebody else is waiting for the connection. 
            if (availableConnections.size() < poolSize) {
                availableConnections.add(connection); 
                notify(); 
                return; 
            }
            // remove this from the connection pool...we have too many. 
            poolConnections.remove(connection); 
        }
        // the additional cleanup occurs outside the synchronized block 
        connection.close(); 
    }
    
    /**
     * Release a closed connection.
     * 
     * @param connection The connection getting released.
     * 
     * @exception MessagingException
     */
    protected void releasePoolConnection(IMAPConnection connection) throws MessagingException
    {
        synchronized(this) {
            // remove this from the connection pool...it's no longer usable. 
            poolConnections.remove(connection); 
        }
        // the additional cleanup occurs outside the synchronized block 
        connection.close(); 
    }


    /**
     * Get a connection for the Store.  This will be either a
     * dedicated connection object, or one from the pool, depending
     * on the mail.imap.separatestoreconnection property.
     *
     * @return An authenticated connection object.
     */
    public synchronized IMAPConnection getStoreConnection() throws MessagingException {  
        if (closed) {
            throw new StoreClosedException(store, "No Store connections available"); 
        }
        // if we have a dedicated connection created, return it.
        if (storeConnection != null) {
            return storeConnection;
        }
        else {
            IMAPConnection connection = getConnection();
            // add the store as a response handler while it has it. 
            connection.addResponseHandler(store); 
            return connection; 
        }
    }


    /**
     * Return the Store connection to the connection pool.  If we have a dedicated
     * store connection, this is simple.  Otherwise, the connection goes back 
     * into the general connection pool.
     * 
     * @param connection The connection getting returned.
     */
    public synchronized void releaseStoreConnection(IMAPConnection connection) throws MessagingException {
        // have a server disconnect situation?
        if (connection.isClosed()) {
            // we no longer have a dedicated store connection.  
            // we need to return to the pool from now on. 
            storeConnection = null; 
            // throw this away. 
            releasePoolConnection(connection); 
        }
        else {
            // if we have a dedicated connection, nothing to do really.  Otherwise, 
            // return this connection to the pool. 
            if (storeConnection == null) {
                // unhook the store from the connection. 
                connection.removeResponseHandler(store); 
                returnPoolConnection(connection); 
            }
        }
    }


    /**
     * Get a connection for Folder.  
     *
     * @return An authenticated connection object.
     */
    public IMAPConnection getFolderConnection() throws MessagingException {  
        // just get a connection from the pool 
        return getConnection(); 
    }


    /**
     * Return a Folder connection to the connection pool.  
     * 
     * @param connection The connection getting returned.
     */
    public void releaseFolderConnection(IMAPConnection connection) throws MessagingException {
        // potentially, the server may have decided to shut us down.  
        // In that case, the connection is no longer usable, so we need 
        // to remove it from the list of available ones. 
        if (!connection.isClosed()) {
            // back into the pool with yee, matey....arrggghhh
            returnPoolConnection(connection); 
        }
        else {
            // can't return this one to the pool.  It's been stomped on 
            releasePoolConnection(connection); 
        }
    }
    
    
    /**
     * Close the entire connection pool. 
     * 
     * @exception MessagingException
     */
    public synchronized void close() throws MessagingException {
        // first close each of the connections.  This also closes the 
        // store connection. 
        for (int i = 0; i < poolConnections.size(); i++) {
            IMAPConnection connection = (IMAPConnection)poolConnections.get(i);
            connection.close(); 
        }
        // clear the pool 
        poolConnections.clear(); 
        availableConnections.clear(); 
        storeConnection = null; 
        // turn out the lights, hang the closed sign on the wall. 
        closed = true; 
    }


    /**
     * Flush any connections from the pool that have not been used
     * for at least the connection pool timeout interval.
     */
    protected synchronized void closeStaleConnections() {
        Iterator i = poolConnections.iterator();

        while (i.hasNext()) {
            IMAPConnection connection = (IMAPConnection)i.next();
            // if this connection is a stale one, remove it from the pool
            // and close it out.
            if (connection.isStale(poolTimeout)) {
                i.remove();
                try {
                    connection.close();
                } catch (MessagingException e) {
                    // ignored.  we're just closing connections that are probably timed out anyway, so errors
                    // on those shouldn't have an effect on the real operation we're dealing with.
                }
            }
        }
    }


    /**
     * Return a connection back to the connection pool.  If we're not
     * over our limit, the connection is kept around.  Otherwise, it's
     * given a nice burial.
     *
     * @param connection The returned connection.
     */
    protected synchronized void releaseConnection(IMAPConnection connection) {
        // before adding this to the pool, close any stale connections we may
        // have.  The connection we're adding is quite likely to be a fresh one,
        // so we should cache that one if we can.
        closeStaleConnections();
        // still over the limit?
        if (poolConnections.size() + 1 > poolSize) {
            try {
                // close this out and forget we ever saw it.
                connection.close();
            } catch (MessagingException e) {
                // ignore....this is a non-critical problem if this fails now.
            }
        }
        else {
            // listen to alerts on this connection, and put it back in the pool.
            poolConnections.add(connection);
        }
    }

    /**
     * Cleanup time.  Sever and cleanup all of the pool connection
     * objects, including the special Store connection, if we have one.
     */
    protected synchronized void freeAllConnections() {
        for (int i = 0; i < poolConnections.size(); i++) {
            IMAPConnection connection = (IMAPConnection)poolConnections.get(i);
            try {
                // close this out and forget we ever saw it.
                connection.close();
            } catch (MessagingException e) {
                // ignore....this is a non-critical problem if this fails now.
            }
        }
        // everybody, out of the pool!
        poolConnections.clear();

        // don't forget the special store connection, if we have one.
        if (storeConnection != null) {
            try {
                // close this out and forget we ever saw it.
                storeConnection.close();
            } catch (MessagingException e) {
                // ignore....this is a non-critical problem if this fails now.
            }
            storeConnection = null;
        }
    }
    
    
    /**
     * Test if this connection has a given capability. 
     * 
     * @param capability The capability name.
     * 
     * @return true if this capability is in the list, false for a mismatch. 
     */
    public boolean hasCapability(String capability) {
        if (capabilities == null) {
            return false; 
        }
        return capabilities.containsKey(capability); 
    }
}


