/*
 * Copyright 2002-2005 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package com.sun.jndi.ldap;

import java.io.PrintStream;
import java.io.OutputStream;
import java.util.Hashtable;
import java.util.StringTokenizer;

import javax.naming.ldap.Control;
import javax.naming.NamingException;
import javax.naming.CommunicationException;
import java.security.AccessController;
import java.security.PrivilegedAction;

import com.sun.jndi.ldap.pool.PoolCleaner;
import com.sun.jndi.ldap.pool.Pool;

/**
 * Contains utilities for managing connection pools of LdapClient.
 * Contains method for
 * - checking whether attempted connection creation may be pooled
 * - creating a pooled connection
 * - closing idle connections.
 *
 * If a timeout period has been configured, then it will automatically
 * close and remove idle connections (those that have not been
 * used for the duration of the timeout period).
 *
 * @author Rosanna Lee
 */

public final class LdapPoolManager {
    private static final String DEBUG =
        "com.sun.jndi.ldap.connect.pool.debug";

    public static final boolean debug =
        "all".equalsIgnoreCase(getProperty(DEBUG, null));

    public static final boolean trace = debug ||
        "fine".equalsIgnoreCase(getProperty(DEBUG, null));

    // ---------- System properties for connection pooling

    // Authentication mechanisms of connections that may be pooled
    private static final String POOL_AUTH =
        "com.sun.jndi.ldap.connect.pool.authentication";

    // Protocol types of connections that may be pooled
    private static final String POOL_PROTOCOL =
        "com.sun.jndi.ldap.connect.pool.protocol";

    // Maximum number of identical connections per pool
    private static final String MAX_POOL_SIZE =
        "com.sun.jndi.ldap.connect.pool.maxsize";

    // Preferred number of identical connections per pool
    private static final String PREF_POOL_SIZE =
        "com.sun.jndi.ldap.connect.pool.prefsize";

    // Initial number of identical connections per pool
    private static final String INIT_POOL_SIZE =
        "com.sun.jndi.ldap.connect.pool.initsize";

    // Milliseconds to wait before closing idle connections
    private static final String POOL_TIMEOUT =
        "com.sun.jndi.ldap.connect.pool.timeout";

    // Properties for DIGEST
    private static final String SASL_CALLBACK =
        "java.naming.security.sasl.callback";

    // --------- Constants
    private static final int DEFAULT_MAX_POOL_SIZE = 0;
    private static final int DEFAULT_PREF_POOL_SIZE = 0;
    private static final int DEFAULT_INIT_POOL_SIZE = 1;
    private static final int DEFAULT_TIMEOUT = 0;    // no timeout
    private static final String DEFAULT_AUTH_MECHS = "none simple";
    private static final String DEFAULT_PROTOCOLS = "plain";

    private static final int NONE = 0;    // indices into pools
    private static final int SIMPLE = 1;
    private static final int DIGEST = 2;

    // --------- static fields
    private static final long idleTimeout;// ms to wait before closing idle conn
    private static final int maxSize;     // max num of identical conns/pool
    private static final int prefSize;    // preferred num of identical conns/pool
    private static final int initSize;    // initial num of identical conns/pool

    private static boolean supportPlainProtocol = false;
    private static boolean supportSslProtocol = false;

    // List of pools used for different auth types
    private static final Pool[] pools = new Pool[3];

    static {
        maxSize = getInteger(MAX_POOL_SIZE, DEFAULT_MAX_POOL_SIZE);

        prefSize = getInteger(PREF_POOL_SIZE, DEFAULT_PREF_POOL_SIZE);

        initSize = getInteger(INIT_POOL_SIZE, DEFAULT_INIT_POOL_SIZE);

        idleTimeout = getLong(POOL_TIMEOUT, DEFAULT_TIMEOUT);

        // Determine supported authentication mechanisms
        String str = getProperty(POOL_AUTH, DEFAULT_AUTH_MECHS);
        StringTokenizer parser = new StringTokenizer(str);
        int count = parser.countTokens();
        String mech;
        int p;
        for (int i = 0; i < count; i++) {
            mech = parser.nextToken().toLowerCase();
            if (mech.equals("anonymous")) {
                mech = "none";
            }

            p = findPool(mech);
            if (p >= 0 && pools[p] == null) {
                pools[p] = new Pool(initSize, prefSize, maxSize);
            }
        }

        // Determine supported protocols
        str= getProperty(POOL_PROTOCOL, DEFAULT_PROTOCOLS);
        parser = new StringTokenizer(str);
        count = parser.countTokens();
        String proto;
        for (int i = 0; i < count; i++) {
            proto = parser.nextToken();
            if ("plain".equalsIgnoreCase(proto)) {
                supportPlainProtocol = true;
            } else if ("ssl".equalsIgnoreCase(proto)) {
                supportSslProtocol = true;
            } else {
                // ignore
            }
        }

        if (idleTimeout > 0) {
            // Create cleaner to expire idle connections
            new PoolCleaner(idleTimeout, pools).start();
        }

        if (debug) {
            showStats(System.err);
        }
    }

    // Cannot instantiate one of these
    private LdapPoolManager() {
    }

    /**
     * Find the index of the pool for the specified mechanism. If not
     * one of "none", "simple", "DIGEST-MD5", or "GSSAPI",
     * return -1.
     * @param mech mechanism type
     */
    private static int findPool(String mech) {
        if ("none".equalsIgnoreCase(mech)) {
            return NONE;
        } else if ("simple".equalsIgnoreCase(mech)) {
            return SIMPLE;
        } else if ("digest-md5".equalsIgnoreCase(mech)) {
            return DIGEST;
        }
        return -1;
    }

    /**
     * Determines whether pooling is allowed given information on how
     * the connection will be used.
     *
     * Non-configurable rejections:
     * - nonstandard socketFactory has been specified: the pool manager
     *   cannot track input or parameters used by the socket factory and
     *   thus has no way of determining whether two connection requests
     *   are equivalent. Maybe in the future it might add a list of allowed
     *   socket factories to be configured
     * - trace enabled (except when debugging)
     * - for Digest authentication, if a callback handler has been specified:
     *  the pool manager cannot track input collected by the handler
     *  and thus has no way of determining whether two connection requests are
     *  equivalent. Maybe in the future it might add a list of allowed
     *  callback handlers.
     *
     * Configurable tests:
     * - Pooling for the requested protocol (plain or ssl) is supported
     * - Pooling for the requested authentication mechanism is supported
     *
     */
    static boolean isPoolingAllowed(String socketFactory, OutputStream trace,
        String authMech, String protocol, Hashtable env)
                throws NamingException {

        if (trace != null && !debug

                // Requesting plain protocol but it is not supported
                || (protocol == null && !supportPlainProtocol)

                // Requesting ssl protocol but it is not supported
                || ("ssl".equalsIgnoreCase(protocol) && !supportSslProtocol)) {

            d("Pooling disallowed due to tracing or unsupported pooling of protocol");
            return false;
        }
        // pooling of custom socket factory is possible only if the
        // socket factory interface implements java.util.comparator
        String COMPARATOR = "java.util.Comparator";
        boolean foundSockCmp = false;
        if ((socketFactory != null) &&
             !socketFactory.equals(LdapCtx.DEFAULT_SSL_FACTORY)) {
            try {
                Class socketFactoryClass = Obj.helper.loadClass(socketFactory);
                Class[] interfaces = socketFactoryClass.getInterfaces();
                for (int i = 0; i < interfaces.length; i++) {
                    if (interfaces[i].getCanonicalName().equals(COMPARATOR)) {
                        foundSockCmp = true;
                    }
                }
            } catch (Exception e) {
                CommunicationException ce =
                    new CommunicationException("Loading the socket factory");
                ce.setRootCause(e);
                throw ce;
            }
            if (!foundSockCmp) {
                return false;
            }
        }
        // Cannot use pooling if authMech is not a supported mechs
        // Cannot use pooling if authMech contains multiple mechs
        int p = findPool(authMech);
        if (p < 0 || pools[p] == null) {
            d("authmech not found: ", authMech);

            return false;
        }

        d("using authmech: ", authMech);

        switch (p) {
        case NONE:
        case SIMPLE:
            return true;

        case DIGEST:
            // Provider won't be able to determine connection identity
            // if an alternate callback handler is used
            return (env == null || env.get(SASL_CALLBACK) == null);
        }
        return false;
    }

    /**
     * Obtains a pooled connection that either already exists or is
     * newly created using the parameters supplied. If it is newly
     * created, it needs to go through the authentication checks to
     * determine whether an LDAP bind is necessary.
     *
     * Caller needs to invoke ldapClient.authenticateCalled() to
     * determine whether ldapClient.authenticate() needs to be invoked.
     * Caller has that responsibility because caller needs to deal
     * with the LDAP bind response, which might involve referrals,
     * response controls, errors, etc. This method is responsible only
     * for establishing the connection.
     *
     * @return an LdapClient that is pooled.
     */
    static LdapClient getLdapClient(String host, int port, String socketFactory,
        int connTimeout, int readTimeout, OutputStream trace, int version,
        String authMech, Control[] ctls, String protocol, String user,
        Object passwd, Hashtable env) throws NamingException {

        // Create base identity for LdapClient
        ClientId id = null;
        Pool pool;

        int p = findPool(authMech);
        if (p < 0 || (pool=pools[p]) == null) {
            throw new IllegalArgumentException(
                "Attempting to use pooling for an unsupported mechanism: " +
                authMech);
        }
        switch (p) {
        case NONE:
            id = new ClientId(version, host, port, protocol,
                        ctls, trace, socketFactory);
            break;

        case SIMPLE:
            // Add identity information used in simple authentication
            id = new SimpleClientId(version, host, port, protocol,
                ctls, trace, socketFactory, user, passwd);
            break;

        case DIGEST:
            // Add user/passwd/realm/authzid/qop/strength/maxbuf/mutual/policy*
            id = new DigestClientId(version, host, port, protocol,
                ctls, trace, socketFactory, user, passwd, env);
            break;
        }

        return (LdapClient) pool.getPooledConnection(id, connTimeout,
            new LdapClientFactory(host, port, socketFactory, connTimeout,
                                readTimeout, trace));
    }

    public static void showStats(PrintStream out) {
        out.println("***** start *****");
        out.println("idle timeout: " + idleTimeout);
        out.println("maximum pool size: " + maxSize);
        out.println("preferred pool size: " + prefSize);
        out.println("initial pool size: " + initSize);
        out.println("protocol types: " + (supportPlainProtocol ? "plain " : "") +
            (supportSslProtocol ? "ssl" : ""));
        out.println("authentication types: " +
            (pools[NONE] != null ? "none " : "") +
            (pools[SIMPLE] != null ? "simple " : "") +
            (pools[DIGEST] != null ? "DIGEST-MD5 " : ""));

        for (int i = 0; i < pools.length; i++) {
            if (pools[i] != null) {
                out.println(
                    (i == NONE ? "anonymous pools" :
                        i == SIMPLE ? "simple auth pools" :
                        i == DIGEST ? "digest pools" : "")
                            + ":");
                pools[i].showStats(out);
            }
        }
        out.println("***** end *****");
    }

    /**
     * Closes idle connections idle since specified time.
     *
     * @param threshold Close connections idle since this time, as
     * specified in milliseconds since "the epoch".
     * @see java.util.Date
     */
    public static void expire(long threshold) {
        for (int i = 0; i < pools.length; i++) {
            if (pools[i] != null) {
                pools[i].expire(threshold);
            }
        }
    }

    private static void d(String msg) {
        if (debug) {
            System.err.println("LdapPoolManager: " + msg);
        }
    }

    private static void d(String msg, String o) {
        if (debug) {
            System.err.println("LdapPoolManager: " + msg + o);
        }
    }

    private static final String getProperty(final String propName,
        final String defVal) {
        return (String) AccessController.doPrivileged(
            new PrivilegedAction() {
            public Object run() {
                try {
                    return System.getProperty(propName, defVal);
                } catch (SecurityException e) {
                    return defVal;
                }
            }
        });
    }

    private static final int getInteger(final String propName,
        final int defVal) {
        Integer val = (Integer) AccessController.doPrivileged(
            new PrivilegedAction() {
            public Object run() {
                try {
                    return Integer.getInteger(propName, defVal);
                } catch (SecurityException e) {
                    return new Integer(defVal);
                }
            }
        });
        return val.intValue();
    }

    private static final long getLong(final String propName,
        final long defVal) {
        Long val = (Long) AccessController.doPrivileged(
            new PrivilegedAction() {
            public Object run() {
                try {
                    return Long.getLong(propName, defVal);
                } catch (SecurityException e) {
                    return new Long(defVal);
                }
            }
        });
        return val.longValue();
    }
}
