// Copyright 1998 The Open Group Research Institute.  All rights reserved.
// Copyright 1999 Memesoft.  All rights reserved.

package krb5.lib.ccache;

import krb5.lib.*;

import krb5.lib.*;
import java.util.*;

/**
 * Virtual memory credentials cache implementation
 */
public class VmCCacheImpl extends CCacheImpl implements CredentialsCache {
    
	/**
	 * Name
	 */    
    private PrincipalName thisPrincipal_;
    
    /**
	 * Credentials list
	 */
    private Vector credList_ = new Vector();

    // Inner class that implements the CCacheEnumerator interface
    // for the VM ccache
    /**
     * Inner class that implements the CCacheEnumerator interface for the VM ccache
     */
    private class VmCCacheEnumerator implements CCacheEnumerator {
        /**
         * Enumeration
         */
        private Enumeration e_;
        /**
         * Vector
         */
        private Vector v_;

        /**
         * Class constructor
         */
        VmCCacheEnumerator(Vector cVec) {
             v_ = (Vector) cVec.clone();
             e_ = v_.elements();
        }

        /**
         * Does have more credentials ?
         */
        public boolean hasMoreCredentials() {
            return e_.hasMoreElements();
        }

        /**
         * Gets next credentials
         */
        public Credentials nextCredential() {
            if (e_.hasMoreElements())
                return (Credentials)((Credentials) e_.nextElement()).clone();
            else
                return null;
        }
    }

    // MUST BE PUBLIC or the getConstructor() method used by the
    // CCacheFactory to obtain a handle on the constructor at runtime
    // will fail.
    /**
     * Class constructor
     * @param info is of type String
     */
    public VmCCacheImpl(String info) {
        // No extra info in a 
    }

    /**
     * Returns name
     * @return String is a result
     */
	public synchronized String getName() {
	    // VM caches have no meaningful name. Perhaps we could
	    // decorate the return value with the address of the cache?
	    //
	    return null;
	}

    /**
     * Returns name
     * @return PrincipalName is a result
     * @see krb5.lib.PrincipalName
     */
	public synchronized PrincipalName getPrimaryPrincipal() {
	    return (PrincipalName)thisPrincipal_.clone();
	}

	/**
	 * Returns name
	 *
	 * @param princ is of type PrincipalName
	 * @see krb5.lib.PrincipalName
	 */
	public synchronized void setPrimaryPrincipal(PrincipalName princ) {
	    thisPrincipal_ = (PrincipalName)princ.clone();
	}
	
	/**
	 * Destroy
	 */
	public synchronized void destroy() {
	    Enumeration e = credList_.elements();
	    while (e.hasMoreElements())
	    {
	        ((Credentials)e.nextElement()).destroy();
	    }
	}

    /**
     * Finalize
     */
	public void finalize() {
	    destroy();
	}

    /**
     * Add credentials
     * @param cred is of type Credentials
     * @see krb5.lib.ccache.Credentials
	 */
	public synchronized void add(Credentials cred) {
	    credList_.addElement((Credentials)cred.clone());
	}

    /**
	 * Add credentials
	 *
	 * @param creds is of type Credentials[]
	 * @see krb5.lib.ccache.Credentials
	 */
	public synchronized void add(Credentials[] creds) {
	    for (int i = 0; i < creds.length; i++)
	        credList_.addElement((Credentials)creds[i].clone());
	}

    /**
	 * Remove credentials
	 *
	 * @param creds is of type Credentials
	 * @see krb5.lib.ccache.Credentials
	 */
	public synchronized void remove(Credentials creds) {
	    //XXX TO BE IMPLEMENTED
	}

    /**
	 * Remove credentials
	 *
	 * @param creds is of type Credentials[]
	 * @see krb5.lib.ccache.Credentials
	 */
	public synchronized void remove(Credentials[] creds) {
	    //XXX TO BE IMPLEMENTED
	}

    /**
	 * Returns credentials
	 *
	 * @return CCacheEnumerator is a result
	 * @see krb5.lib.ccache.CCacheEnumerator
	 */
	public synchronized CCacheEnumerator getCredentials() {
	    return (CCacheEnumerator) new VmCCacheEnumerator(credList_);
	}

	/**
	 * Lookups credentials
	 *
	 * @return CCacheEnumerator is a result
	 * @param filters is of type CredentialsFilter[]
	 * @see krb5.lib.ccache.CCacheEnumerator
	 * @see krb5.lib.ccache.CredentialsFilter
	 */
	public synchronized CCacheEnumerator lookupCredentials(CredentialsFilter[] filters) {
	    Vector matchVec = new Vector(credList_.size());
	    Credentials curCred = null;
	    for (Enumeration e = credList_.elements(); e.hasMoreElements();) {
	        curCred = (Credentials)e.nextElement();
	        boolean matched = true;
	        for (int j = 0; j < filters.length && matched; j++)
	            matched = filters[j].filter(curCred);
	        if (matched)
	            matchVec.addElement(curCred);
	    }

        return new VmCCacheEnumerator(matchVec);
	}

	/**
	 * Lookups single credentials
	 *
	 * @return Credentials is a result
	 * @param filters is of type CredentialsFilter[]
	 * @see krb5.lib.ccache.Credentials
	 * @see krb5.lib.ccache.CredentialsFilter
	 */
	public synchronized Credentials lookupSingleCredentials(CredentialsFilter[] filters) {
	    Credentials cred = null;
	    for (Enumeration e = credList_.elements(); e.hasMoreElements();) {
	        Credentials curCred = (Credentials)e.nextElement();
	        boolean matched = true;
	        for (int j = 0; j < filters.length && matched; j++)
	            matched = filters[j].filter(curCred);
	        if (matched)
	            cred = (Credentials)curCred.clone();
	    }
	    return cred;
	}
    
	/**
	 * Copies from a given credentials cache
	 *
	 * @param ccache is of type CredentialsCache
	 * @see krb5.lib.ccache.CredentialsCache
	 */
	public synchronized void copyFrom(CredentialsCache ccache) {
	    for (CCacheEnumerator e = ccache.getCredentials(); e.hasMoreCredentials();)
	        credList_.addElement(e.nextCredential());
	}

    /**
     * Prints
     */
	public synchronized void print() {
	    // XXX TO BE IMPLEMENTED
	}
}
