/*
 * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */
package java.security.cert;
import java.security.AccessController;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivilegedAction;
import java.security.Provider;
import java.security.Security;
import java.util.Collection;
import sun.security.jca.*;
import sun.security.jca.GetInstance.Instance;
/**
 * A class for retrieving Certificates and CRLs
 * from a repository.
 * 
 * This class uses a provider-based architecture.
 * To create a CertStore, call one of the static
 * getInstance methods, passing in the type of
 * CertStore desired, any applicable initialization parameters
 * and optionally the name of the provider desired.
 * 
 * Once the CertStore has been created, it can be used to
 * retrieve Certificates and CRLs by calling its
 * {@link #getCertificates(CertSelector selector) getCertificates} and
 * {@link #getCRLs(CRLSelector selector) getCRLs} methods.
 * 
 * Unlike a {@link java.security.KeyStore KeyStore}, which provides access
 * to a cache of private keys and trusted certificates, a
 * CertStore is designed to provide access to a potentially
 * vast repository of untrusted certificates and CRLs. For example, an LDAP
 * implementation of CertStore provides access to certificates
 * and CRLs stored in one or more directories using the LDAP protocol and the
 * schema as defined in the RFC service attribute.
 *
 * 
 Every implementation of the Java platform is required to support the
 * following standard CertStore type:
 * 
* Concurrent Access *
 * All public methods of CertStore objects must be thread-safe.
 * That is, multiple threads may concurrently invoke these methods on a
 * single CertStore object (or more than one) with no
 * ill effects. This allows a CertPathBuilder to search for a
 * CRL while simultaneously searching for further certificates, for instance.
 * 
* The static methods of this class are also guaranteed to be thread-safe. * Multiple threads may concurrently invoke the static methods defined in * this class with no ill effects. * * @since 1.4 * @author Sean Mullan, Steve Hanna */ public class CertStore { /* * Constant to lookup in the Security properties file to determine * the default certstore type. In the Security properties file, the * default certstore type is given as: *
     * certstore.type=LDAP
     * 
     */
    private static final String CERTSTORE_TYPE = "certstore.type";
    private CertStoreSpi storeSpi;
    private Provider provider;
    private String type;
    private CertStoreParameters params;
    /**
     * Creates a CertStore object of the given type, and
     * encapsulates the given provider implementation (SPI object) in it.
     *
     * @param storeSpi the provider implementation
     * @param provider the provider
     * @param type the type
     * @param params the initialization parameters (may be null)
     */
    protected CertStore(CertStoreSpi storeSpi, Provider provider,
                        String type, CertStoreParameters params) {
        this.storeSpi = storeSpi;
        this.provider = provider;
        this.type = type;
        if (params != null)
            this.params = (CertStoreParameters) params.clone();
    }
    /**
     * Returns a Collection of Certificates that
     * match the specified selector. If no Certificates
     * match the selector, an empty Collection will be returned.
     * 
     * For some CertStore types, the resulting
     * Collection may not contain all of the
     * Certificates that match the selector. For instance,
     * an LDAP CertStore may not search all entries in the
     * directory. Instead, it may just search entries that are likely to
     * contain the Certificates it is looking for.
     * 
     * Some CertStore implementations (especially LDAP
     * CertStores) may throw a CertStoreException
     * unless a non-null CertSelector is provided that
     * includes specific criteria that can be used to find the certificates.
     * Issuer and/or subject names are especially useful criteria.
     *
     * @param selector A CertSelector used to select which
     *  Certificates should be returned. Specify null
     *  to return all Certificates (if supported).
     * @return A Collection of Certificates that
     *         match the specified selector (never null)
     * @throws CertStoreException if an exception occurs
     */
    public final Collection extends Certificate> getCertificates
            (CertSelector selector) throws CertStoreException {
        return storeSpi.engineGetCertificates(selector);
    }
    /**
     * Returns a Collection of CRLs that
     * match the specified selector. If no CRLs
     * match the selector, an empty Collection will be returned.
     * 
     * For some CertStore types, the resulting
     * Collection may not contain all of the
     * CRLs that match the selector. For instance,
     * an LDAP CertStore may not search all entries in the
     * directory. Instead, it may just search entries that are likely to
     * contain the CRLs it is looking for.
     * 
     * Some CertStore implementations (especially LDAP
     * CertStores) may throw a CertStoreException
     * unless a non-null CRLSelector is provided that
     * includes specific criteria that can be used to find the CRLs.
     * Issuer names and/or the certificate to be checked are especially useful.
     *
     * @param selector A CRLSelector used to select which
     *  CRLs should be returned. Specify null
     *  to return all CRLs (if supported).
     * @return A Collection of CRLs that
     *         match the specified selector (never null)
     * @throws CertStoreException if an exception occurs
     */
    public final Collection extends CRL> getCRLs(CRLSelector selector)
            throws CertStoreException {
        return storeSpi.engineGetCRLs(selector);
    }
    /**
     * Returns a CertStore object that implements the specified
     * CertStore type and is initialized with the specified
     * parameters.
     *
     * 
This method traverses the list of registered security Providers, * starting with the most preferred Provider. * A new CertStore object encapsulating the * CertStoreSpi implementation from the first * Provider that supports the specified type is returned. * *
Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * *
The CertStore that is returned is initialized with the
     * specified CertStoreParameters. The type of parameters
     * needed may vary between different types of CertStores.
     * Note that the specified CertStoreParameters object is
     * cloned.
     *
     * @param type the name of the requested CertStore type.
     * See the CertStore section in the 
     * Java Cryptography Architecture Standard Algorithm Name Documentation
     * for information about standard types.
     *
     * @param params the initialization parameters (may be null).
     *
     * @return a CertStore object that implements the specified
     *          CertStore type.
     *
     * @throws NoSuchAlgorithmException if no Provider supports a
     *          CertStoreSpi implementation for the specified type.
     *
     * @throws InvalidAlgorithmParameterException if the specified
     *          initialization parameters are inappropriate for this
     *          CertStore.
     *
     * @see java.security.Provider
     */
    public static CertStore getInstance(String type, CertStoreParameters params)
            throws InvalidAlgorithmParameterException,
            NoSuchAlgorithmException {
        try {
            Instance instance = GetInstance.getInstance("CertStore",
                CertStoreSpi.class, type, params);
            return new CertStore((CertStoreSpi)instance.impl,
                instance.provider, type, params);
        } catch (NoSuchAlgorithmException e) {
            return handleException(e);
        }
    }
    private static CertStore handleException(NoSuchAlgorithmException e)
            throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
        Throwable cause = e.getCause();
        if (cause instanceof InvalidAlgorithmParameterException) {
            throw (InvalidAlgorithmParameterException)cause;
        }
        throw e;
    }
    /**
     * Returns a CertStore object that implements the specified
     * CertStore type.
     *
     * 
A new CertStore object encapsulating the * CertStoreSpi implementation from the specified provider * is returned. The specified provider must be registered * in the security provider list. * *
Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * *
The CertStore that is returned is initialized with the
     * specified CertStoreParameters. The type of parameters
     * needed may vary between different types of CertStores.
     * Note that the specified CertStoreParameters object is
     * cloned.
     *
     * @param type the requested CertStore type.
     * See the CertStore section in the 
     * Java Cryptography Architecture Standard Algorithm Name Documentation
     * for information about standard types.
     *
     * @param params the initialization parameters (may be null).
     *
     * @param provider the name of the provider.
     *
     * @return a CertStore object that implements the
     *          specified type.
     *
     * @throws NoSuchAlgorithmException if a CertStoreSpi
     *          implementation for the specified type is not
     *          available from the specified provider.
     *
     * @throws InvalidAlgorithmParameterException if the specified
     *          initialization parameters are inappropriate for this
     *          CertStore.
     *
     * @throws NoSuchProviderException if the specified provider is not
     *          registered in the security provider list.
     *
     * @exception IllegalArgumentException if the provider is
     *          null or empty.
     *
     * @see java.security.Provider
     */
    public static CertStore getInstance(String type,
            CertStoreParameters params, String provider)
            throws InvalidAlgorithmParameterException,
            NoSuchAlgorithmException, NoSuchProviderException {
        try {
            Instance instance = GetInstance.getInstance("CertStore",
                CertStoreSpi.class, type, params, provider);
            return new CertStore((CertStoreSpi)instance.impl,
                instance.provider, type, params);
        } catch (NoSuchAlgorithmException e) {
            return handleException(e);
        }
    }
    /**
     * Returns a CertStore object that implements the specified
     * CertStore type.
     *
     * 
A new CertStore object encapsulating the * CertStoreSpi implementation from the specified Provider * object is returned. Note that the specified Provider object * does not have to be registered in the provider list. * *
The CertStore that is returned is initialized with the
     * specified CertStoreParameters. The type of parameters
     * needed may vary between different types of CertStores.
     * Note that the specified CertStoreParameters object is
     * cloned.
     *
     * @param type the requested CertStore type.
     * See the CertStore section in the 
     * Java Cryptography Architecture Standard Algorithm Name Documentation
     * for information about standard types.
     *
     * @param params the initialization parameters (may be null).
     *
     * @param provider the provider.
     *
     * @return a CertStore object that implements the
     *          specified type.
     *
     * @exception NoSuchAlgorithmException if a CertStoreSpi
     *          implementation for the specified type is not available
     *          from the specified Provider object.
     *
     * @throws InvalidAlgorithmParameterException if the specified
     *          initialization parameters are inappropriate for this
     *          CertStore
     *
     * @exception IllegalArgumentException if the provider is
     *          null.
     *
     * @see java.security.Provider
     */
    public static CertStore getInstance(String type, CertStoreParameters params,
            Provider provider) throws NoSuchAlgorithmException,
            InvalidAlgorithmParameterException {
        try {
            Instance instance = GetInstance.getInstance("CertStore",
                CertStoreSpi.class, type, params, provider);
            return new CertStore((CertStoreSpi)instance.impl,
                instance.provider, type, params);
        } catch (NoSuchAlgorithmException e) {
            return handleException(e);
        }
    }
    /**
     * Returns the parameters used to initialize this CertStore.
     * Note that the CertStoreParameters object is cloned before
     * it is returned.
     *
     * @return the parameters used to initialize this CertStore
     * (may be null)
     */
    public final CertStoreParameters getCertStoreParameters() {
        return (params == null ? null : (CertStoreParameters) params.clone());
    }
    /**
     * Returns the type of this CertStore.
     *
     * @return the type of this CertStore
     */
    public final String getType() {
        return this.type;
    }
    /**
     * Returns the provider of this CertStore.
     *
     * @return the provider of this CertStore
     */
    public final Provider getProvider() {
        return this.provider;
    }
    /**
     * Returns the default CertStore type as specified in the
     * Java security properties file, or the string "LDAP" if no
     * such property exists. The Java security properties file is located in
     * the file named <JAVA_HOME>/lib/security/java.security.
     * <JAVA_HOME> refers to the value of the java.home system property,
     * and specifies the directory where the JRE is installed.
     *
     * 
The default CertStore type can be used by applications
     * that do not want to use a hard-coded type when calling one of the
     * getInstance methods, and want to provide a default
     * CertStore type in case a user does not specify its own.
     *
     * 
The default CertStore type can be changed by setting
     * the value of the "certstore.type" security property (in the Java
     * security properties file) to the desired type.
     *
     * @return the default CertStore type as specified in the
     * Java security properties file, or the string "LDAP"
     * if no such property exists.
     */
    public final static String getDefaultType() {
        String cstype;
        cstype = AccessController.doPrivileged(new PrivilegedAction