/*
 * @(#)Provider.java	1.27 97/10/10
 * 
 * Copyright 1993-1997 Sun Microsystems, Inc. 901 San Antonio Road, 
 * Palo Alto, California, 94303, U.S.A.  All Rights Reserved.
 * 
 * This software is the confidential and proprietary information of Sun
 * Microsystems, Inc. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Sun.
 * 
 * CopyrightVersion 1.2
 * 
 */

package com.novell.java.security;

import java.io.*;
import java.util.*;

/**
 * Represents a provider for the Java Security API. A provider
 * implements some or all parts of Java Security, including:
 *
 * <ul><li>Algorithms (such as DSA, RSA, MD5 or SHA-1).
 * <li>Key generation and management facilities (such as for
 * algorithm-specific keys).
 * </ul>
 *
 * <p>Each provider has a name and a version number, and is configured
 * in each runtime in which it is installed. The default JDK
 * provider is the SUN Provider. See The Provider Class in Sun's
 * Java Cryptography Architecture API Specification & Reference
 * documentation for information about how providers work and how
 * to install them.
 * 
 * @version 1.27 98/01/14
 * @author Benjamin Renaud */

public abstract class Provider extends Properties {

    private String name;
    private String info;
    private double version;

    /**
     * Constructs a provider with the specified name, version number,
     * and information string.
     *
     * @param name The name of the provider.
     *
     * @param version The provider version number.
     * 
     * @param info A description of the provider and its services.
     */
    protected Provider(String name, double version, String info) {
	this.name = name;
	this.version = version;
	this.info = info;
    }

    /**
     * Constructs a provider with the specified name. Assigns it
     * version 1.0.
     *
     * @param name the provider name.  
     */
    Provider(String name) {
	this(name, 1.0, "no information available");
    }

    /**
     * Returns the name of this provider.     
     * 
     * @return The name of this provider.
     */
    public String getName() {
	return name;
    }

    /**
     * Returns the version number for this provider.     
     * 
     * @return The version number for this provider.
     */
    public double getVersion() {
	return version;
    }

    /**
     * Returns a description of the provider and its services in
     * String format. It may be an HTML page, with relevant links.
     *
     * @return A description of the provider and its services.  
     */
    public String getInfo() {
	return info;
    }


    static Provider loadProvider(String name) {
	
	try {
	    Class cl = Class.forName(name);
	    Object instance = cl.newInstance();

	    if (instance instanceof Provider) {
		return (Provider)instance;
	    }

	} catch (Exception e) {
	    debug("error loading provider " + name, e);
	}
	return null;
    }


    /**
     * Returns a string containing the name and the version number
     * of this provider.     
     * 
     * @return A string with the name and the version number
     * of this provider.
     */
    public String toString() {
	return name + " version " + version;
    }

    /*
     * override 3 methods from Hashtable to ensure that provider
     * information can only be changed if the caller has the appropriate
     * permissions.
     */

    /**
     * Clears this provider so that it no longer contains the properties
     * used to look up facilities implemented by the provider.
     *
     * @since JDK1.2
     */
    public synchronized void clear() {
	check("Provider.clear."+name);
	super.clear();
    }

    /**
     * Sets the key property to have the specified value.
     * 
     * @param key The property key.
     * 
     * @param value The property value.
     * 
     * @return The previous value of the specified property
     * key, or NULL if it did not have one.
     * 
     * @since JDK1.2
     */
    public synchronized Object put(Object key, Object value) {
	check("Provider.put."+name);
	return super.put(key, value);
    }

    /**
     * Removes the key property and its corresponding 
     * value.
     * 
     * @param key The key for the property to be removed.
     * 
     * @return The value to which the key had been mapped,
     *         or NULL if the key did not have a mapping.
     * 
     * @since JDK1.2
     */
    public synchronized Object remove(Object key) {
	check("Provider.remove."+name);
	return super.remove(key);
    }

    private static void check(String directive) {
         SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkSecurityAccess(directive);
        }
    }

    private static void debug(String msg) {
//	Security.debug(msg);
    }

    private static void debug(String msg, Throwable t) {
//	Security.debug(msg, t);
    }

    // Declare serialVersionUID to be compatible with JDK1.1
    static final long serialVersionUID = -4298000515446427739L;    
}

