ServiceManager.java revision 8af80418ba1ec431c8027fa9668e5678658d3611
/**
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2005 Sun Microsystems Inc. All Rights Reserved
*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License). You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* See the License for the specific language governing
* permission and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* Header Notice in each file and include the License file
* at opensso/legal/CDDLv1.0.txt.
* If applicable, add the following below the CDDL Header,
* with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* $Id: ServiceManager.java,v 1.27 2009/10/28 04:24:26 hengming Exp $
*
*/
/*
* Portions Copyrighted 2012 ForgeRock Inc
*/
/**
* services and to list currently registered services. It also provides methods
* to obtain an instance of <code>ServiceSchemaManager</code> and an instance
* of <code>ServiceConfigManager</code>.
*
* @supported.api
*/
public class ServiceManager {
// Initialization parameters
private static boolean initialized;
private static boolean loadedAuthServices;
// For realms and co-existance support
protected static HashMap serviceNameDefaultVersion =
new CaseInsensitiveHashMap();
public static final String REALM_SERVICE =
"sunidentityrepositoryservice";
protected static final String DEFAULT_SERVICES_FOR_REALMS =
"serviceNamesForAutoAssignment";
protected static final String ATTR_SERVER_LIST =
"iplanet-am-platform-server-list";
private static boolean realmCache;
private static boolean coexistenceCache = true;
private static boolean ditUpgradedCache;
protected static Set requiredServices;
protected static Set defaultServicesToLoad;
// constants for IdRepo management
// List of sub-services
protected static CachedSubEntries serviceNames;
protected static Set accessManagerServers;
// SSOToken of the caller
// Debug & I18n
private static boolean amsdkChecked;
private static boolean isAMSDKEnabled;
/**
* Creates an instance of <code>ServiceManager</code>.
* The <code>SSOToken</code> is used to identify the user performing
* service operations.
*
* @param token
* the authenticated single sign on token.
* @throws SSOException
* if the user's single sign on token is invalid or expired
* @throws SMSException
* if an error occurred while performing the operation
*
* @supported.api
*/
// Initilaize the static variables and caches
// Validate SSOToken
}
/**
* Returns the <code>ServiceSchemaManager</code> for
* the given service name and version.
*
* @param serviceName
* the name of the service
* @param version
* the version of the service
* @return the <code>ServiceSchemaManager</code> for the given service
* name and version
* @throws SSOException
* if the user's single sign on token is invalid or expired
* @throws SMSException
* if an error occurred while performing the operation
*
* @supported.api
*/
}
/**
* Returns the <code>ServiceConfigManager</code> for
* the given service name and version.
*
* @param serviceName
* the name of the service
* @param version
* the version of the service
* @return the <code>ServiceConfigManager</code> for the given service
* name and version.
* @throws SSOException
* if the user's single sign on token is invalid or expired
* @throws SMSException
* if an error occurred while performing the operation
*
* @supported.api
*/
}
/**
* Returns the <code>OrganizationConfigManager</code> for the given
* organization name. If the <code>orgName</code> either <code>
* null</code>
* or empty or "/", the organization configuration for the root organization
* will be returned.
*
* @param orgName
* the name of the organization
* @return the <code>OrganizationConfigManager</code> for the given
* organization name
*
* @throws SSOException
* if the user's single sign on token is invalid or expired
* @throws SMSException
* if an error occurred while performing the operation
*/
}
/**
* Returns all the service names that have been
* registered.
*
* @return the set of names of services that have been registered
* @throws SMSException
* if an error occurred while performing the operation
*
* @supported.api
*/
try {
if (serviceNames == null) {
}
} catch (SSOException s) {
throw (new SMSException(s, "sms-service-not-found"));
}
}
/**
* Returns a map of service names and the related object classes for the
* given <code>schemaType</code>.
*
* @param schemaType
* name of the schema
* @return Map of service names and objectclasses
*/
if (schemaType == null) {
schemaType = "filteredrole";
}
try {
try {
if (isCoexistenceMode()) {
// For backward compatibility, get the
// version from the service.
// no hardcoding to '1.0', even if it
// improves performance in OpenSSO.
// Otherwise, it breaks for services like
// iplanetAMProviderConfigService with
// '1.1' as version.
} else {
}
// Check if service has schemaType
if (schemaType != null &&
schemaType)) == null) {
// If the schema type is "User"
// check for "Dynamic" also
== null)
{
continue;
}
// If the schema type is "Role:
// check for "Dynamic" also
if (schemaType.toLowerCase()
== null)
{
continue;
}
}
{
}
}
}
} catch (SMSException smse) {
// continue with next service. Best effort to get
// all service names.
if (debug.messageEnabled()) {
"ServiceManager.getServiceNamesandOCs"
+ " caught SMSException ", smse);
}
}
}
}
} catch (SMSException smse) {
// ignore
if (debug.messageEnabled()) {
+ " caught SMSException ", smse);
}
} catch (SSOException ssoe) {
// ignore
if (debug.messageEnabled()) {
+ " caught SSOException ", ssoe);
}
}
}
}
/**
* Returns all versions supported by the service.
*
* @param serviceName
* service name.
* @return the set of versions supported by the service
* @throws SMSException
* if an error occurred while performing the operation
*
* @supported.api
*/
try {
} catch (SSOException s) {
throw (new SMSException(s, "sms-version-not-found"));
}
}
/**
* Registers one or more services, defined by the XML
* input stream that follows the SMS DTD.
*
* @param xmlServiceSchema
* the input stream of service metadata in XML conforming to SMS
* DTD.
* @return set of registered service names.
* @throws SMSException if an error occurred while performing the operation.
* @throws SSOException if the user's single sign on token is invalid or
* expired.
*
* @supported.api
*/
throws SMSException, SSOException {
}
/**
* Registers one or more services, defined by the XML
* input stream that follows the SMS DTD.
*
* @param xmlServiceSchema
* the input stream of service metadata in XML conforming to SMS
* DTD.
* @param decryptObj Object to decrypt the password in the XML.
* @return set of registered service names.
* @throws SMSException if an error occurred while performing the operation
* @throws SSOException if the user's single sign on token is invalid or
* expired.
*/
public Set registerServices(
) throws SMSException, SSOException {
// Validate SSO Token
// Get the XML document and get the list of service nodes
if (!validSMSDtdDocType(doc)) {
}
// Before validating service schema, we need to check
// for AttributeSchema having the syntax of "password"
// and if present, encrypt the DefaultValues if any
// Create service schema
// Obtain the SMSSchema for Schema and PluginSchema
// Check if the schema element exists
// Update the service name and version cached SMSEntry
if (serviceNames == null) {
}
// Not present, hence create it and add it
}
}
// Check if PluginSchema nodes exists
{
}
!= null) {
}
}
clearCache();
}
/*
* Need to do this after all the schema has been loaded
*/
/*
* Store the configuration, will throw exception if
* the service configuration already exists
*/
configNode, true, decryptObj);
}
return sNames;
}
throws SMSException, SSOException {
}
public Document parseServicesFile(
) throws SMSException, SSOException {
// Validate SSO Token
//Set<SMSSchema> smsSchemas = new HashSet<SMSSchema>();
// Get the XML document and get the list of service nodes
return doc;
}
/*
if (!validSMSDtdDocType(doc)) {
throw new SMSException(IUMSConstants.UMS_BUNDLE_NAME,
IUMSConstants.SMS_xml_invalid_doc_type, null);
}
// Before validating service schema, we need to check
// for AttributeSchema having the syntax of "password"
// and if present, encrypt the DefaultValues if any
checkAndEncryptPasswordSyntax(doc, true, decryptObj);
// Create service schema
NodeList nodes = doc.getElementsByTagName(SMSUtils.SERVICE);
for (int i = 0; (nodes != null) && (i < nodes.getLength()); i++) {
Node serviceNode = nodes.item(i);
String name = XMLUtils.getNodeAttributeValue(serviceNode,
SMSUtils.NAME);
String version = XMLUtils.getNodeAttributeValue(serviceNode,
SMSUtils.VERSION);
// Obtain the SMSSchema for Schema and PluginSchema
SMSSchema smsSchema = new SMSSchema(name, version, doc);
smsSchemas.put(name, smsSchema);
}
// Check if the schema element exists
/*if (XMLUtils.getChildNode(serviceNode, SMSUtils.SCHEMA) != null) {
validateServiceSchema(serviceNode);
ServiceSchemaManager.createService(token, smsSchema);
// Update the service name and version cached SMSEntry
if (serviceNames == null) {
serviceNames = CachedSubEntries.getInstance(token,
serviceDN);
}
serviceNames.add(name);
CachedSubEntries sVersions = (CachedSubEntries) serviceVersions
.get(name);
if (sVersions == null) {
// Not present, hence create it and add it
sVersions = CachedSubEntries.getInstance(token,
getServiceNameDN(name));
serviceVersions.put(name, sVersions);
}
sVersions.add(version);
sNames.add(name);
}
// Check if PluginSchema nodes exists
for (Iterator pluginNodes = XMLUtils.getChildNodes(serviceNode,
SMSUtils.PLUGIN_SCHEMA).iterator(); pluginNodes.hasNext();)
{
Node pluginNode = (Node) pluginNodes.next();
PluginSchema.createPluginSchema(token, pluginNode, smsSchema);
}
if (XMLUtils.getChildNode(serviceNode, SMSUtils.CONFIGURATION)
!= null) {
serviceNodes.add(serviceNode);
}
}
if (serviceNodes.size() > 0) {
clearCache();
}
/*
* Need to do this after all the schema has been loaded
*/
/*
for (Iterator i = serviceNodes.iterator(); i.hasNext(); ) {
Node svcNode = (Node)i.next();
String name = XMLUtils.getNodeAttributeValue(svcNode,
SMSUtils.NAME);
String version = XMLUtils.getNodeAttributeValue(svcNode,
SMSUtils.VERSION);
Node configNode = XMLUtils.getChildNode(svcNode,
SMSUtils.CONFIGURATION);
/*
* Store the configuration, will throw exception if
* the service configuration already exists
*/
/*
CreateServiceConfig.createService(this, name, version,
configNode, true, decryptObj);
}
return sNames;
return smsSchemas;
}*/
boolean valid = false;
if (idx != -1) {
}
}
}
return valid;
}
/**
* Adds a new plugin schema to an existing service
*
* @param pluginDoc
* @throws SMSException if an error occurred while performing the operation
* @throws SSOException if the user's single sign on token is invalid or
* expired.
*/
throws SMSException, SSOException {
// Validate SSO Token
// Obtain the SMSSchema for Schema and PluginSchema
}
/**
* Removes a plugin schema from a service
*
* @param serviceName The name of the service
* @param interfaceName The name of the plugin interface
* @param pluginName The name of the plugin schema
* @throws SMSException if an error occurred while performing the operation
* @throws SSOException if the user's single sign on token is invalid or
* expired.
*/
throws SMSException, SSOException {
// Check if PluginSchema nodes exists
// if they match, delete
// Construct the DN and get CachedSMSEntry
try {
} catch (SSOException ssoe) {
}
} else {
throw new SMSException("Condition does not exist");
}
if (debug.messageEnabled()) {
"from service " + serviceName);
}
}
/**
* Removes the service schema and configuration for
* the given service name.
*
* @param serviceName
* the name of the service
* @param version
* the version of the service
* @throws SMSException
* if an error occurred while performing the operation
* @throws SSOException
* if the user's single sign on token is invalid or expired
*
* @supported.api
*/
throws SMSException, SSOException {
// Find all service entries that have the DN
// Search for (&(ou=<serviceName>)(objectclass=top))
// construct the rdn with the given version, look for the entry
// in iDS and if entry exists(service with that version), delete.
"sms-SERVICE_CORE_CANNOT_DELETE", args));
}
configdn);
if (configsmse.isDirty()) {
}
if (!confige.isNewEntry()) {
}
// If there are no other service version nodes for that service,
// delete that node(schema).
}
}
}
}
/**
* Deletes only the schema for the given service name. This is provided only
* for backward compatibility for DSAME 5.0 and will be deprecated in the
* future release. Alternative is to use
* <code>ServiceSchemaManager.replaceSchema()</code>.
*
* @param serviceName
* Name of service to be deleted.
* @throws SMSException
* if an error occurred while performing the operation
* @throws SSOException
* if the user's single sign on token is invalid or expired
*/
"sms-SERVICE_CORE_CANNOT_DELETE", args));
}
}
}
}
/**
* Returns the base DN (or root DN) that was set in
* <code>serverconfig.xml</code> at install time.
*/
}
/**
* Returns all AM Server instance. Read the configured servers from platform
* service's <code>iplanet-am-platform-server-list</code>
*/
public static Set getAMServerInstances() {
// Check cache
if (accessManagerServers == null) {
// Get AdminToken
try {
if (debug.messageEnabled()) {
+ "server list: " + accessManagerServers);
}
} catch (SMSException e) {
if (debug.warningEnabled()) {
"Unable to get server list", e);
}
} catch (SSOException e) {
if (debug.warningEnabled()) {
"Unable to get server list", e);
}
}
}
}
/**
* Returns organization names that match the given attribute name and
* values. Only exact matching is supported, and if more than one value is
* provided the organization must have all these values for the attribute.
* Basically an AND is performed for attribute values for searching.
*
* @param serviceName
* service name under which the attribute is to be sought.
* @param attrName
* name of the attribute to search.
* @param values
* set of attribute values to search.
* @return organizations that match the attribute name and values.
* @throws SMSException
* if an error occurred while performing the operation.
* @throws SSOException
* if the user's single sign on token is invalid or expired.
*/
try {
if (subEntries == null) {
}
} catch (SSOException ssoe) {
+ "get sub organization names", ssoe);
.getString("sms-INVALID_SSO_TOKEN"),
"sms-INVALID_SSO_TOKEN"));
}
}
/**
* Removes all the SMS cached entries. This method
* should be called to clear the cache for example, if ACIs for the SMS
* entries are changed in the directory. Also, this clears the SMS entries
* only in this JVM instance. If multiple instances (of JVM) are running
* this method must be called within each instance.
*
* @supported.api
*/
public synchronized void clearCache() {
// Clear the local caches
serviceNameAndOCs = new CaseInsensitiveHashMap();
serviceVersions = new CaseInsensitiveHashMap();
amsdkChecked = false;
// Call respective Impl classes
// ServiceSchemaManagerImpl.clearCache();
// Re-initialize the flags
try {
} catch (Exception e) {
"re-initialize global flags", e);
}
}
/**
* Returns the flag which lets IdRepo and SM know that we are running in the
* co-existence mode.
*
* @return true or false depending on if the coexistence flag is enabled or
* not.
*/
public static boolean isCoexistenceMode() {
return (coexistenceCache);
}
/**
* Returns the version for a service. This is to handle the co-existence
* of OpenSSO and AM 7.1 in realm mode. The co-existence of OpenSSO and
* AM 7.1 in legacy mode is handled by the call to isCoexistenceMode()
* method. There is a special service named "iPlanetAMProviderConfigService"
* used in AM 7.x code for ID-FF metadata, the version for the service
* is "1.1", all the rest of service is "1.0" right now. This method can
* be removed if no need to support Co-existence of OpenSSO and AM 7.x
* any more.
* @param serviceName Name of the service.
* @return version of the service, the value will be 1.0 or 1.1.
*/
return "1.1";
} else {
return "1.0";
}
}
/**
* Returns <code>true</code> if current service
* configuration uses the realm model to store the configuration data.
*
* @return <code>true</code> is realm model is used for storing
* configuration data; <code>false</code> otherwise.
*
* @supported.api
*/
public static boolean isRealmEnabled() {
if (!initialized) {
try {
+ "initialize", ssme);
}
}
return (realmCache);
}
/**
* Returns <code>true</code> if AMSDK IdRepo plugin is
* configured in any of the realms
*/
public static boolean isAMSDKConfigured() throws SMSException {
// Legacy mode, AMSDK is configured by default
return (true);
}
// Iterate through all the realms to check if AMSDK is configured
.getSubOrganizationNames("*", true);
return (true);
}
}
return (false);
}
/**
* Returns <code>true</code> if configuration data has been migrated to
* Access Manager 7.0. Else <code>false</code> otherwise.
*
* @return <code>true</code> if configuration data has been migrated to AM
* 7.0; <code>false</code> otherwise
*/
public static boolean isConfigMigratedTo70() {
return (ditUpgradedCache);
}
// ------------------------------------------------------------
// Protected methods
// ------------------------------------------------------------
// Called by CreateServiceConfig.java to create LDAP entries
SSOToken getSSOToken() {
return (token);
}
return (
}
}
{
}
throws SMSException, SSOException {
.get(serviceName);
throw (new ServiceNotFoundException(
}
}
}
boolean encrypt
) throws SMSException {
}
protected static void checkAndEncryptPasswordSyntax(
boolean encrypt,
) throws SMSException {
// Get the node list of all AttributeSchema
// Check if the "syntax" attribute is "password"
if (debug.messageEnabled()) {
}
// Get the DefaultValues and encrypt then
// Get NodeList of "Value" nodes and encrypt them
.hasNext();) {
// skip empty passwords
continue;
}
if (encrypt) {
if (encryptObj != null) {
.doPrivileged(new DecodeAction(
value, encryptObj));
try {
byte[] b = new byte[1];
b[0] = -96;
} catch (UnsupportedEncodingException e) {
//ignore
}
}
}
new EncodeAction(value));
} else {
new DecodeAction(value));
try {
//this is catch the whitespace for password
encValue = "&#160;";
}
} catch (UnsupportedEncodingException e) {
//ignore
}
if (encryptObj != null) {
.doPrivileged(new EncodeAction(
encValue, encryptObj));
}
}
// Construct the encrypted "Value" node
// Replace the node
}
}
}
}
}
throws SMSException {
}
}
return (true);
}
// Gets called by OrganizationConfigManager when service schema has changed
protected static void schemaChanged() {
// Reset the service names and OCs used by IdRepo
serviceNameAndOCs = new CaseInsensitiveHashMap();
// Reset the schema types and service names
// Reset the service names
serviceNames = null;
}
} else {
throw (new ServiceNotFoundException(
msgs));
}
}
return (version);
}
/**
* Returns service names that will be assigned to a realm during creation.
*/
public static Set servicesAssignedByDefault() {
if (!loadedAuthServices) {
if (debug.messageEnabled()) {
+ "defaultServicesToLoad = " + defaultServicesToLoad);
}
loadedAuthServices = true;
}
return (defaultServicesToLoad);
}
/**
* Returns service names configured via IdRepo service to be
* added as required services
*/
static Set requiredServices() {
return (requiredServices);
}
// Validate SSOToken
// Check if already initialized
if (initialized)
return;
// Initilaize the parameters
try {
// Get the service names and cache it
if (debug.warningEnabled()) {
+ "does not exists: " + serviceDN);
}
}
} catch (SMSException e) {
+ serviceDN, e);
throw (e);
}
// Check if realm is enabled and set appropriate flags
initialized = true;
}
try {
}
if (!entry.isNewEntry()) {
ditUpgradedCache = true;
return;
}
coexistenceCache = false;
}
realmCache = true;
}
// Get the default services to be loaded
defaultServicesToLoad = new HashSet();
// Make this flag false, for always the union of
// auto assignment services from idRepoService.xml and
// auth services from AMAuthenticationManager code
// should be returned for deep copy for a newly created
// sub realm.
loadedAuthServices = false;
}
if (debug.messageEnabled()) {
+ realmCache);
+ coexistenceCache);
}
} catch (SMSException e) {
+ "if Realm is enabled: ", e);
throw (e);
}
}
throws SMSException, SSOException
{
.append("\n")
.append("<!DOCTYPE ServicesConfiguration\n")
.append(
"PUBLIC \"=//iPlanet//Service Management Services (SMS) 1.0 DTD//EN\"\n")
ServiceSchemaManager ssm = new
serviceName, token);
}
}
}
/**
* in IdRepo Service Configuration schema
*/
public static boolean isAMSDKEnabled() {
if (amsdkChecked) {
return (isAMSDKEnabled);
}
try {
if (!ServiceManager.isRealmEnabled()) {
amsdkChecked = true;
// If in legacy mode, then amSDK plugin would always be there.
isAMSDKEnabled = true;
} else {
isAMSDKEnabled = true;
}
amsdkChecked = true;
}
} catch (Exception e) {
"Error in checking AM.SDK being configured", e);
}
amsdkChecked = true;
return (isAMSDKEnabled);
}
}