/*
 * 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.util.Arrays; // JDK 1.2
import java.io.OutputStream;
import javax.naming.ldap.Control;
import java.lang.reflect.Method;
import javax.net.SocketFactory;

/**
 * Represents identity information about an anonymous LDAP connection.
 * This base class contains the following information:
 * - protocol version number
 * - server's hostname (case-insensitive)
 * - server's port number
 * - prototype type (plain or ssl)
 * - controls to be sent with the LDAP bind request
 *
 * All other identity classes must be a subclass of ClientId.
 * Identity subclasses would add more distinguishing information, depending
 * on the type of authentication that the connection is to have.
 *
 * The equals() and hashCode() methods of this class and its subclasses are
 * important because they are used to determine whether two requests for
 * the same connection are identical, and thus whether the same connection
 * may be shared. This is especially important for authenticated connections
 * because a mistake would result in a serious security violation.
 *
 * @author Rosanna Lee
 */
class ClientId {
    final private int version;
    final private String hostname;
    final private int port;
    final private String protocol;
    final private Control[] bindCtls;
    final private OutputStream trace;
    final private String socketFactory;
    final private int myHash;
    final private int ctlHash;

    private SocketFactory factory = null;
    private Method sockComparator = null;
    private boolean isDefaultSockFactory = false;
    final public static boolean debug = false;

    ClientId(int version, String hostname, int port, String protocol,
            Control[] bindCtls, OutputStream trace, String socketFactory) {
        this.version = version;
        this.hostname = hostname.toLowerCase();  // ignore case
        this.port = port;
        this.protocol = protocol;
        this.bindCtls = (bindCtls != null ? (Control[]) bindCtls.clone() : null);
        this.trace = trace;
        //
        // Needed for custom socket factory pooling
        //
        this.socketFactory = socketFactory;
        if ((socketFactory != null) &&
             !socketFactory.equals(LdapCtx.DEFAULT_SSL_FACTORY)) {
            try {
                Class socketFactoryClass = Obj.helper.loadClass(socketFactory);
                Class objClass = Class.forName("java.lang.Object");
                this.sockComparator = socketFactoryClass.getMethod(
                                "compare", new Class[]{objClass, objClass});
                Method getDefault =
                    socketFactoryClass.getMethod("getDefault", new Class[]{});
                this.factory = (SocketFactory) getDefault.invoke(null, new Object[]{});
            } catch (Exception e) {
                // Ignore it here, the same exceptions are/will be handled by
                // LdapPoolManager and Connection classes.
                if (debug) {
                    System.out.println("ClientId received an exception");
                    e.printStackTrace();
                }
            }
        } else {
             isDefaultSockFactory = true;
        }

        // The SocketFactory field is not used in the myHash
        // computation as there is no right way to compute the hash code
        // for this field. There is no harm in skipping it from the hash
        // computation
        myHash = version + port
            + (trace != null ? trace.hashCode() : 0)
            + (this.hostname != null ? this.hostname.hashCode() : 0)
            + (protocol != null ? protocol.hashCode() : 0)
            + (ctlHash=hashCodeControls(bindCtls));
    }

    public boolean equals(Object obj) {
        if (!(obj instanceof ClientId)) {
            return false;
        }

        ClientId other = (ClientId)obj;

        return myHash == other.myHash
            && version == other.version
            && port == other.port
            && trace == other.trace
            && (hostname == other.hostname // null OK
                || (hostname != null && hostname.equals(other.hostname)))
            && (protocol == other.protocol // null OK
                || (protocol != null && protocol.equals(other.protocol)))
            && ctlHash == other.ctlHash
            && (equalsControls(bindCtls, other.bindCtls))
            && (equalsSockFactory(other));
    }

    public int hashCode() {
        return myHash;
    }

    private static int hashCodeControls(Control[] c) {
        if (c == null) {
            return 0;
        }

        int code = 0;
        for (int i = 0; i < c.length; i++) {
            code = code * 31 + c[i].getID().hashCode();
        }
        return code;
    }

    private static boolean equalsControls(Control[] a, Control[] b) {
        if (a == b) {
            return true;  // both null or same
        }
        if (a == null || b == null) {
            return false; // one is non-null
        }
        if (a.length != b.length) {
            return false;
        }

        for (int i = 0; i < a.length; i++) {
            if (!a[i].getID().equals(b[i].getID())
                || a[i].isCritical() != b[i].isCritical()
                || !Arrays.equals(a[i].getEncodedValue(),
                    b[i].getEncodedValue())) {
                return false;
            }
        }
        return true;
    }

    private boolean equalsSockFactory(ClientId other) {
        if (this.isDefaultSockFactory && other.isDefaultSockFactory) {
            return true;
        }
        else if (!other.isDefaultSockFactory) {
             return invokeComparator(other, this);
        } else {
             return invokeComparator(this, other);
        }
    }

    // delegate the comparison work to the SocketFactory class
    // as there is no enough information here, to do the comparison
    private boolean invokeComparator(ClientId c1, ClientId c2) {
        Object ret;
        try {
            ret = (c1.sockComparator).invoke(
                        c1.factory, c1.socketFactory, c2.socketFactory);
        } catch(Exception e) {
            if (debug) {
                System.out.println("ClientId received an exception");
                e.printStackTrace();
            }
            // Failed to invoke the comparator; flag unequality
            return false;
        }
        if (((Integer) ret) == 0) {
            return true;
        }
        return false;
    }

    private static String toStringControls(Control[] ctls) {
        if (ctls == null) {
            return "";
        }
        StringBuffer str = new StringBuffer();
        for (int i = 0; i < ctls.length; i++) {
            str.append(ctls[i].getID());
            str.append(' ');
        }
        return str.toString();
    }

    public String toString() {
        return (hostname + ":" + port + ":" +
            (protocol != null ? protocol : "") + ":" +
            toStringControls(bindCtls) + ":" +
            socketFactory);
    }
}
