/*
* 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
* https://opensso.dev.java.net/public/CDDLv1.0.html or
* opensso/legal/CDDLv1.0.txt
* 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: ConfigManagerUMS.java,v 1.6 2009/01/28 05:34:50 ww203982 Exp $
*
* Portions Copyrighted 2011-2015 ForgeRock AS.
*/
package com.iplanet.ums;
import java.security.AccessController;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import com.iplanet.am.util.Cache;
import com.iplanet.services.ldap.Attr;
import com.iplanet.services.ldap.AttrSet;
import com.iplanet.services.ldap.DSConfigMgr;
import com.iplanet.services.ldap.LDAPUser;
import com.iplanet.services.ldap.ServerInstance;
import com.iplanet.services.util.I18n;
import com.iplanet.sso.SSOException;
import com.iplanet.sso.SSOToken;
import com.iplanet.sso.SSOTokenManager;
import com.iplanet.ums.util.GuidUtils;
import com.sun.identity.authentication.internal.AuthContext;
import com.sun.identity.authentication.internal.AuthPrincipal;
import com.sun.identity.security.ServerInstanceAction;
import com.sun.identity.shared.debug.Debug;
import com.sun.identity.sm.SMSException;
import com.sun.identity.sm.ServiceConfig;
import com.sun.identity.sm.ServiceConfigManager;
import org.forgerock.openam.ldap.LDAPUtils;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.RDN;
import org.forgerock.opendj.ldap.SearchScope;
/**
* Configuration Manager is responsible for getting configuration parameters for
* UMS. ConfigManager is implemented as a singleton and the configurations can
* be accessed as follows:
* <p>
*
* <pre>
* ConfigManager cm = ConfigManager.getConfigManager();
* AttrSet tempAtts=
* cm.getTemplate(&quot;o=foo,o=isp&quot;, &quot;BasicUser&quot;);
* Set hs =
* cm.getEntity(&quot;o=foo,o=isp&quot;,
* &quot;com.iplanet.ums.PeopleContainer&quot; );
* String [] sTemplateNames =
* cm.getCreationTemplateNames(&quot;o=foo, o=isp&quot;); *
* </pre>
*
* ConfigManager obsoletes the use of previous Config class which opens up
* resource file and reading whenever a configuation is needed. ConfigManager
* speeds up the retrieval in caching the configurations at start up time once
* as a singleton and share it among the ums package. ConfigManager uses the
* default PROXY as AuthPrincipal for this instance of the server.
*
* </p>
*/
public class ConfigManagerUMS implements java.io.Serializable {
/**
* i18n keys
*/
static final String ERROR_CM_INITIATE = "error-cminitiate";
static final String ERROR_CM = "error-cm";
private static I18n i18n = I18n.getInstance(IUMSConstants.UMS_PKG);
/**
* Get the singleton instance of Config Manager.
*
* @return Singleton instance of Configuration Manager.
*/
public static synchronized ConfigManagerUMS getConfigManager()
throws ConfigManagerException {
if (_instance == null) {
try {
_instance = new ConfigManagerUMS();
} catch (Exception e) {
_debug.error(e.toString());
String args[] = new String[1];
args[0] = e.toString();
throw new ConfigManagerException(i18n.getString(
IUMSConstants.ERROR_CM_INITIATE, args));
}
}
return _instance;
}
/**
* Reads the directory server, via SMS APIs for a given org (/b/a) and for a
* given template (<code>StructureTemplates</code>,
* <code>CreationTemplates</code>, etc.).
*
* @param org Name of organization <code>/pepsi/coke</code>.
* @param c List of template names.
* @param template Name of template.
*/
private void loadCache(String org, Set c, String template) {
//
// To get all attributes for each component name from DS and store
// in cache. Calls getServiceAttrs()
//
Iterator iter = c.iterator();
String entName = "";
AttrSet attrSet = null;
while (iter.hasNext()) {
entName = iter.next().toString();
Map entityAttributes = new HashMap();
attrSet = new AttrSet();
try {
entityAttributes = getServiceAttributes(org, entName);
} catch (SMSException smse) {
// Don't throw an exception, just log it. Cache will return
// a null
_debug.error("ConfigManager->loadCache: SMSException: "
+ smse.toString());
} catch (SSOException ssoe) {
// Don't throw an exception, just log it. Cache will return
// a null
_debug.error("ConfigManager->loadCache: SSOException: "
+ ssoe.toString());
}
if (entityAttributes.isEmpty())
continue;
for (Iterator it = entityAttributes.entrySet().iterator(); it
.hasNext();) {
Map.Entry ent = (Map.Entry) it.next();
Set hs = (Set) ent.getValue();
Iterator itera = hs.iterator();
itera = hs.iterator();
while (itera.hasNext()) {
attrSet.add(new Attr((String) ent.getKey(), (String) itera
.next()));
}
}
String key = org + "/" + template + "/";
Attr classAttr = null;
if (template.equals(ENTITY)) {
// This search is for EntityManager
classAttr = attrSet.getAttribute(CLASS);
if (classAttr != null) {
Set hs = new HashSet();
if (_cch.containsKey(key + classAttr.getValue())) {
hs = (Set) _cch.get(key + classAttr.getValue());
hs.add(attrSet);
} else {
hs.add(attrSet);
}
_cch.put(key + classAttr.getValue(), hs);
if (_debug.messageEnabled())
_debug.message("ConfigManager->loadCache KEY:" + key
+ classAttr.getValue() + " VALUE:" + hs);
}
int l = entName.lastIndexOf("/");
String cname = entName.substring(l + 1);
// This search is for EntityManager
Set hset = new HashSet();
hset.add(attrSet);
_cch.put(key + cname, hset);
if (_debug.messageEnabled())
_debug.message("ConfigManager->loadCache KEY:" + key
+ cname + " VALUE:" + hset);
}
// } else {
if ((template.equals(SEARCH)) || template.equals(CREATION)) {
// This search is for TemplateManager
classAttr = attrSet.getAttribute(JAVACLASS);
if (classAttr != null) {
_cch.put(key + classAttr.getValue(), attrSet);
if (_debug.messageEnabled())
_debug.message("ConfigManager->loadCache KEY:" + key
+ classAttr.getValue() + " VALUE:" + attrSet);
}
// This search is for TemplateManager
classAttr = attrSet.getAttribute(ATTRNAME);
if (classAttr != null) {
_cch.put(key + classAttr.getValue(), attrSet);
_debug.message("ConfigManager->loadCache KEY:" + key
+ classAttr.getValue() + " VALUE:" + attrSet);
}
}
if (template.equals(OBJECTRESOLVER)) {
// This adds the String[][] for ObjectResolver to cache
String oc_jc_map_string = attrSet.getValue(OC_JC_MAP);
if (oc_jc_map_string != null) {
_cch
.put(OBJECTRESOLVERPATH,
getOC_JC_MAP(oc_jc_map_string));
_debug.message("ConfigManager->loadCache KEY:"
+ OBJECTRESOLVERPATH + " VALUE:" + attrSet);
}
}
}
}
/**
* CACHE MANAGEMENT for entity and template components.
*
* @param org A string identifier for the cache.
* @throws ConfigManagerException
* The default components would be loaded through an XML
* schema/configuration file <code>ConfigManager</code> has to
* get the components and the related attributes from the directory
* Server initially to store them in the cache by calling the SMS
* API.
*/
void updateCache(String org) throws ConfigManagerException {
Set eNames = new HashSet();
Set sNames = new HashSet();
Set cNames = new HashSet();
// If org = "" (base level), then add OBJECTRESOLVER ATTRSET TO CACHE
if (org.equals(_rootDN)) {
Set oSet = new HashSet();
oSet.add(OBJECTRESOLVERPATH);
loadCache(org, oSet, OBJECTRESOLVER);
}
try {
eNames = getServiceComponents(org, ENTITYPATH, true);
} catch (SMSException smse) {
// Don't do anything. This is an LDAP problem,
// cache will just return NULL
if (_debug.warningEnabled())
_debug.warning("ConfigManager->updateCache: SMSException: "
+ smse.toString());
} catch (SSOException ssoe) {
// Don't do anything. This is an LDAP problem,
// cache will just return NULL
if (_debug.warningEnabled())
_debug.warning("ConfigManager->updateCache: SSOException: "
+ ssoe.toString());
}
try {
sNames = getServiceComponents(org, SEARCHPATH, true);
} catch (SMSException smse) {
// Don't do anything. This is an LDAP problem,
// cache will just return NULL
if (_debug.warningEnabled())
_debug.warning("ConfigManager->updateCache: SMSException: "
+ smse.toString());
} catch (SSOException ssoe) {
// Don't do anything. This is an LDAP problem,
// cache will just return NULL
if (_debug.warningEnabled())
_debug.warning("ConfigManager->updateCache: SSOException: "
+ ssoe.toString());
}
try {
cNames = getServiceComponents(org, CREATIONPATH, true);
} catch (SMSException smse) {
// Don't do anything. This is an LDAP problem,
// cache will just return NULL
if (_debug.warningEnabled())
_debug.warning("ConfigManager->updateCache: SMSException: "
+ smse.toString());
} catch (SSOException ssoe) {
// Don't do anything. This is an SSO problem,
// cache will just return NULL
if (_debug.warningEnabled())
_debug.warning("ConfigManager->updateCache: SSOException: "
+ ssoe.toString());
}
if (cNames.isEmpty() && eNames.isEmpty() && sNames.isEmpty()) {
_checkListCache.put(org.toLowerCase(), "dummy");
return;
}
// This is a search for searchTemplateNames only.
if (!sNames.isEmpty()) {
Iterator it = sNames.iterator();
Set set = new HashSet();
while (it.hasNext()) {
String s = new String();
String t;
t = (String) it.next();
int count = t.lastIndexOf("/");
s = t.substring(count + 1);
set.add(s);
}
_cch.put(org + "/" + SEARCH + "Names", set);
if (_debug.messageEnabled())
_debug.message("ConfigManager->updateCache: " + org + "/"
+ SEARCH + "Names :" + set);
}
// This is a search for creationTemplateNames only.
if (!cNames.isEmpty()) {
Iterator it = cNames.iterator();
Set set = new HashSet();
while (it.hasNext()) {
String s = new String();
String t;
t = (String) it.next();
int count = t.lastIndexOf("/");
s = t.substring(count + 1);
set.add(s);
}
_cch.put(org + "/" + CREATION + "Names", set);
if (_debug.messageEnabled())
_debug.message("ConfigManager->updateCache: " + org + "/"
+ CREATION + "Names :" + set);
}
loadCache(org, eNames, ENTITY);
loadCache(org, cNames, CREATION);
loadCache(org, sNames, SEARCH);
_checkListCache.put(org.toLowerCase(), "dummy");
}
private Set getServiceComponents(String orgName, String path, boolean b)
throws SMSException, SSOException {
ServiceConfig sc = (orgName.equals(_rootDN)) ? _smapi
.getGlobalConfig(null) : _smapi.getOrganizationConfig(orgName,
null);
if (sc == null) {
return new HashSet();
}
// Parser the "/" seperated path to get the right service config
StringTokenizer st = new StringTokenizer(path, "/");
while (st.hasMoreTokens()) {
String token = st.nextToken();
if ((token.length() == 0) || (token.length() == 0)) {
continue;
}
sc = sc.getSubConfig(token);
}
Set answer = new HashSet();
Iterator comps = sc.getSubConfigNames().iterator();
while (comps.hasNext()) {
answer.add(path + "/" + comps.next());
}
return (answer);
}
private Map getServiceAttributes(String orgName, String path)
throws SMSException, SSOException {
ServiceConfig sc = (orgName.equals(_rootDN)) ? _smapi
.getGlobalConfig(null) : _smapi.getOrganizationConfig(orgName,
null);
// Parser the "/" seperated path to get the right service config
StringTokenizer st = new StringTokenizer(path, "/");
while (st.hasMoreTokens()) {
String token = st.nextToken();
if ((token.length() == 0) || (token.length() == 0)) {
continue;
}
if (sc != null)
sc = sc.getSubConfig(token);
else
return (java.util.Collections.EMPTY_MAP);
}
if (sc != null)
return (sc.getAttributes());
else
return (java.util.Collections.EMPTY_MAP);
}
private void replaceServiceAttributes(String orgName, String path,
Map attrs)
throws SMSException, SSOException {
ServiceConfig sc = _smapi.getGlobalConfig(null);
// Parser the "/" seperated path to get the right service config
StringTokenizer st = new StringTokenizer(path, "/");
while (st.hasMoreTokens()) {
String token = st.nextToken();
if ((token.length() == 0) || (token.length() == 0)) {
continue;
}
sc = sc.getSubConfig(token);
}
sc.setAttributes(attrs);
}
void deleteOrgFromCache(String org) throws ConfigManagerException {
// Create this partial keys /b/a/StructureTemplates,
// /b/a/CreationTemplates,/b/a/SearchTemplate,
// so that with a root org, where the key would be ""
// everything doesn't get deleted in the cache.
String fdn;
if (org == null || org.length() == 0) {
// fdn = "";
fdn = _rootDN;
} else {
/*
* DN dn = new DN(org); DN root = new DN(_rootDN); String [] dns =
* dn.explodeDN(true); String [] rootdns = root.explodeDN(true); int
* len = dns.length; int rootLen = rootdns.length; StringBuffer sb =
* new StringBuffer(); for (int k=0; k<len-rootLen; k++) {
* sb.append("/").append(dns[len-k-rootLen -1]); } fdn =
* sb.toString();
*/
fdn = DN.valueOf(org).toString().toLowerCase();
}
String cchPartialKey1 = fdn + "/" + ENTITY;
String cchPartialKey2 = fdn + "/" + CREATION;
String cchPartialKey3 = fdn + "/" + SEARCH;
if (_debug.messageEnabled())
_debug.message("ConfigManager->deleteOrgFromCache: Deleting " + org
+ " from cache");
_checkListCache.remove(org.toLowerCase());
Enumeration e = _cch.keys();
while (e.hasMoreElements()) {
String key = (String) e.nextElement();
if ((key.indexOf(cchPartialKey1) == 0)
|| (key.indexOf(cchPartialKey2) == 0)
|| (key.indexOf(cchPartialKey3) == 0)) {
if (_debug.messageEnabled())
_debug.message("ConfigManager->deleteOrgFromCache: "
+ " Deleting..." + key);
_cch.remove(key);
}
}
// if org == "" (Base level) then remove ObjectResolver class too.
if (org.length() == 0 && _cch.containsKey(OBJECTRESOLVERPATH)) {
_cch.remove(OBJECTRESOLVERPATH);
_oc_jc_map = null;
}
}
/**
* Config management.
*
* @param guid GUID it is looking under.
* @param name Name for which AttrSets are needed.
* @param template Template name (<code>StructureTemplates</code>, etc.)
* @return either an <code>AttrSet</code> or a collection depending on
* caller.
*/
private Object getConfigData(Guid guid, String name, String template,
int lookup) throws ConfigManagerException {
// if guid is null, replace it use the rootDN
if (guid == null)
guid = new Guid(_rootDN);
// if guid is not "o=...", find the organization guid
/*
* if (!guid.getDn().startsWith("o=")) { guid =
* GuidUtils.getOrgGuid(guid); }
*/
DN dn = DN.valueOf(guid.getDn());
// Till we find what we are looking for,
// traverse the tree in the cache
while (true) {
String fdn = _rootDN;
boolean inCache = false;
boolean checkedDS = false;
String cacheKey = null;
//
// Explode the guid and build a string delimited by "/".
// ex: guid->o=b,o=a fdn->/b/a
// Build the cache key as fdn + name
// ex: /b/a/com.iplanet.ums.organization
// or /b/a/BasicUser
fdn = dn.toString().toLowerCase();
// Special case Cache Key for OBJECTRESOLVER
if (template.equals(OBJECTRESOLVER))
cacheKey = OBJECTRESOLVERPATH;
else
cacheKey = fdn + "/" + template + "/" + name;
if (_debug.messageEnabled())
_debug.message("ConfigManager->getConfigData: fdn=" + fdn
+ " cacheKey=" + cacheKey);
//
// Check the cache for the entry.
// If it's in the cache, return the information.
//
inCache = _cch.containsKey(cacheKey);
if (inCache) {
if (_debug.messageEnabled()) {
_debug.message("ConfigManager->getConfigData: get from " +
"cache for " + dn);
}
return _cch.get(cacheKey);
}
//
// If it's not in the cache, check if we've looked in the
// DS already. If we haven't checked the DS, go to the DS.
// "updateCache" will get the info from the DS and update
// both the cache (_cch) and _checkListCache.
//
checkedDS = _checkListCache.containsKey(fdn.toLowerCase());
if (!checkedDS) {
if (_debug.messageEnabled())
_debug.message("ConfigManager->getConfigData: updating " +
"cache for " + dn);
synchronized (lock_cch) {
updateCache(fdn);
}
if (_cch.containsKey(cacheKey))
return _cch.get(cacheKey);
}
//
// We've checked the DS already so get the parent and
// try again.
// Check if we need to traverse to the parent
switch (lookup) {
case TemplateManager.SCOPE_ORG:
return null;
case TemplateManager.SCOPE_TOP:
dn = DN.valueOf(_rootDN);
break;
case TemplateManager.SCOPE_ANCESTORS:
dn = dn.parent();
// After getting parent, check if this is already root of tree,
// if so return null
// if (dn.toString().length() == 0) return null;
if (dn.isInScopeOf(_root, SearchScope.WHOLE_SUBTREE)) {
break;
} else {
return null;
}
}
if (_debug.messageEnabled())
_debug.message("ConfigManager->getConfigData: Traversing " +
"parent: " + dn);
}
}
public Set getConfigTemplateNames(Guid guid, String template, int lookup)
throws ConfigManagerException {
// if guid is null, replace it use the rootDN
if (guid == null)
guid = new Guid(_rootDN);
// if guid is not "o=...", find the organization guid
if (!guid.getDn().startsWith("o=")) {
guid = GuidUtils.getOrgGuid(guid);
}
DN dn = DN.valueOf(guid.getDn());
while (true) {
String fdn = "";
boolean inCache = false;
boolean checkedDS = false;
String cacheKey = null;
//
// Explode the guid and build a string delimited by "/".
// ex: guid->o=b,o=a fdn->/b/a
// Build the cache key as fdn + name
// ex: /b/a/com.iplanet.ums.organization
// or /b/a/BasicUser
/*
* String[] dns = dn.explodeDN(true); String[] rootdns =
* root.explodeDN(true); int len = dns.length; int rootLen =
* rootdns.length; for (int k=0; k<len-rootLen; k++) { fdn = fdn +
* "/" + dns[len-k-rootLen-1]; }
*/
fdn = dn.toString().toLowerCase();
cacheKey = fdn + "/" + template + "Names";
//
// Check the cache for the entry.
// If it's in the cache, return the information.
//
if (_debug.messageEnabled())
_debug.message("ConfigManager->getConfigTemplateNames: " +
"Looking for: " + cacheKey);
inCache = _cch.containsKey(cacheKey);
if (inCache)
return (Set) _cch.get(cacheKey);
//
// If it's not in the cache, check if we've looked in the
// DS already. If we haven't checked the DS, go to the DS.
// "updateCache" will get the info from the DS and update
// both the cache (_cch) and _checkListCache.
//
checkedDS = _checkListCache.containsKey(fdn.toLowerCase());
if (!checkedDS) {
if (_debug.messageEnabled())
_debug.message("ConfigManager->getConfigTemplateNames: " +
"updating " + dn);
synchronized (lock_cch) {
updateCache(fdn);
}
if (_cch.containsKey(cacheKey))
return (Set) _cch.get(cacheKey);
}
//
// We've checked the DS already so get the parent and
// try again.
switch (lookup) {
case TemplateManager.SCOPE_ORG:
return java.util.Collections.EMPTY_SET;
case TemplateManager.SCOPE_TOP:
dn = DN.valueOf(_rootDN);
break;
case TemplateManager.SCOPE_ANCESTORS:
dn = dn.parent();
// After getting parent, check if this is already root of tree,
// if so return null
// if (dn.toString().length() == 0)
if (dn.isInScopeOf(_root, SearchScope.WHOLE_SUBTREE)) {
break;
} else {
return java.util.Collections.EMPTY_SET;
}
}
_debug.message("ConfigManager->getConfigTemplateNames: " +
"Traversing parent: " + dn);
}
}
/**
* Returns the Attribute Key-Value set of a Structure Template
* entry. It searches for all entries and returns the entry for which the
* "class" Attribute matches the provided name.
*
* @param guid GUI specifies the starting location for
* <code>ConfigManager</code> to begin searching for DIT
* information (for structural entities).
* @param name Class name of the object for which the DIT information
* applies.
* @return Collection of attrSets pertaining to the structure
* templates in the DIT.
* @throws ConfigManagerException.
*/
public Set getEntity(Guid guid, String name) throws ConfigManagerException {
Set ret = (Set) getConfigData(guid, name, ENTITY,
TemplateManager.SCOPE_ANCESTORS);
return (ret == null) ?
java.util.Collections.EMPTY_SET : ret;
}
/**
* TEMPLATE MANAGER APIs
*
*/
/**
* Returns the Attribute Key-Value set of a Search or Creation
* Template entry. It searches for all entries and returns the entry for
* which the "name" Attribute matches the provided name.
*
* @param guid Specifies the starting location for
* <code>ConfigManager</code> to begin searching for DIT
* information (for structural entities).
* @param templateName Template name.
* @param lookup
* @return <code>AttrSet</code> value pertaining to the structural template
* in the DIT. Usage:
* <pre>
* AttrSet a = CM.getSearchTemplateForClass(
* principal, "o=foo,o=org", "BasicUserSearch");
* </pre>
* Converts the guid to <code>/iDA/foo/org</code> (for internal SMS
* representation). Looks for Search Template with attribute "name"
* matching <code>BasicUserSearch</code> and returns the first one
* matched. If found in cache, it returns that. Else it looks it up
* in the Directory through SMS (traverses the tree if need be).
* @throws ConfigManagerException.
*/
public AttrSet getSearchTemplate(Guid guid, String templateName, int lookup)
throws ConfigManagerException {
AttrSet ret = (AttrSet)getConfigData(guid, templateName, SEARCH,
lookup);
return (ret == null) ?
com.iplanet.services.ldap.AttrSet.EMPTY_ATTR_SET : ret;
}
/**
* Returns Attribute Key-Value set of a <code>CreationTemplate</code> entry.
* It searches for all entries and returns the entry for which the
* "name" Attribute matches the provided name.
*
* @param guid Specifies the starting location for
* <code>ConfigManager</code> to begin searching for DIT information
* (for structural entities).
* @param templateName Template name.
* @param lookup
* @return <code>AttrSet</code> value pertaining to the structural template
* in the DIT. Usage:
* <pre>
* AttrSet a = CM.getCreationTemplateForClass(
* principal, "o=foo,o=org", "BasicUser");
* </pre>
* Converts the guid to <code>/iDA/foo/org</code> (for internal SMS
* representation). Looks for Search Template with attribute "name"
* matching <code>BasicUser</code> and returns the first one
* matched. If found in cache, it returns that. Else it looks it
* up in the Directory through SMS (traverses the tree if need be)
* @throws ConfigManagerException.
*/
public AttrSet getCreationTemplate(
Guid guid,
String templateName,
int lookup
) throws ConfigManagerException {
AttrSet ret = (AttrSet) getConfigData(guid, templateName, CREATION,
lookup);
if (ret == null)
return com.iplanet.services.ldap.AttrSet.EMPTY_ATTR_SET;
return ret;
}
/**
* Returns the Attribute key-value pair of Creation templates under the
* given organization by matching the the <code>javaclass</code> attribute
* to the name provided. If no templates are listed under the current
* organization then it traverses the org tree till it finds one, or returns
* null.
*
* @param guid Organization DN.
* @param className Name of <code>javaclass</code> Attribute to be matched.
* @param lookup
* @return Attribute key-value pair of Creation templates. Usage:
* <pre>
* AttrSet a = CM.getCreationTemplateForClass(
* principal, "o=foo,o=org", "com.iplanet.ums.BasicUser");
* </pre>
* Converts the guid to <code>/iDA/org</code>. Looks under
* <code>CreationTemplates/templates/org</code> for nodes where
* attribute "class" matches <code>com.iplanet.ums.BasicUser</code>.
* First looks up cache, if not found in cache, then looks up in
* Directory.
*/
public AttrSet getCreationTemplateForClass(
Guid guid,
String className,
int lookup
) throws ConfigManagerException {
AttrSet ret = (AttrSet) getConfigData(
guid, className, CREATION, lookup);
if (ret == null) {
return com.iplanet.services.ldap.AttrSet.EMPTY_ATTR_SET;
}
return ret;
}
/**
* Returns an array of the Creation Template names under the
* given organization. If there are no Creation Templates under the given
* organization then it traveres the organization tree upwards till it finds
* one, or returns null.
*
* @param guid Organization to look under.
* @return Set of Creation Template names.
*/
public Set getCreationTemplateNames(Guid guid)
throws ConfigManagerException {
return getConfigTemplateNames(
guid, CREATION, TemplateManager.SCOPE_ORG);
}
/**
* Returns a set of the Search Template names under the given
* organization. If there are no Search Templates under the given
* organization then it traveres the organization tree upwards till it finds
* one, or returns null.
*
* @param guid Organization to look under.
* @return Set of template name.
* @throws ConfigManagerException.
*/
public Set getSearchTemplateNames(Guid guid) throws ConfigManagerException {
return getConfigTemplateNames(guid, SEARCH, TemplateManager.SCOPE_ORG);
}
/**
* Gets the mapping between ldap entry objectclasses and the UMS Java class.
* This is an array of objectclass, java class pairs. The
* Objectclass/Javaclass pair for a superclass should be defined before that
* of a subclass. This method returns a double-subscripted array for the
* component "ObjectResolver" under the root tree. This component will not
* exist under any other organization except the root.
*
* @return an array of Objectclass/Javaclass pairs.
* @exception ConfigManagerException.
*
* Usage: String[][] a = CM.getClassResolver() Looks up the attributes at
* the top level /ObjectResolver/templates/iDA Caches it first.
*/
public String[][] getClassResolver() throws ConfigManagerException {
// if it is not in the oc_jc_map cache, gets it
if (_oc_jc_map == null) {
_oc_jc_map = (String[][]) getConfigData(null, OBJECTRESOLVER,
OBJECTRESOLVER, TemplateManager.SCOPE_ORG);
}
return _oc_jc_map;
}
/**
* Replaces an existing template.
*
* @param guid the GUID it is looking under.
* @param templateName Name of the template.
* @param attrSet attribute-values pair to be replaced.
* @exception ConfigManagerException.
*/
public void replaceCreationTemplate(Guid guid, String templateName,
AttrSet attrSet) throws ConfigManagerException {
if (guid == null) {
guid = new Guid(_rootDN);
}
DN dn = DN.valueOf(guid.getDn());
String org = "";
List<RDN> rdns = new ArrayList<>();
for (RDN rdn : dn) {
rdns.add(0, rdn);
}
for (RDN rdn : rdns) {
org = org + "/" + LDAPUtils.rdnValue(rdn);
}
String service = CREATIONPATH + "/" + templateName;
Map map = convertToMap(attrSet);
try {
replaceServiceAttributes(org, service, map);
} catch (SMSException e) {
String args[] = new String[1];
args[0] = e.toString();
throw new ConfigManagerException(i18n.getString(
IUMSConstants.ERROR_CM, args));
} catch (SSOException se) {
String args[] = new String[1];
args[0] = se.toString();
throw new ConfigManagerException(i18n.getString(
IUMSConstants.ERROR_CM, args));
}
}
private Map convertToMap(AttrSet attrs) {
HashMap map = new HashMap();
String[] names = attrs.getAttributeNames();
for (int i = 0; i < names.length; i++) {
Attr attr = attrs.getAttribute(names[i]);
String[] values = attr.getStringValues();
HashSet set = new HashSet();
set.addAll(Arrays.asList(values));
map.put(names[i], set);
}
return map;
}
private String[][] getOC_JC_MAP(String oc_jc_map_string) {
StringTokenizer st = new StringTokenizer(oc_jc_map_string, ";");
int tokencount = st.countTokens();
String[][] oc_jc_map = new String[tokencount][2];
int i = 0;
while (st.hasMoreTokens()) {
String s = st.nextToken();
int index = s.indexOf('=');
if (index >= 0) {
String oc = s.substring(0, index);
String jc = s.substring(index + 1, s.length());
oc_jc_map[i][0] = oc;
oc_jc_map[i][1] = jc;
i++;
}
}
return oc_jc_map;
}
/**
* Construct configuration.
*/
private ConfigManagerUMS() throws ConfigManagerException {
_cch = new Hashtable();
_checkListCache = new Cache(10000);
String[] args = new String[1];
try {
DSConfigMgr dm = DSConfigMgr.getDSConfigMgr();
ServerInstance si = dm.getServerInstance(LDAPUser.Type.AUTH_ADMIN);
_rootDN = si.getBaseDN();
_root = DN.valueOf(_rootDN);
_rootDN = _root.toString().toLowerCase();
if (_debug.messageEnabled())
_debug
.message("ConfigManager->Constructor: root DN "
+ _rootDN);
String p = si.getAuthID();
_principal = new AuthPrincipal(p);
String psswd = (String) AccessController
.doPrivileged(new ServerInstanceAction(si));
AuthContext ac = new AuthContext(_principal, psswd.toCharArray());
SSOToken token = ac.getSSOToken();
try {
SSOTokenManager.getInstance().validateToken(token);
} catch (SSOException e) {
args[0] = e.toString();
throw new ConfigManagerException(i18n.getString(
IUMSConstants.INVALID_TOKEN, args));
}
// _smapi = new ServiceConfigManager(_principal);
_smapi = new ServiceConfigManager(token, UMS_SRVC, UMS_VERSION);
_listener = new CMListener();
_lid = _smapi.addListener(_listener);
} catch (Exception e) {
_debug.error("ConfigManager->Constructor: Caught exception " + e);
e.printStackTrace();
args[0] = e.toString();
throw new ConfigManagerException(i18n.getString(
IUMSConstants.ERROR_CM, args));
}
}
protected static final String UMS_SRVC = "DAI";
private static final String UMS_VERSION = "1.0";
private static final String TEMPLATEPATH = "/templates";
static final String ENTITYPATH = TEMPLATEPATH + "/StructureTemplates";
static final String SEARCHPATH = TEMPLATEPATH + "/SearchTemplates";
static final String CREATIONPATH = TEMPLATEPATH + "/CreationTemplates";
private static final String OBJECTRESOLVERPATH = TEMPLATEPATH
+ "/ObjectResolver";
private static final String OBJECTRESOLVER = "ObjectResolver";
private static final String ENTITY = "StructureTemplates";
private static final String SEARCH = "SearchTemplates";
private static final String CREATION = "CreationTemplates";
private static final String CLASS = "class";
private static final String JAVACLASS = "javaclass";
private static final String ATTRNAME = "name";
private static final String OC_JC_MAP = "oc_jc_map";
private static ConfigManagerUMS _instance = null;
static Hashtable _cch = null;
private static final Object lock_cch = new Object();
private static Cache _checkListCache = null;
private static AuthPrincipal _principal;
private static ServiceConfigManager _smapi;
private static String _rootDN;
private static DN _root;
private static CMListener _listener;
private static String _lid; // Listener ID
private static Debug _debug = Debug.getInstance(IUMSConstants.UMS_DEBUG);
private static String[][] _oc_jc_map; // separate cache for oc_jc_map
}