/*
 * @(#)IdentityScope.java	1.36 97/09/19
 * 
 * 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.Serializable;
import java.util.Enumeration;
import java.util.Properties;

/** 
 * <p>Represents a scope for identities. It is an identity 
 * itself, and therefore has a name, can have a scope, and can 
 * optionally have a public key and associated certificates.
 *
 * <p>An IdentityScope can contain identity objects of all kinds,
 * including signers. All types of identity objects can be retrieved,
 * added, and removed using the same methods. Note that it is possible,
 * and in fact expected, that different types of identity scopes will
 * apply different policies for their various operations on the
 * various types of identities.
 *
 * <p>There is a one-to-one mapping between keys and identities, and 
 * there can be only one copy of one key per scope. For example, suppose
 * Acme Software, Inc is a software publisher known to a user.
 * Suppose it is an Identity, that is, it has a public key and a set of
 * associated certificates. It is named in the scope using the name 
 * Acme Software. No other named identity in the scope has the same 
 * public  key or the same name.
 *
 * @see Identity
 * @see Principal
 * @see Key
 *
 * @version 1.36 98/01/14
 * @author Benjamin Renaud */
public abstract 
class IdentityScope extends Identity {

    /* The system's scope */
    private static IdentityScope scope;

    // initialize the system scope
    private static void initializeSystemScope() {

//	String classname = Security.getProperty("system.scope");
   String classname = "com.novell.service.session.xplat.XplatIdentityScope";

	if (classname == null) {
	    return;

        } else {

	    try {
		Class.forName(classname);
	    } catch (ClassNotFoundException e) {
//		Security.error("unable to establish a system scope from " +
//			       classname);
		e.printStackTrace();
	    }
	}
    }

    /**
     * @internal
     *
     * This constructor is used for serialization only and should not
     * be used by subclasses.
     */
    protected IdentityScope() {
	this("restoring...");
    }

    /**
     * Constructs a new identity scope with the specified name.
     *
     * @param The name of the scope.
     */
    public IdentityScope(String name) {
	super(name);
    }

    /**
     * Constructs a new IdentityScope with the specified name
     * and scope.
     * 
     * @param name  The name of the IdentityScope.
     * @param scope The scope for the new IdentityScope.
     * 
     * @exception KeyManagementException Thrown if there is already
     *            an identity with the same name in the scope.
     */
    public IdentityScope(String name, IdentityScope scope) 
    throws KeyManagementException {
	super(name, scope);
    }

    /**
     * Returns the system's IdentityScope. See the
     * System Identity Scope section in Sun's Java Cryptography
     * Architecture API Specification & Reference documentation.
     * 
     * @return The system's IdentityScope.
     */
    public static IdentityScope getSystemScope() {
	if (scope == null) {
	    initializeSystemScope();
	}
	return scope;
    }


    /**
     * Sets the system's IdentityScope. See the System Identity
     * Scope section in the Java Cryptography Architecture API
     * Specification & Reference documentation.
     *
     * @param scope The scope to set.
     */
    protected static void setSystemScope(IdentityScope scope) {
	check("IdentityScope.setSystemScope");
	IdentityScope.scope = scope;
    }

    /**
     * Returns the number of identities within this IdentityScope.
     * 
     * @return The number of identities within this IdentityScope.
     */
    public abstract int size();

    /**
     * Returns the identity of the specified name in this scope, or
     * NULL if there are no identities named.
     * 
     * @param name The name of the identity to be retrieved.
     * 
     * @return The identity of the specified name or NULL.
     */
    public abstract Identity getIdentity(String name);

    /**
     * Retrieves the identity whose name is the same as that of the 
     * specified Principal, or NULL if there are no identities of
     * the same name in this scope. Note that Identity implements
     * Principal.
     *
     * @param principal The Principal corresponding to the identity
     *                  to be retrieved.
     * 
     * @return The identity whose name is the same as that of the 
     *         principal, or NULL.
     */
    public Identity getIdentity(Principal principal) {
	return getIdentity(principal.getName());
    }

    /**
     * Retrieves the identity with the specified PublicKey.
     *
     * @param key The PublicKey for the identity to be returned.
     *
     * @return The identity for the specified PublicKey, or NULL
     * if there are no identities in this scope with that key.
     */
    public abstract Identity getIdentity(PublicKey key);

    /**
     * Adds an identity to this IdentityScope.
     *
     * @param The Identity to be added to this IdentityScope.
     *
     * @exception KeyManagementException Thrown if the identity is not
     * valid, a name conflict occurs, another identity has the same
     * public key as the identity being added, or another exception
     * occurs.
     */
    public abstract void addIdentity(Identity identity) 
    throws KeyManagementException;

    /**
     * Removes an identity from this IdentityScope.
     *
     * @param identity The Identity to be removed.
     *
     * @exception KeyManagementException Thrown if the identity is
     *            missing, or another exception occurs.
     */
    public abstract void removeIdentity(Identity identity) 
    throws KeyManagementException;

    /**
     * Returns an enumeration of all identities in this IdentityScope.
     * 
     * @return An enumeration of all identities in this IdentityScope.
     */
    public abstract Enumeration identities();

    /**
     * Generates a short String representation of this IdentityScope,
     * including its name, its scope name, and the number of identities
     * included. The returned string, which textually represents the
     * object, should be a concise but informative representation that
     * is easy to read.
     *
     * @return A String containing information about this IdentityScope.
     */
    public String toString() 
	 {
			if(IdentityScope.scope != null)
				return super.toString() + "[" + size() + "]("+IdentityScope.scope.getName()+")";

			return super.toString() + "[" + size() + "]";
    }

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

}
