/* 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., 59 Temple Place, Suite 330, Boston, MA
02111-1307 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 "jks" .
   */
  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 = "jks";

    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);
  }

}
