/*
 * Copyright 2000-2006 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 sun.security.jgss;

import org.ietf.jgss.*;
import sun.security.jgss.spi.*;
import java.util.*;

public class GSSCredentialImpl implements GSSCredential {

    private GSSManagerImpl gssManager = null;
    private boolean destroyed = false;

    /*
     * We store all elements in a hashtable, using <oid, usage> as the
     * key. This makes it easy to locate the specific kind of credential we
     * need. The implementation needs to be optimized for the case where
     * there is just one element (tempCred).
     */
    private Hashtable<SearchKey, GSSCredentialSpi> hashtable = null;

    // XXX Optimization for single mech usage
    private GSSCredentialSpi tempCred = null;

    GSSCredentialImpl(GSSManagerImpl gssManager, int usage)
        throws GSSException {
        this(gssManager, null, GSSCredential.DEFAULT_LIFETIME,
             (Oid[]) null, usage);
    }

    GSSCredentialImpl(GSSManagerImpl gssManager, GSSName name,
                             int lifetime, Oid mech, int usage)
        throws GSSException {
        if (mech == null) mech = ProviderList.DEFAULT_MECH_OID;

        init(gssManager);
        add(name, lifetime, lifetime, mech, usage);
    }

    GSSCredentialImpl(GSSManagerImpl gssManager, GSSName name,
                      int lifetime, Oid mechs[], int usage)
        throws GSSException {
        init(gssManager);
        boolean defaultList = false;
        if (mechs == null) {
            mechs = gssManager.getMechs();
            defaultList = true;
        }

        for (int i = 0; i < mechs.length; i++) {
            try {
                add(name, lifetime, lifetime, mechs[i], usage);
            } catch (GSSException e) {
                if (defaultList) {
                    // Try the next mechanism
                    GSSUtil.debug("Ignore " + e + " while acquring cred for "
                        + mechs[i]);
                    //e.printStackTrace();
                } else throw e; // else try the next mechanism
            }
        }
        if ((hashtable.size() == 0) || (usage != getUsage()))
            throw new GSSException(GSSException.NO_CRED);
    }

    public GSSCredentialImpl(GSSManagerImpl gssManager,
                      GSSCredentialSpi mechElement) throws GSSException {

        init(gssManager);
        int usage = GSSCredential.ACCEPT_ONLY;
        if (mechElement.isInitiatorCredential()) {
            if (mechElement.isAcceptorCredential()) {
                usage = GSSCredential.INITIATE_AND_ACCEPT;
            } else {
                usage = GSSCredential.INITIATE_ONLY;
            }
        }
        SearchKey key = new SearchKey(mechElement.getMechanism(),
                                        usage);
        tempCred = mechElement;
        hashtable.put(key, tempCred);
    }

    void init(GSSManagerImpl gssManager) {
        this.gssManager = gssManager;
        hashtable = new Hashtable<SearchKey, GSSCredentialSpi>(
                                                gssManager.getMechs().length);
    }

    public void dispose() throws GSSException {
        if (!destroyed) {
            GSSCredentialSpi element;
            Enumeration<GSSCredentialSpi> values = hashtable.elements();
            while (values.hasMoreElements()) {
                element = values.nextElement();
                element.dispose();
            }
            destroyed = true;
        }
    }

    public GSSName getName() throws GSSException {
        if (destroyed) {
            throw new IllegalStateException("This credential is " +
                                        "no longer valid");
        }
        return GSSNameImpl.wrapElement(gssManager, tempCred.getName());
    }

    public GSSName getName(Oid mech) throws GSSException {

        if (destroyed) {
            throw new IllegalStateException("This credential is " +
                                        "no longer valid");
        }

        SearchKey key = null;
        GSSCredentialSpi element = null;

        if (mech == null) mech = ProviderList.DEFAULT_MECH_OID;

        key = new SearchKey(mech, GSSCredential.INITIATE_ONLY);
        element = hashtable.get(key);

        if (element == null) {
            key = new SearchKey(mech, GSSCredential.ACCEPT_ONLY);
            element = hashtable.get(key);
        }

        if (element == null) {
            key = new SearchKey(mech, GSSCredential.INITIATE_AND_ACCEPT);
            element = hashtable.get(key);
        }

        if (element == null) {
            throw new GSSExceptionImpl(GSSException.BAD_MECH, mech);
        }

        return GSSNameImpl.wrapElement(gssManager, element.getName());

    }

    /**
     * Returns the remaining lifetime of this credential. The remaining
     * lifetime is defined as the minimum lifetime, either for initiate or
     * for accept, across all elements contained in it. Not terribly
     * useful, but required by GSS-API.
     */
    public int getRemainingLifetime() throws GSSException {

        if (destroyed) {
            throw new IllegalStateException("This credential is " +
                                        "no longer valid");
        }

        SearchKey tempKey;
        GSSCredentialSpi tempCred;
        int tempLife = 0, tempInitLife = 0, tempAcceptLife = 0;
        int min = INDEFINITE_LIFETIME;

        for (Enumeration<SearchKey> e = hashtable.keys();
                                        e.hasMoreElements(); ) {
            tempKey = e.nextElement();
            tempCred = hashtable.get(tempKey);
            if (tempKey.getUsage() == INITIATE_ONLY)
                tempLife = tempCred.getInitLifetime();
            else if (tempKey.getUsage() == ACCEPT_ONLY)
                tempLife = tempCred.getAcceptLifetime();
            else {
                tempInitLife = tempCred.getInitLifetime();
                tempAcceptLife = tempCred.getAcceptLifetime();
                tempLife = (tempInitLife < tempAcceptLife ?
                            tempInitLife:
                            tempAcceptLife);
            }
            if (min > tempLife)
                min = tempLife;
        }

        return min;
    }

    public int getRemainingInitLifetime(Oid mech) throws GSSException {

        if (destroyed) {
            throw new IllegalStateException("This credential is " +
                                        "no longer valid");
        }

        GSSCredentialSpi element = null;
        SearchKey key = null;
        boolean found = false;
        int max = 0;

        if (mech == null) mech = ProviderList.DEFAULT_MECH_OID;

        key = new SearchKey(mech, GSSCredential.INITIATE_ONLY);
        element = hashtable.get(key);

        if (element != null) {
            found = true;
            if (max < element.getInitLifetime())
                max = element.getInitLifetime();
        }

        key = new SearchKey(mech, GSSCredential.INITIATE_AND_ACCEPT);
        element = hashtable.get(key);

        if (element != null) {
            found = true;
            if (max < element.getInitLifetime())
                max = element.getInitLifetime();
        }

        if (!found) {
            throw new GSSExceptionImpl(GSSException.BAD_MECH, mech);
        }

        return max;

    }

    public int getRemainingAcceptLifetime(Oid mech) throws GSSException {

        if (destroyed) {
            throw new IllegalStateException("This credential is " +
                                        "no longer valid");
        }

        GSSCredentialSpi element = null;
        SearchKey key = null;
        boolean found = false;
        int max = 0;

        if (mech == null) mech = ProviderList.DEFAULT_MECH_OID;

        key = new SearchKey(mech, GSSCredential.ACCEPT_ONLY);
        element = hashtable.get(key);

        if (element != null) {
            found = true;
            if (max < element.getAcceptLifetime())
                max = element.getAcceptLifetime();
        }

        key = new SearchKey(mech, GSSCredential.INITIATE_AND_ACCEPT);
        element = hashtable.get(key);

        if (element != null) {
            found = true;
            if (max < element.getAcceptLifetime())
                max = element.getAcceptLifetime();
        }

        if (!found) {
            throw new GSSExceptionImpl(GSSException.BAD_MECH, mech);
        }

        return max;

    }

    /**
     * Returns the usage mode for this credential. Returns
     * INITIATE_AND_ACCEPT if any one element contained in it supports
     * INITIATE_AND_ACCEPT or if two different elements exist where one
     * support INITIATE_ONLY and the other supports ACCEPT_ONLY.
     */
    public int getUsage() throws GSSException {

        if (destroyed) {
            throw new IllegalStateException("This credential is " +
                                        "no longer valid");
        }

        SearchKey tempKey;
        boolean initiate = false;
        boolean accept = false;

        for (Enumeration<SearchKey> e = hashtable.keys();
                                        e.hasMoreElements(); ) {
            tempKey = e.nextElement();
            if (tempKey.getUsage() == INITIATE_ONLY)
                initiate = true;
            else if (tempKey.getUsage() == ACCEPT_ONLY)
                accept = true;
            else
                return INITIATE_AND_ACCEPT;
        }
        if (initiate) {
            if (accept)
                return INITIATE_AND_ACCEPT;
            else
                return INITIATE_ONLY;
        } else
            return ACCEPT_ONLY;
    }

    public int getUsage(Oid mech) throws GSSException {

        if (destroyed) {
            throw new IllegalStateException("This credential is " +
                                        "no longer valid");
        }

        GSSCredentialSpi element = null;
        SearchKey key = null;
        boolean initiate = false;
        boolean accept = false;

        if (mech == null) mech = ProviderList.DEFAULT_MECH_OID;

        key = new SearchKey(mech, GSSCredential.INITIATE_ONLY);
        element = hashtable.get(key);

        if (element != null) {
            initiate = true;
        }

        key = new SearchKey(mech, GSSCredential.ACCEPT_ONLY);
        element = hashtable.get(key);

        if (element != null) {
            accept = true;
        }

        key = new SearchKey(mech, GSSCredential.INITIATE_AND_ACCEPT);
        element = hashtable.get(key);

        if (element != null) {
            initiate = true;
            accept = true;
        }

        if (initiate && accept)
            return GSSCredential.INITIATE_AND_ACCEPT;
        else if (initiate)
            return GSSCredential.INITIATE_ONLY;
        else if (accept)
            return GSSCredential.ACCEPT_ONLY;
        else {
            throw new GSSExceptionImpl(GSSException.BAD_MECH, mech);
        }
    }

    public Oid[] getMechs() throws GSSException {

        if (destroyed) {
            throw new IllegalStateException("This credential is " +
                                        "no longer valid");
        }
        Vector<Oid> result = new Vector<Oid>(hashtable.size());

        for (Enumeration<SearchKey> e = hashtable.keys();
                                                e.hasMoreElements(); ) {
            SearchKey tempKey = e.nextElement();
            result.addElement(tempKey.getMech());
        }
        return result.toArray(new Oid[0]);
    }

    public void add(GSSName name, int initLifetime, int acceptLifetime,
                    Oid mech, int usage) throws GSSException {

        if (destroyed) {
            throw new IllegalStateException("This credential is " +
                                        "no longer valid");
        }
        if (mech == null) mech = ProviderList.DEFAULT_MECH_OID;

        SearchKey key = new SearchKey(mech, usage);
        if (hashtable.containsKey(key)) {
            throw new GSSExceptionImpl(GSSException.DUPLICATE_ELEMENT,
                                       "Duplicate element found: " +
                                       getElementStr(mech, usage));
        }

        // XXX If not instance of GSSNameImpl then throw exception
        // Application mixing GSS implementations
        GSSNameSpi nameElement = (name == null ? null :
                                  ((GSSNameImpl)name).getElement(mech));

        tempCred = gssManager.getCredentialElement(nameElement,
                                                   initLifetime,
                                                   acceptLifetime,
                                                   mech,
                                                   usage);
        /*
         * Not all mechanisms support the concept of one credential element
         * that can be used for both initiating and accepting a context. In
         * the event that an application requests usage INITIATE_AND_ACCEPT
         * for a credential from such a mechanism, the GSS framework will
         * need to obtain two different credential elements from the
         * mechanism, one that will have usage INITIATE_ONLY and another
         * that will have usage ACCEPT_ONLY. The mechanism will help the
         * GSS-API realize this by returning a credential element with
         * usage INITIATE_ONLY or ACCEPT_ONLY prompting it to make another
         * call to getCredentialElement, this time with the other usage
         * mode.
         */

        if (tempCred != null) {
            if (usage == GSSCredential.INITIATE_AND_ACCEPT &&
                (!tempCred.isAcceptorCredential() ||
                !tempCred.isInitiatorCredential())) {

                int currentUsage;
                int desiredUsage;

                if (!tempCred.isInitiatorCredential()) {
                    currentUsage = GSSCredential.ACCEPT_ONLY;
                    desiredUsage = GSSCredential.INITIATE_ONLY;
                } else {
                    currentUsage = GSSCredential.INITIATE_ONLY;
                    desiredUsage = GSSCredential.ACCEPT_ONLY;
                }

                key = new SearchKey(mech, currentUsage);
                hashtable.put(key, tempCred);

                tempCred = gssManager.getCredentialElement(nameElement,
                                                        initLifetime,
                                                        acceptLifetime,
                                                        mech,
                                                        desiredUsage);

                key = new SearchKey(mech, desiredUsage);
                hashtable.put(key, tempCred);
            } else {
                hashtable.put(key, tempCred);
            }
        }
    }

    public boolean equals(Object another) {

        if (destroyed) {
            throw new IllegalStateException("This credential is " +
                                        "no longer valid");
        }

        if (this == another) {
            return true;
        }

        if (!(another instanceof GSSCredentialImpl)) {
            return false;
        }

        // NOTE: The specification does not define the criteria to compare
        // credentials.
        /*
         * XXX
         * The RFC says: "Tests if this GSSCredential refers to the same
         * entity as the supplied object.  The two credentials must be
         * acquired over the same mechanisms and must refer to the same
         * principal.  Returns "true" if the two GSSCredentials refer to
         * the same entity; "false" otherwise."
         *
         * Well, when do two credentials refer to the same principal? Do
         * they need to have one GSSName in common for the different
         * GSSName's that the credential elements return? Or do all
         * GSSName's have to be in common when the names are exported with
         * their respective mechanisms for the credential elements?
         */
        return false;

    }

    /**
     * Returns a hashcode value for this GSSCredential.
     *
     * @return a hashCode value
     */
    public int hashCode() {

        if (destroyed) {
            throw new IllegalStateException("This credential is " +
                                        "no longer valid");
        }

        // NOTE: The specification does not define the criteria to compare
        // credentials.
        /*
         * XXX
         * Decide on a criteria for equals first then do this.
         */
        return 1;
    }

    /**
     * Returns the specified mechanism's credential-element.
     *
     * @param mechOid - the oid for mechanism to retrieve
     * @param throwExcep - boolean indicating if the function is
     *    to throw exception or return null when element is not
     *    found.
     * @return mechanism credential object
     * @exception GSSException of invalid mechanism
     */
    public GSSCredentialSpi getElement(Oid mechOid, boolean initiate)
        throws GSSException {

        if (destroyed) {
            throw new IllegalStateException("This credential is " +
                                        "no longer valid");
        }

        SearchKey key;
        GSSCredentialSpi element;

        if (mechOid == null) {
            /*
             * First see if the default mechanism satisfies the
             * desired usage.
             */
            mechOid = ProviderList.DEFAULT_MECH_OID;
            key = new SearchKey(mechOid,
                                 initiate? INITIATE_ONLY : ACCEPT_ONLY);
            element = hashtable.get(key);
            if (element == null) {
                key = new SearchKey(mechOid, INITIATE_AND_ACCEPT);
                element = hashtable.get(key);
                if (element == null) {
                    /*
                     * Now just return any element that satisfies the
                     * desired usage.
                     */
                    Object[] elements = hashtable.entrySet().toArray();
                    for (int i = 0; i < elements.length; i++) {
                        element = (GSSCredentialSpi)
                            ((Map.Entry)elements[i]).getValue();
                        if (element.isInitiatorCredential() == initiate)
                            break;
                    } // for loop
                }
            }
        } else {

            if (initiate)
                key = new SearchKey(mechOid, INITIATE_ONLY);
            else
                key = new SearchKey(mechOid, ACCEPT_ONLY);

            element = hashtable.get(key);

            if (element == null) {
                key = new SearchKey(mechOid, INITIATE_AND_ACCEPT);
                element = hashtable.get(key);
            }
        }

        if (element == null)
            throw new GSSExceptionImpl(GSSException.NO_CRED,
                                       "No credential found for: " +
                                       mechOid + getElementStr(mechOid,
                                       initiate? INITIATE_ONLY : ACCEPT_ONLY));
        return element;
    }

    Set<GSSCredentialSpi> getElements() {
        HashSet<GSSCredentialSpi> retVal =
                        new HashSet<GSSCredentialSpi>(hashtable.size());
        Enumeration<GSSCredentialSpi> values = hashtable.elements();
        while (values.hasMoreElements()) {
            GSSCredentialSpi o = values.nextElement();
            retVal.add(o);
        }
        return retVal;
    }

    private static String getElementStr(Oid mechOid, int usage) {
        String displayString = mechOid.toString();
        if (usage == GSSCredential.INITIATE_ONLY) {
            displayString =
                displayString.concat(" usage: Initiate");
        } else if (usage == GSSCredential.ACCEPT_ONLY) {
            displayString =
                displayString.concat(" usage: Accept");
        } else {
            displayString =
                displayString.concat(" usage: Initiate and Accept");
        }
        return displayString;
    }

    public String toString() {

        if (destroyed) {
            throw new IllegalStateException("This credential is " +
                                        "no longer valid");
        }

        GSSCredentialSpi element = null;
        StringBuffer buffer = new StringBuffer("[GSSCredential: ");
        Object[] elements = hashtable.entrySet().toArray();
        for (int i = 0; i < elements.length; i++) {
            try {
                buffer.append('\n');
                element = (GSSCredentialSpi)
                    ((Map.Entry)elements[i]).getValue();
                buffer.append(element.getName());
                buffer.append(' ');
                buffer.append(element.getMechanism());
                buffer.append(element.isInitiatorCredential() ?
                              " Initiate" : "");
                buffer.append(element.isAcceptorCredential() ?
                              " Accept" : "");
                buffer.append(" [");
                buffer.append(element.toString());
                buffer.append(']');
            } catch (GSSException e) {
                // skip to next element
            }
        }
        buffer.append(']');
        return buffer.toString();
    }

    static class SearchKey {
        private Oid mechOid = null;
        private int usage = GSSCredential.INITIATE_AND_ACCEPT;
        public SearchKey(Oid mechOid, int usage) {

            this.mechOid = mechOid;
            this.usage = usage;
        }
        public Oid getMech() {
            return mechOid;
        }
        public int getUsage() {
            return usage;
        }
        public boolean equals(Object other) {
            if (! (other instanceof SearchKey))
                return false;
            SearchKey that = (SearchKey) other;
            return ((this.mechOid.equals(that.mechOid)) &&
                    (this.usage == that.usage));
        }
        public int hashCode() {
            return mechOid.hashCode();
        }
    }

}
