/* KeyStore.java --- Key Store Class
   Copyright (C) 1999, 2002, 2003, 2004  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath 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 for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.security;

import gnu.java.security.Engine;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.cert.CertificateException;
import java.util.Date;
import java.util.Enumeration;

/**
 * Keystore represents an in-memory collection of keys and 
 * certificates. There are two types of entries:
 *
 * <dl>
 * <dt>Key Entry</dt>
 *
 * <dd><p>This type of keystore entry store sensitive crytographic key
 * information in a protected format.Typically this is a secret 
 * key or a private key with a certificate chain.</p></dd>
 *
 * <dt>Trusted Ceritificate Entry</dt>
 *
 * <dd><p>This type of keystore entry contains a single public key 
 * certificate belonging to annother entity. It is called trusted
 * because the keystore owner trusts that the certificates
 * belongs to the subject (owner) of the certificate.</p></dd>
 * </dl>
 *
 * <p>Entries in a key store are referred to by their "alias": a simple
 * unique string.
 *
 * <p>The structure and persistentence of the key store is not 
 * specified. Any method could be used to protect sensitive 
 * (private or secret) keys. Smart cards or integrated 
 * cryptographic engines could be used or the keystore could 
 * be simply stored in a file.</p>
 *
 * @see java.security.cert.Certificate
 * @see Key
 */
public class KeyStore
{

  // Constants and fields.
  // ------------------------------------------------------------------------

  /** Service name for key stores. */
  private static final String KEY_STORE = "KeyStore";

  private KeyStoreSpi keyStoreSpi;
  private Provider provider;
  private String type;

  // Constructors.
  // ------------------------------------------------------------------------

  /**
     Creates an instance of KeyStore

     @param keyStoreSpi A KeyStore engine to use
     @param provider A provider to use
     @param type The type of KeyStore
   */
  protected KeyStore(KeyStoreSpi keyStoreSpi, Provider provider, String type)
  {
    this.keyStoreSpi = keyStoreSpi;
    this.provider = provider;
    this.type = type;
  }

  // Class methods.
  // ------------------------------------------------------------------------

  /** 
   * Gets an instance of the KeyStore class representing
   * the specified keystore. If the type is not 
   * found then, it throws KeyStoreException.
   *
   * @param type the type of keystore to choose
   * @return a KeyStore repesenting the desired type
   * @throws KeyStoreException if the type of keystore is not implemented
   *         by providers or the implementation cannot be instantiated.
   */
  public static KeyStore getInstance(String type) throws KeyStoreException
  {
    Provider[] p = Security.getProviders();

    for (int i = 0; i < p.length; i++)
      {
        try
          {
            return getInstance(type, p[i]);
          }
        catch (KeyStoreException e)
          {
	    // Ignore.
          }
      }

    throw new KeyStoreException(type);
  }

  /** 
   * Gets an instance of the KeyStore class representing
   * the specified key store from the specified provider. 
   * If the type is not found then, it throws KeyStoreException. 
   * If the provider is not found, then it throws 
   * NoSuchProviderException.
   *
   * @param type the type of keystore to choose
   * @param provider the provider name
   * @return a KeyStore repesenting the desired type
   * @throws KeyStoreException if the type of keystore is not 
   *          implemented by the given provider
   * @throws NoSuchProviderException if the provider is not found
   * @throws IllegalArgumentException if the provider string is 
   *           null or empty
   */
  public static KeyStore getInstance(String type, String provider)
    throws KeyStoreException, NoSuchProviderException
  {
    if (provider == null || provider.length() == 0)
      throw new IllegalArgumentException("Illegal provider");

    Provider p = Security.getProvider(provider);
    if (p == null)
      throw new NoSuchProviderException(provider);

    return getInstance(type, p);
  }

  /** 
   * Gets an instance of the KeyStore class representing
   * the specified key store from the specified provider. 
   * If the type is not found then, it throws KeyStoreException. 
   * If the provider is not found, then it throws 
   * NoSuchProviderException.
   *
   * @param type the type of keystore to choose
   * @param provider the keystore provider
   * @return a KeyStore repesenting the desired type
   * @throws KeyStoreException if the type of keystore is not 
   *          implemented by the given provider
   * @throws IllegalArgumentException if the provider object is null
   * @since 1.4
   */
  public static KeyStore getInstance(String type, Provider provider)
    throws KeyStoreException 
  {
    if (provider == null)
      throw new IllegalArgumentException("Illegal provider");
    try
      {
        return new KeyStore(
          (KeyStoreSpi) Engine.getInstance(KEY_STORE, type, provider),
          provider, type);
      }
    catch (NoSuchAlgorithmException nsae)
      {
        throw new KeyStoreException(type);
      }
    catch (java.lang.reflect.InvocationTargetException ite)
      {
	throw new KeyStoreException(type);
      }
    catch (ClassCastException cce)
      {
        throw new KeyStoreException(type);
      }
  }

  /**
   * Returns the default KeyStore type. This method looks up the
   * type in &lt;JAVA_HOME&gt;/lib/security/java.security with the 
   * property "keystore.type" or if that fails then "gkr" .
   */
  public static final String getDefaultType()
  {
    // Security reads every property in java.security so it 
    // will return this property if it exists. 
    String tmp = Security.getProperty("keystore.type");

    if (tmp == null)
      tmp = "gkr";

    return tmp;
  }

  // Instance methods.
  // ------------------------------------------------------------------------

  /**
     Gets the provider that the class is from.

     @return the provider of this class
   */
  public final Provider getProvider()
  {
    return provider;
  }

  /**
     Returns the type of the KeyStore supported

     @return A string with the type of KeyStore
   */
  public final String getType()
  {
    return type;
  }

  /**
     Returns the key associated with given alias using the 
     supplied password.

     @param alias an alias for the key to get
     @param password password to access key with

     @return the requested key, or null otherwise

     @throws NoSuchAlgorithmException if there is no algorithm
     for recovering the key
     @throws UnrecoverableKeyException key cannot be reocovered
     (wrong password).
   */
  public final Key getKey(String alias, char[]password)
    throws KeyStoreException, NoSuchAlgorithmException,
    UnrecoverableKeyException
  {
    return keyStoreSpi.engineGetKey(alias, password);
  }

  /**
     Gets a Certificate chain for the specified alias.

     @param alias the alias name

     @return a chain of Certificates ( ordered from the user's 
     certificate to the Certificate Authority's ) or 
     null if the alias does not exist or there is no
     certificate chain for the alias ( the alias refers
     to a trusted certificate entry or there is no entry).
   */
  public final java.security.cert.
    Certificate[] getCertificateChain(String alias) throws KeyStoreException
  {
    return keyStoreSpi.engineGetCertificateChain(alias);
  }

  /**
     Gets a Certificate for the specified alias.

     If there is a trusted certificate entry then that is returned.
     it there is a key entry with a certificate chain then the
     first certificate is return or else null.

     @param alias the alias name

     @return a Certificate or null if the alias does not exist 
     or there is no certificate for the alias
   */
  public final java.security.cert.Certificate getCertificate(String alias)
    throws KeyStoreException
  {
    return keyStoreSpi.engineGetCertificate(alias);
  }

  /**
     Gets entry creation date for the specified alias.

     @param alias the alias name

     @returns the entry creation date or null
   */
  public final Date getCreationDate(String alias) throws KeyStoreException
  {
    return keyStoreSpi.engineGetCreationDate(alias);
  }

  /**
     Assign the key to the alias in the keystore, protecting it
     with the given password. It will overwrite an existing 
     entry and if the key is a PrivateKey, also add the 
     certificate chain representing the corresponding public key.

     @param alias the alias name
     @param key the key to add
     @password the password to protect with
     @param chain the certificate chain for the corresponding
     public key

     @throws KeyStoreException if it fails
   */
  public final void setKeyEntry(String alias, Key key, char[]password,
				java.security.cert.
				Certificate[]chain) throws KeyStoreException
  {
    keyStoreSpi.engineSetKeyEntry(alias, key, password, chain);
  }

  /**
     Assign the key to the alias in the keystore. It will overwrite
     an existing entry and if the key is a PrivateKey, also 
     add the certificate chain representing the corresponding 
     public key.

     @param alias the alias name
     @param key the key to add
     @param chain the certificate chain for the corresponding
     public key

     @throws KeyStoreException if it fails
   */
  public final void setKeyEntry(String alias, byte[]key,
				java.security.cert.
				Certificate[]chain) throws KeyStoreException
  {
    keyStoreSpi.engineSetKeyEntry(alias, key, chain);
  }

  /**
     Assign the certificate to the alias in the keystore. It 
     will overwrite an existing entry.

     @param alias the alias name
     @param cert the certificate to add

     @throws KeyStoreException if it fails
   */
  public final void setCertificateEntry(String alias,
					java.security.cert.
					Certificate cert) throws
    KeyStoreException
  {
    keyStoreSpi.engineSetCertificateEntry(alias, cert);
  }

  /**
     Deletes the entry for the specified entry.

     @param alias the alias name

     @throws KeyStoreException if it fails
   */
  public final void deleteEntry(String alias) throws KeyStoreException
  {
    keyStoreSpi.engineDeleteEntry(alias);
  }

  /**
     Generates a list of all the aliases in the keystore.

     @return an Enumeration of the aliases
   */
  public final Enumeration aliases() throws KeyStoreException
  {
    return keyStoreSpi.engineAliases();
  }

  /**
     Determines if the keystore contains the specified alias.

     @param alias the alias name

     @return true if it contains the alias, false otherwise
   */
  public final boolean containsAlias(String alias) throws KeyStoreException
  {
    return keyStoreSpi.engineContainsAlias(alias);
  }

  /**
     Returns the number of entries in the keystore.

     @returns the number of keystore entries.
   */
  public final int size() throws KeyStoreException
  {
    return keyStoreSpi.engineSize();
  }

  /**
     Determines if the keystore contains a key entry for 
     the specified alias.

     @param alias the alias name

     @return true if it is a key entry, false otherwise
   */
  public final boolean isKeyEntry(String alias) throws KeyStoreException
  {
    return keyStoreSpi.engineIsKeyEntry(alias);
  }


  /**
     Determines if the keystore contains a certificate entry for 
     the specified alias.

     @param alias the alias name

     @return true if it is a certificate entry, false otherwise
   */
  public final boolean isCertificateEntry(String alias)
    throws KeyStoreException
  {
    return keyStoreSpi.engineIsCertificateEntry(alias);
  }

  /**
     Determines if the keystore contains the specified certificate 
     entry and returns the alias.

     It checks every entry and for a key entry checks only the
     first certificate in the chain.

     @param cert Certificate to look for

     @return alias of first matching certificate, null if it 
     does not exist.
   */
  public final String getCertificateAlias(java.security.cert.Certificate cert)
    throws KeyStoreException
  {
    return keyStoreSpi.engineGetCertificateAlias(cert);
  }

  /**
     Stores the keystore in the specified output stream and it
     uses the specified key it keep it secure.

     @param stream the output stream to save the keystore to
     @param password the password to protect the keystore integrity with

     @throws IOException if an I/O error occurs.
     @throws NoSuchAlgorithmException the data integrity algorithm 
     used cannot be found.
     @throws CertificateException if any certificates could not be
     stored in the output stream.
   */
  public final void store(OutputStream stream, char[]password)
    throws KeyStoreException, IOException, NoSuchAlgorithmException,
    CertificateException
  {
    keyStoreSpi.engineStore(stream, password);
  }

  /**
     Loads the keystore from the specified input stream and it
     uses the specified password to check for integrity if supplied.

     @param stream the input stream to load the keystore from
     @param password the password to check the keystore integrity with

     @throws IOException if an I/O error occurs.
     @throws NoSuchAlgorithmException the data integrity algorithm 
     used cannot be found.
     @throws CertificateException if any certificates could not be
     stored in the output stream.
   */
  public final void load(InputStream stream, char[]password)
    throws IOException, NoSuchAlgorithmException, CertificateException
  {
    keyStoreSpi.engineLoad(stream, password);
  }

}
