// Hashregistry.java
// (c) COPYRIGHT MIT and INRIA, 1997.
// Please first read the full copyright statement in file COPYRIGHT.html

// The source code is jointly developed by W3C and some of its members
// participating in the Digital Signature Initiative.  The authors are:
//    Mark Champine, HP, <champine@apollo.hp.com>
//    Yang-hua Chu, MIT/W3C, <yhchu@w3.org>
//    Vasanthan Dasan, Sun, <vasanthan.dasan@central.sun.com>
//    Peter Lipp, University of Technology, Graz <plipp@iaik.tu-graz.ac.at>
//    Andreas Sterbenz, U. of Technology, Graz <sterbenz@iaik.tu-graz.ac.at>

package w3c.www.dsig;

import w3c.tools.codec.*;
import java.util.*;
import java.security.*;
import java.io.*;

/**
 * The CertFormatRegistry class maintains a database of the certificate
 * formats installed on the system.
 * Classes implementing a certificate format follow the standard
 * java.security.Certificate API.
 *
 * @author Andreas Sterbenz
 * @version 1.0beta (last modified 18-December-1997)
 */
public final class CertFormatRegistry
{
  /**
   * Flag indicating debug mode. Internal use only.
   */
  private final static boolean DEBUG = false;
  /**
   * The URL defined to indentify the X.509 certificate format.
   * Currently this is <TT>http://www.w3.org/PICS/DSig/X509-1_0.html</TT>,
   * but note that this might change in the future as this variable will
   * always hold the URL of the <EM>latest</EM> version of the DSig X.509
   * specification!
   */
  public final static String X509URL = "http://www.w3.org/PICS/DSig/X509-1_0.html";
  /**
   * The URL defined to indentify the PGP certificate format.
   * Currently this is <TT>http://www.w3.org/PICS/DSig/pgpcert-1_0.html</TT>,
   * but note that this might change in the future as this variable will
   * always hold the URL of the <EM>latest</EM> version of the DSig PGP
   * specification!
   */
  public final static String PGPURL = 
  "http://www.w3.org/PICS/DSig/pgpcert-1_0.html";

  private static Hashtable formats;

  static {
    initialize();
  }

  /**
   * Initialize function to initialize the hashtable.
   */
  private static void initialize()
  {
    formats = new Hashtable();
    // no defaults to add
  }

  /**
   * Return the number of installed certificate formats.
   */
  public static int size()
  {
    return formats.size();
  }

  /**
   * Return an enumeration with the URL names of the currently
   * installed certificate formats.
   */
  public static Enumeration formats()
  {
    return formats.keys();
  }

  /**
   * Print the list of currently installed certificate formats and the
   * names of the classes that implement them on stdout.
   */
  public static void printFormats()
  {
    System.out.println("Currently installed certificate formats:");
    for (Enumeration e = formats() ; e.hasMoreElements() ;) {
      String name = (String)e.nextElement();
      System.out.println(name + " -> " +((Class)formats.get(name)).getName());
    }
  }

  /**
   * Add a new certificate format, identified via name, implemented by the
   * class clazz. The class represented by clazz must implement
   * the java.security.Certificate interface.
   * Returns true is successful, false otherwise (algorithm already present)
   */
  public static boolean addFormat(String name, Class clazz)
  {
    try {
      if( clazz.newInstance() instanceof Certificate ) {
        return formats.put(name, clazz) == null;
      } else {
        return false;
      }
    } catch( Exception e ) {
      return false;
    }
  }

  /**
   * Find out if the specified certificate format is installed in the
   * registry.
   */
  public static boolean isInstalled(String name)
  {
    return formats.get(name) != null;
  }

  /**
   * Remove the named certificate format from the registry.
   * Returns true if successful, false if the algorithm was not installed.
   */
  public static boolean removeFormat(String name)
  {
    return formats.remove(name) == null;
  }

  /**
   * Get an instance of a class implementing the certificate format name.
   * Name is the URL identifying the algorithm.
   * @exception NoSuchAlgorithmException if the format is not installed.
   */
  public static Certificate getInstance(String name) throws NoSuchAlgorithmException
  {
    try {
      return (Certificate)((Class)formats.get(name)).newInstance();
    } catch( Exception e ) {
      throw new NoSuchAlgorithmException();
    }
  }

  /**
   * Return the Class object of the class implementing the certificate
   * format name.
   * @exception NoSuchAlgorithmException if the format is not installed.
   */
  public static Class getImplementor(String name) throws NoSuchAlgorithmException
  {
    if( isInstalled(name) ) {
      return (Class)formats.get(name);
    } else {
      throw new NoSuchAlgorithmException();
    }
  }

  /**
   * Prevent instantiation of the class using a compiler generated
   * default constructor by declaring a private constructor.
   */
  private CertFormatRegistry()
  {
    super();
  }
}
