DirectoryServicesImpl.java revision bee2440354b4bc8796e1de0b6cbd60e1f68deba0
/*
* 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: DirectoryServicesImpl.java,v 1.14 2009/11/20 23:52:51 ww203982 Exp $
*
* Portions Copyrighted 2011-2015 ForgeRock AS.
*/
/**
* A class which manages all the major Directory related operations. Contains
* functionality to create, delete and manange directory entries.
*
* This class should not be used directly when caching mode is on.
*
*/
private static final String LDAP_CONNECTION_ERROR_CODES =
"com.iplanet.am.ldap.connection.ldap.error.codes.retries";
// String constants
protected static final String EXTERNAL_ATTRIBUTES_FETCH_ENABLED_ATTR =
"iplanet-am-admin-console-external-attribute-fetch-enabled";
public static boolean isUserPluginInitialized = false; // first time flag
// A handle to Singleton instance
private static IDirectoryServices instance;
private static EventManager eventManager;
protected DCTreeServicesImpl dcTreeImpl;
protected ComplianceServicesImpl complianceImpl;
protected CallBackHelper callBackHelper;
protected SSOToken internalToken;
static {
while (stz.hasMoreTokens()) {
}
}
}
/**
* Ideally this constructor should be private, since we are extending this
* class, it needs to be public. This constructor should not be used to
* create an instance of this class.
*
* <p>
* Use <code>AMDirectoryWrapper.getInstance()</code> to create an
* instance.
*/
public DirectoryServicesImpl() {
dcTreeImpl = new DCTreeServicesImpl();
complianceImpl = new ComplianceServicesImpl();
callBackHelper = new CallBackHelper();
}
protected static synchronized IDirectoryServices getInstance() {
+ "new Instance of DirectoryServicesImpl()");
instance = new DirectoryServicesImpl();
}
return instance;
}
// *************************************************************************
// Some local utility methods related to the operations performed. Generic
// UMSException & LDAPException Processing:
// TODO: Refactor these to some other class
// *************************************************************************
}
return entryName;
}
// This is hack??
if (index != -1) {
}
}
}
return dn;
}
switch (objectType) {
case AMObject.MANAGED_ROLE:
case AMObject.FILTERED_ROLE:
return "465";
case AMObject.DYNAMIC_GROUP:
case AMObject.STATIC_GROUP:
return "466";
case AMObject.ORGANIZATION:
return "467";
return "468";
case AMObject.ORGANIZATIONAL_UNIT:
return "469";
case AMObject.PEOPLE_CONTAINER:
return "470";
case AMObject.GROUP_CONTAINER:
return "471";
default:
return "461";
}
}
switch (objectType) {
case AMObject.MANAGED_ROLE:
case AMObject.FILTERED_ROLE:
return "472";
case AMObject.DYNAMIC_GROUP:
case AMObject.STATIC_GROUP:
return "473";
case AMObject.ORGANIZATION:
return "474";
return "475";
case AMObject.ORGANIZATIONAL_UNIT:
return "476";
case AMObject.PEOPLE_CONTAINER:
return "477";
case AMObject.GROUP_CONTAINER:
return "483";
default:
return "462";
}
}
/**
* Method which does some generic processing of the UMSException and throws
* an appropriate AMException
*
* @param SSOToken
* the SSOToken of the user performing the operation
* @param ue
* the UMSException thrown
* @param defaultErrorCode -
* the default error code of the localized message to be used if
* a generic error occurs
* @throws AMException
* a suitable AMException with specific message indicating the
* error.
*/
try {
// Check for specific error conditions
} else {
}
} else {
}
if (ex instanceof AMException) {
throw ((AMException) ex);
} else {
if (debug.messageEnabled()) {
+ "internal exception", ex);
}
}
}
}
/**
* Method to check if the CallBack plugins are enabled for reading external
* attributes.
*/
// Obtain the ServiceConfig
try {
// Get the org config
} else {
}
}
boolean enabled = false;
}
if (debug.messageEnabled()) {
+ "isExternalGetAttributeEnabled() = " + enabled);
}
return enabled;
}
// Org Config may not exist. Get default values
if (debug.messageEnabled()) {
+ "Organization config for service ("
+ ") not found. Obtaining default service "
+ "config values ..");
}
try {
if (defaultValues != null) {
}
} catch (Exception e) {
if (debug.warningEnabled()) {
+ "Unable to get default global config information", e);
}
}
return null;
}
// *************************************************************************
// Some other Private methods
// *************************************************************************
/**
* Gets the user post plugin instance. Returns a null if plugin not
* configured could not be loaded. TODO: REMOVE after few releases.
* Supported through AMCallBack
*/
public static AMUserEntryProcessed getUserPostPlugin() {
if (!isUserPluginInitialized) {
// TODO: REMOVE after Portal moves to new API's
try {
if (debug.messageEnabled()) {
+ "getUserPostPlugin: Class " + implClassName
+ " instantiated.");
}
} catch (ClassNotFoundException c) {
+ "Class not found: " + implClassName, c);
} catch (InstantiationException ie) {
} catch (IllegalAccessException le) {
}
}
isUserPluginInitialized = true;
}
return userEntry;
}
public IDCTreeServices getDCTreeServicesImpl() {
return dcTreeImpl;
}
public IComplianceServices getComplianceServicesImpl() {
return complianceImpl;
}
// *************************************************************************
// All public methods related to DS Operations.
// *************************************************************************
/**
* Checks if the entry exists in the directory.
*
* @param token
* a valid SSOToken
* @param entryDN
* The DN of the entry that needs to be checked
* @return true if the entryDN exists in the directory, false otherwise
*/
try {
entryDN));
} catch (UMSException ue) {
/*
* The very first time when 'Agents' gets selected from the
* Navigation menu of IS console, there will be no
* ou=agents,ROOT_SUFFIX in the directory. Only it gets created when
* a new agent gets created. So do not log this message.
*/
if (debug.messageEnabled()) {
"DirectoryServicesImpl.doesProfileExist(): + "
+ "Exception caught: ", ue);
}
}
return false;
}
return true;
}
/**
* Gets the type of the object given its DN.
*
* @param token
* token a valid SSOToken
* @param dn
* DN of the object whose type is to be known.
*
* @throws AMException
* if the data store is unavailable or if the object type is
* unknown
* @throws SSOException
* if ssoToken is invalid or expired.
*/
}
/**
* Gets the type of the object given its DN.
*
* @param token
* token a valid SSOToken
* @param dn
* DN of the object whose type is to be known.
* @param cachedAttributes
* cached attributes of the user
*
* @throws AMException
* if the data store is unavailable or if the object type is
* unknown
* @throws SSOException
* if ssoToken is invalid or expired.
*/
throws AMException, SSOException {
if (debug.messageEnabled()) {
+ "object type for: " + dn);
}
}
// Check if object classes are cached, if not get from directory
if (cachedAttributes == null
|| (objectClasses = (Set)
if (debug.messageEnabled()) {
+ " LDAP call to get objectclass attributes for DN: "
+ dn);
}
}
}
// Determine the object type
if (objectClasses != null) {
if (debug.messageEnabled()) {
}
int possibleOT = -1;
continue;
if (debug.messageEnabled()) {
+ "token, entryDN, cachedAttributes)- DN: "
}
return objectType;
}
}
if (possibleOT != -1) {
if (debug.messageEnabled()) {
+ "token, entryDN, cachedAttributes)- DN: " + dn
+ " objectType: " + possibleOT);
}
return possibleOT;
}
}
}
/**
* Gets the attributes for this entryDN from the corresponding DC Tree node.
* The attributes are fetched only for Organization entries in DC tree mode.
*
* @param token
* a valid SSOToken
* @param entryDN
* the dn of the entry
* @param attrNames
* attribute names
* @param byteValues
* <code>true</code> if result in byte
* @param objectType
* the object type.
* @return an AttrSet of values or null if not found
* @throws AMException
* if error encountered in fetching the DC node attributes.
*/
throws AMException, SSOException {
// Already an RFC String
{
entryDN);
.size()]));
}
}
return null;
}
/**
* Checks for Compliance related attributes if applicable. The check can be
* over-ridden by setting the ignoreCompliance to true
*
* @param attrSet
* the attrSet to verify
* @param ignoreCompliance
* if true the check will not take place in Compliance mode.
* @throws AMException
*/
boolean ignoreCompliance) throws AMException {
if (!ignoreCompliance
// Verify for deleted user
}
}
throws AMException, SSOException {
boolean ignoreCompliance = true;
boolean byteValues = false;
}
boolean ignoreCompliance = true;
boolean byteValues = false;
}
// Note: This API will not be implemented in Cached impl of this interface
boolean ignoreCompliance = true;
boolean byteValues = false;
}
// fetch byte values
boolean byteValues = true;
boolean ignoreCompliance = true;
}
// fetch byte values
boolean byteValues = true;
boolean ignoreCompliance = true;
}
/**
* Gets all attributes corresponding to the entryDN. This method obtains the
* DC Tree node attributes and also performs compliance related verification
* checks in compliance mode. Note: In compliance mode you can skip the
* compliance checks by setting ignoreCompliance to "false".
*
* @param token
* a valid SSOToken
* @param entryDN
* the DN of the entry whose attributes need to retrieved
* @param ignoreCompliance
* a boolean value specificying if compliance related entries
* need to ignored or not. Ignored if true.
* @return a Map containing attribute names as keys and Set of values
* corresponding to each key.
* @throws AMException
* if an error is encountered in fetching the attributes
*/
throws AMException, SSOException {
try {
// Obtain attributes from directory
entryDN));
/*
* Add this 'dn' explicitly to the result set and return. reason:
* does not return this attribute, but returns other ones.
*/
// Perform Compliance related checks
return attributes;
} catch (IllegalArgumentException ie) {
if (debug.warningEnabled()) {
+ "Unable to get attributes: ", ie);
}
} catch (UMSException e) {
if (debug.warningEnabled()) {
+ "Unable to get attributes: ", e);
}
// Extract the ldap error code from Exception
}
}
throws AMException, SSOException {
}
/**
* Gets the specific attributes corresponding to the entryDN. This method
* obtains the DC Tree node attributes and also performs compliance related
* verification checks in compliance mode. Note: In compliance mode you can
* skip the compliance checks by setting ignoreCompliance to "false".
*
* @param token
* a valid SSOToken
* @param entryDN
* the DN of the entry whose attributes need to retrieved
* @param attrNames
* a Set of names of the attributes that need to be retrieved.
* The attrNames should not be null.
* @param ignoreCompliance
* a boolean value specificying if compliance related entries
* need to ignored or not. Ignored if true.
* @return a Map containing attribute names as keys and Set of values
* corresponding to each key.
* @throws AMException
* if an error is encountered in fetching the attributes
*/
int profileType)
throws AMException, SSOException {
}
try {
// Convert the attrNames to String[]
.size()]);
entryDN));
// Perform compliance related checks
if (!ignoreCompliance
{ // check for deleted user by getting complaince attributes
} else {
}
// Obtain DC tree attributes if applicable
return attributes;
} catch (UMSException e) {
if (debug.warningEnabled()) {
+ "Unable to get attributes: ", e);
}
// Extract the ldap error code from Exception
}
}
// The search filter calls here should return a global search
// filter (not default) if a search template cannot be found for this
// entryDN. It is a hack as entryDN may not be orgDN, but right now
// only solution.
}
/**
* Gets the Organization DN for the specified entryDN. If the entry itself
* is an org, then same DN is returned.
* <p>
* <b>NOTE:</b> This method will involve serveral directory searches, hence
* be cautious of Performance hit
*
* @param token
* a valid SSOToken
* @param entryDN
* the entry whose parent Organization is to be obtained
* @return the DN String of the parent Organization
* @throws AMException
* if an error occured while obtaining the parent Organization
*/
throws AMException {
+ entryDN);
}
}
return organizationDN;
}
/**
* Returns attributes from an external data store.
*
* @param token
* Single sign on token of user
* @param entryDN
* DN of the entry user is trying to read
* @param attrNames
* Set of attributes to be read
* @param profileType
* Integer determining the type of profile being read
* @return A Map of attribute-value pairs
* @throws AMException
* if an error occurs when trying to read external datastore
*/
} else {
}
}
/**
* Adds or remove static group DN to or from member attribute
* 'iplanet-am-static-group-dn'
*
* @param token
* SSOToken
* @param members
* set of user DN's
* @param staticGroupDN
* DN of the static group
* @param toAdd
* true to add, false to remove
* @throws AMException
* if there is an internal problem with AM Store.
*/
if (debug.messageEnabled()) {
+ " members: " + members);
}
try {
if (toAdd) {
} else {
}
} catch (UMSException e) {
+ "Failed while trying to set the static groupDN "
}
}
}
// *************************************************************************
// All un-modified methods from DirectoryServicesImpl. (Comments only for
// reference)
// *************************************************************************
if (index == -1) {
} else {
}
}
/**
* When an object is being created and attribute sets are being passed UMS
* does not overrid objectclasses in the attribute set, with the ones from
* creation template. This method takes care of that.
*
* @param ct
* @param aSet
*/
// UMS creation template will not append default user
// objectclasses if the "objectclass" attribute is present
// so we need to append those default objectclass here
// if (attr != null) {
// TO: To write a separate method for attrSet combine object class
// values. Need to avoid conversion from string array to sets.
// get default user objectclass from creation template
.getStringValues()) : new HashSet();
// }
return aSet;
}
/**
* Method to create a user entry
*/
// Invoke the Pre Processing plugin
// Invoke the user password validation plugin
try {
} catch (AMException ame) {
+ "characters for user", ame);
throw ame;
}
// User user = new User(creationTemp, attrSet);
try {
} catch (AccessRightsException e) {
if (debug.warningEnabled()) {
"DirectoryServicesImpl.createUser(): Insufficient "
+ "Access rights to create user", e);
}
} catch (EntryAlreadyExistsException ee) {
// COMPLIANCE
// If the existing entry is marked for deletion, then
// the error message should be different.
}
if (debug.warningEnabled()) {
+ "already exists: ", ee);
}
} catch (UMSException ue) {
if (debug.warningEnabled()) {
+ "Error occurred. Unable to create User Entry", ue);
}
}
// Invoke Post processing impls
// TODO: REMOVE after Portal moves to new API's
if (postPlugin != null) {
}
.getDN());
}
/**
* Method to create a user entry
*/
// Invoke the Pre Processing plugin
// Create a user if no CT defined.
ctName = "BasicUser";
}
try {
} catch (AccessRightsException e) {
if (debug.warningEnabled()) {
+ " Insufficient Access rights to create entity", e);
}
} catch (EntryAlreadyExistsException ee) {
// COMPLIANCE
// If the existing entry is marked for deletion, then
// the error message should be different.
}
if (debug.warningEnabled()) {
+ "already exists: ", ee);
}
} catch (UMSException ue) {
if (debug.warningEnabled()) {
+ "Error occurred. Unable to create User Entry", ue);
}
}
}
}
// Invoke the Pre Processing plugin
// Invoke Post processing impls
}
// Invoke the Pre Processing plugin. Note: we need to obtain
// the parent org of this organization to obtain the
// plugin classes for the parent org.
// COMPLIANCE: DCTREE
if (dcTreeImpl.isRequired()) {
attrSet);
attrSetArray[0]);
// create the DC node first. If it fails then the org node will not
// be created at all. No clean up needed afterwards then.
} else {
}
try {
} catch (UMSException ue) {
// clean up DC node
if (dcTreeImpl.isRequired()) {
}
// COMPLIANCE
// If the existing entry is marked for deletion, then
// the error message should be different.
}
throw ue;
}
}
// If Realms is enabled and is configured in backward compatibitly
// mode, the corresponding realm must also be created.
&& ServiceManager.isRealmEnabled()) {
try {
// Check if realm exisits, this throws SMSException
// if realm does not exist
} catch (SMSException smse) {
// Organization does not exist, create it
if (debug.messageEnabled()) {
}
try {
} catch (SMSException se) {
if (debug.messageEnabled()) {
+ "createOrganization unable to create realm: "
}
}
}
}
// If in legacy mode, add the default services
if (ServiceManager.isCoexistenceMode()) {
try {
} catch (SMSException smse) {
// Unable to load default services
if (debug.warningEnabled()) {
}
}
}
// Invoke Post processing impls. Note: orgDN is parent org
}
// Invoke the Pre Processing plugin
}
// Invoke Post processing impls
}
throws UMSException, AMException {
// Invoke the Pre Processing plugin
AMObject.ASSIGNABLE_DYNAMIC_GROUP, false);
// Invoke Post processing impls
AMObject.ASSIGNABLE_DYNAMIC_GROUP, false);
}
// Invoke the Pre Process plugin
false);
}
// Invoke Post processing impls
false);
}
attrSet);
}
throws UMSException, AMException {
// Invoke the Pre Post Plugins
AMObject.ORGANIZATIONAL_UNIT, false);
// Invoke Post processing impls
}
}
// Invoke the Pre Processing plugin
false);
}
// Invoke Post processing impls
false);
}
/**
* Create an entry in the Directory
*
* @param token
* SSOToken
* @param entryName
* name of the entry (naming value), e.g. "sun.com", "manager"
* @param objectType
* Profile Type, ORGANIZATION, AMObject.ROLE, AMObject.USER, etc.
* @param parentDN
* the parent DN
* @param attributes
* the initial attribute set for creation
*/
try {
}
// tmpDN to be used only when validating since the method
// expects a DN.
+ "," + parentDN;
// Get handle to the parent object
parentDN));
switch (objectType) {
break;
case AMObject.MANAGED_ROLE:
break;
case AMObject.ORGANIZATION:
break;
case AMObject.STATIC_GROUP:
break;
break;
case AMObject.DYNAMIC_GROUP:
break;
case AMObject.PEOPLE_CONTAINER:
break;
case AMObject.ORGANIZATIONAL_UNIT:
break;
case AMObject.GROUP_CONTAINER:
break;
case AMObject.FILTERED_ROLE:
break;
break;
case AMObject.UNKNOWN_OBJECT_TYPE:
default: // Supported generic type
}
} catch (AccessRightsException e) {
if (debug.warningEnabled()) {
+ "Insufficient access rights to create entry: "
+ entryName, e);
}
} catch (EntryAlreadyExistsException e) {
if (debug.warningEnabled()) {
+ entryName + "already exists: ", e);
}
args);
} catch (UMSException e) {
if (debug.warningEnabled()) {
+ "create entry: " + entryName, e);
}
}
}
// Call pre-processing user impls
// Get the parent oganization for this org.
}
}
}
}
}
boolean softDelete) throws AMException {
// Invoke post processing impls
// Get the parent oganization for this org.
}
}
}
}
/**
* Remove an entry from the directory.
*
* @param token
* SSOToken
* @param entryDN
* dn of the profile to be removed
* @param objectType
* profile type
* @param recursive
* if true, remove all sub entries & the object
* @param softDelete
* delete itself, otherwise, remove the object only
*/
if (debug.messageEnabled()) {
}
if (recursive) {
// will list all entries in the sub-tree and delete them
// one by one.
} else {
}
// If Organization is deleted, and if realms in enabled and is
// configured in backward compatibitly mode, the corresponding
// realm must also be deleted.
&& ServiceManager.isRealmEnabled()) {
try {
// Check if realm exisits, this throws SMSException
// if realm does not exist
// Since the above did not throw an exception, the
// realm must be deleted
} catch (SMSException smse) {
if (debug.messageEnabled()) {
"unable to delete corresponding realm: " + entryDN);
}
}
}
}
/**
* Private method to delete a single entry
*/
}
try {
// Extract a delete notification list
}
if ((getUserPostPlugin() != null)
// Obtain the attributes needed to send notification and also
// call backs as these won't be available after deletion
}
// if (recursive) {
// deleteSubtree(token, entryDN, softDelete);
// } else {
if (dcTreeImpl.isRequired()) {
}
// }
} catch (AccessRightsException e) {
+ "access rights to remove entry: " + entryDN, e);
} catch (EntryNotFoundException e) {
+ entry, e);
} catch (UMSException e) {
+ " Internal error occurred: ", e);
}
if (postPlugin != null) {
// TODO: Remove after deprecating interface
}
{
}
}
}
/**
* Private method used by "removeEntry" to delete an entire subtree
*/
try {
// first get all the children of the object
"(|(objectclass=*)(objectclass=ldapsubEntry))";
// get number of RDNs in the entry itself
// to count maximum level of RDNs in the search return
int maxRDNCount = entryRDNs;
// go through all search results, add DN to the list, and
// set the maximun RDN count, will be used to remove DNs
while (children.hasMoreElements()) {
if (debug.messageEnabled()) {
}
if (count > maxRDNCount) {
maxRDNCount = count;
}
}
if (debug.messageEnabled()) {
+ "RDNs: " + maxRDNCount);
}
// go through all search results, delete entries from the
// bottom up, starting from entries whose's RDN count
// equals the maxRDNCount
// TODO : If the list has too many entries, then the multiple
// iteration in the inner for loop may be the bottleneck.
// One enhancement to the existing algorithm is to store all
// the entries by level in a different List. Per Sai's comments
for (int i = maxRDNCount; i >= entryRDNs; i--) {
for (int j = 0; j < len; j++) {
// check if we need delete it now
// remove the entry
if (debug.messageEnabled()) {
}
try {
} catch (AMException ae) {
// Not a managed type, just delete it.
}
// Do a non-recursive delete
try {
} catch (AMPreCallBackException amp) {
+ "removeSubTree: Aborting delete of: "
+ rfcDN
+ " due to pre-callback exception",
amp);
}
}
// remove the deleted entry from the list
// move back pointer, as current element is removed
j--;
// reduce list length
len--;
}
}
}
} catch (AccessRightsException e) {
+ "access rights to remove entry: " + entryDN, e);
} catch (EntryNotFoundException e) {
+ entry, e);
} catch (UMSException e) {
+ " Internal error occurred: ", e);
}
}
/**
* Remove group admin role
*
* @param token
* SSOToken of the caller
* @param dn
* group DN
* @param recursive
* true to delete all admin roles for all sub groups or sub
* people container
*/
throws SSOException, AMException {
if (debug.messageEnabled()) {
+ " recursive: " + recursive);
}
// first find out the admin role dn for the group
if (recursive) {
} else {
adminRoles = new HashSet();
}
// remove all members from the role
try {
new Guid(adminRoleDN));
// removeEntry(token, adminRoleDN, AMObject.ROLE, false, false);
} catch (Exception e) {
if (debug.messageEnabled()) {
+ "Unable to admin roles:", e);
}
}
}
}
/**
* convert search results to a set of DNS
*/
while (results.hasMoreElements()) {
}
}
return set;
}
/**
* Searches the Directory
*
* @param token
* SSOToken
* @param entryDN
* DN of the entry to start the search with
* @param searchFilter
* search filter
* @param searchScope
* search scope, BASE, ONELEVEL or SUBTREE
* @return Set set of matching DNs
*/
int searchScope) throws AMException {
try {
entryDN));
} catch (UMSException ue) {
}
if (debug.warningEnabled()) {
ue);
}
}
return resultSet;
}
/**
* convert search results to a AMSearchResults object TODO: Refactor code
*/
boolean getAllAttrs) throws UMSException {
tmpTreeSet = new TreeSet();
}
try {
while (results.hasMoreElements()) {
} else {
}
} else {
}
} else {
}
// Support for multiple return values
} else {
/*
* Support for multiple return values when attribute
* names are not passed as part of the return
* attributes. This boolean check is to make sure user
* has set the setAllReturnAttributes flag in
* AMSearchControl in order to get all attributes or
* not.
*/
if (getAllAttrs) {
true);
}
}
}
}
} catch (SizeLimitExceededException slee) {
} catch (TimeLimitExceededException tlee) {
}
int countValue;
} else {
}
} else {
}
}
} else {
for (int i = 0; i < len; i++) {
} else {
}
}
}
}
}
return searchResults;
}
// RENAME from searchUsingSearchControl => search()
/**
* Search the Directory
*
* @param token
* SSOToken
* @param entryDN
* DN of the entry to start the search with
* @param searchFilter
* search filter
* @param searchControl
* search control defining the VLV indexes and search scope
* @param attrNames
* name of attributes
* @return Set set of matching DNs
*/
try {
}
if (debug.messageEnabled()) {
+ "searchcontrol locale = " + userLocale);
}
.getLocale(userLocale));
sc = new SearchControl();
} else {
sc = searchControl;
}
entryDN));
} else {
}
} else {
} else {
}
}
} catch (UMSException ue) {
if (debug.warningEnabled()) {
}
}
return amResults;
}
/**
* Get members for roles, dynamic group or static group
*
* @param token
* SSOToken
* @param entryDN
* DN of the role or group
* @param objectType
* objectType of the target object, AMObject.ROLE or
* AMObject.GROUP
* @return Set Member DNs
*/
throws AMException {
try {
switch (objectType) {
case AMObject.MANAGED_ROLE:
return searchResultsToSet(results);
case AMObject.FILTERED_ROLE:
return searchResultsToSet(results);
case AMObject.STATIC_GROUP:
return searchResultsToSet(results);
case AMObject.DYNAMIC_GROUP:
return searchResultsToSet(results);
// TODO: See if it works after removing this workaround
// fake object to get around UMS problem.
// UMS AssignableDynamicGroup has a class resolver, it is
// added to resolver list in static block. So I need to
// construct a dummy AssignableDynamicGroup
return searchResultsToSet(results);
default:
}
} catch (EntryNotFoundException e) {
+ " objectType: " + objectType
+ " Unable to get members: ", e);
args);
} catch (UMSException e) {
+ " objectType: " + objectType
+ " Unable to get members: ", e);
}
}
}
}
/**
* Renames an entry. Currently used for only user renaming
*
* @param token
* the sso token
* @param objectType
* the type of entry
* @param entryDN
* the entry DN
* @param newName
* the new name (i.e., if RDN is cn=John, the value passed should
* be "John"
* @param deleteOldName
* if true the old name is deleted otherwise it is retained.
* @return new <code>DN</code> of the renamed entry
* @throws AMException
* if the operation was not successful
*/
try {
entryDN));
} catch (AccessRightsException e) {
if (debug.warningEnabled()) {
+ "not have sufficient access rights ", e);
}
} catch (EntryNotFoundException e) {
if (debug.warningEnabled()) {
+ "not found: ", e);
}
args);
} catch (UMSException ume) {
if (debug.warningEnabled()) {
+ "rename entry: ", ume);
}
}
}
// TODO: Need to see if the split attributes to a another way of doing
// this instead of passing an array. Need to see if the domain status can
// also be set along with other attributes. Also DCTree code needs to use
// Maps instead of attrSet.
}
// split up the attrs to be set on DC node and organization node.
}
return attributes;
}
int objectType) throws AMException {
// Get the parent oganization for this org.
// Get the parent oganization for this org.
}
}
objectType, false);
}
}
// Get the parent oganization for this org.
}
}
if (oldAttributes == null) {
}
objectType, false);
}
return attributes;
}
if (isAdd) { // Add attribute
} else if (isDelete) { // Remove attribute
} else { // Replace attribute
}
}
// Add string attributes
/*
* AMObjectImpl.removeAttributes(...) sets the values to be
* Collections.EMPTY_SET.
*/
}
}
}
// Add byte attributes
}
}
}
// TODO: method rename from setProfileAttributes to setAttributes
/**
* Method Set the attributes of an entry.
*
* @param token
* SSOToken
* @param entryDN
* DN of the profile whose template is to be set
* @param objectType
* profile type
* @param stringAttributes
* attributes to be set
* @param byteAttributes
* attributes to be set
* @param isAdd
* <code>true</code> if add to existing value;
* otherwise replace the existing value.
*/
throws AMException, SSOException {
}
try {
if (debug.messageEnabled()) {
+ entryDN);
}
// Invoke the user password validation plugin. Note: the
// validation is done only for String attributes
try {
} catch (AMException ame) {
"DirectoryServicesImpl.setAttributes(): Invalid "
+ "characters for user", ame);
throw ame;
}
// Create a mailter instance
}
if ((getUserPostPlugin() != null)
}
// Call pre-processing user impls & get modified attributes
// Note currently only String attributes supported
// Set DCTree attributes
// modify and save the entry
} catch (AccessRightsException e) {
if (debug.warningEnabled()) {
"DirectoryServicesImpl.setAttributes() User does "
+ "not have sufficient access rights: ", e);
}
} catch (EntryNotFoundException ee) {
if (debug.warningEnabled()) {
"DirectoryServicesImpl.setAttributes() Entry not "
+ "found: ", ee);
}
args);
} catch (UMSException e) {
if (debug.warningEnabled())
+ "error occurred", e);
}
}
{
}
}
}
/**
* Changes user password.
*
* @param token Single sign on token
* @param entryDN DN of the profile whose template is to be set
* @param attrName password attribute name
* @param oldPassword old password
* @param newPassword new password
* @throws AMException if an error occurs when changing user password
* @throws SSOException If user's single sign on token is invalid.
*/
throws AMException, SSOException {
try {
} catch (UMSException umex) {
}
}
// ##########Group and role related APIs
/**
* Returns an array containing the dynamic group's scope, base dn, and
* filter.
*/
int scope;
try {
} catch (EntryNotFoundException e) {
args);
} catch (UMSException e) {
}
return result;
}
/**
* Sets the filter for a dynamic group in the datastore.
*
* @param token
* @param entryDN
* @param filter
* @throws AMException
* @throws SSOException
*/
throws AMException, SSOException {
try {
dynamicGroup.save();
} catch (UMSException ume) {
+ "setFilter()", ume);
}
}
/**
* @param token
* @param target
* @param members
* @param operation
* @param profileType
* @throws UMSException
* @throws AMException
*/
try {
} catch (ClassCastException e) {
"DirectoryServicesImpl.modifyRoleMembership() - Unable to "
+ "modify role membership", e);
}
// Since this target cannot be an Org. Get the parent
return;
}
}
switch (operation) {
case ADD_MEMBER:
// COMPLIANCE: if admin role then perform iplanet
// compilance related operations if needed.
target);
}
break;
case REMOVE_MEMBER:
// UMS does not have Role.removerMembers : TBD
}
// COMPLIANCE: if admin role then perform iplanet
// compilance related operations if needed.
target);
}
break;
default:
}
// Make call backs to the plugins to let them know modification to
// role membership.
// Here the new members are just the ones added not the complete Set
}
}
target));
// Make call backs to the plugins to let them know modification
// to role membership.
// Since this target cannot be an Org. Get the parent
return;
}
}
switch (operation) {
case ADD_MEMBER:
break;
case REMOVE_MEMBER:
// UMS does not have Role.removerMembers : TBD
}
break;
default:
}
// Make call backs to the plugins to let them know modification to
// role membership.
// Here the new members are just the ones added not the complete Set
}
}
throws UMSException, AMException {
// fake object to get around UMS problem.
// UMS AssignableDynamicGroup has a class resolver, it is
// added to resolver list in static block. So I need to
// construct a dummy AssignableDynamicGroup
// Make call backs to the plugins to let them know modification
// to role membership.
// Since this target cannot be an Org. Get the parent
return;
}
}
switch (operation) {
case ADD_MEMBER:
target);
}
break;
case REMOVE_MEMBER:
}
// COMPLIANCE: if admin group then perform iplanet
// compliance related operations if needed.
target);
}
break;
default:
}
// Make call backs to the plugins to let them know modification to
// role membership.
// Here the new members are just the ones added not the complete Set
}
}
"461", args);
}
switch (objectType) {
case AMObject.MANAGED_ROLE:
errorCode = "465";
break;
case AMObject.STATIC_GROUP:
errorCode = "466";
break;
}
} else {
errorCode = "468";
}
+ target, e);
}
/**
* Modify member ship for role or static group
*
* @param token
* SSOToken
* @param members
* Set of member DN to be operated
* @param target
* DN of the target object to add the member
* @param type
* type of the target object, AMObject.ROLE or AMObject.GROUP
* @param operation
* type of operation, ADD_MEMBER or REMOVE_MEMBER
*/
if (debug.messageEnabled()) {
}
+ "Invalid DN: " + userDN);
}
}
try {
switch (type) {
case AMObject.MANAGED_ROLE:
break;
case AMObject.STATIC_GROUP:
break;
break;
default:
}
} catch (AccessRightsException e) {
+ "access rights: ", e);
} catch (EntryNotFoundException e) {
} catch (UMSException e) {
+ "modify membership", e);
}
}
// *************************************************************************
// Service Related Functionality
// *************************************************************************
/**
* Get registered services for an organization
*
* @param token
* SSOToken
* @param entryDN
* DN of the org
* @return Set set of service names
*/
throws AMException {
try {
// User dsame privileged user to get the registered
// services. Admins of all levels will need this access
}
if (debug.messageEnabled()) {
+ "getRegisteredServiceNames()"
+ " Registered Service Names for entryDN: "
}
return resultSet;
} catch (Exception e) {
}
}
/**
* Register a service for an org or org unit policy to a profile
*
* @param token
* token
* @param orgDN
* DN of the org
* @param serviceName
* Service Name
*/
try {
// This returns a valid set only if the service has
// Dynamic attributes
}
} catch (AccessRightsException e) {
+ "Insufficient access rights to register service: "
+ serviceName, e);
} catch (EntryAlreadyExistsException e) {
if (debug.warningEnabled()) {
}
"464", args);
} catch (SMSException e) {
+ "register service: " + serviceName, e);
} catch (UMSException e) {
+ "register service: " + serviceName, e);
}
}
/**
* Method to get the attribute names of a service with CosQualifier. For
* example: Return set could be ["iplanet-am-web-agent-allow-list
* merge-schemes", "iplanet-am-web-agent-deny-list merge-schemes"] This only
* returns Dynamic attributes
*/
try {
} catch (SMSException sme) {
if (debug.warningEnabled()) {
+ "schema defined for SchemaType.DYNAMIC type");
}
}
return Collections.EMPTY_SET;
}
}
return attrNames;
}
/**
* Create a COS Definition based on serviceID & attribute set & type. For
* policy attribute, will set cosattribute to "override" For other
* attribute, will set cosattribute to "default"
*/
// new attribute set
// set naming attribute to the serviceID
// add cosspecifier
// add cosattribute
}
return new DirectCOSDefinition(attrs);
}
// Rename from removeService to unRegisterService
/**
* Un register service for a AMro profile.
*
* @param token
* SSOToken
* @param entryDN
* DN of the profile whose service is to be removed
* @param objectType
* profile type
* @param serviceName
* Service Name
* @param type
* Template type
*/
// TODO:change "cn" to fleasible naming attribute for AMObject.ROLE
try {
// COS Definition to obtaint depends on different profile type
switch (objectType) {
case AMObject.FILTERED_ROLE:
break;
case AMObject.ORGANIZATION:
case AMObject.ORGANIZATIONAL_UNIT:
case AMObject.PEOPLE_CONTAINER:
break;
default:
// entry other than AMObject.ROLE,FILTERED_ROLE,ORG,PC
// does not have COS
}
try {
} catch (COSNotFoundException e) {
if (debug.messageEnabled()) {
+ "unRegisterService() "
+ "No COSDefinition found for service: "
+ serviceName);
}
}
// Remove the COS Definition and Template
} catch (AccessRightsException e) {
+ "Insufficient Access rights to unRegister service: ",
e);
} catch (UMSException e) {
+ "Unable to unregister service ", e);
}
}
}
/**
* Get the AMTemplate DN (COSTemplateDN)
*
* @param token
* SSOToken
* @param entryDN
* DN of the profile whose template is to be set
* @param serviceName
* Service Name
* @param type
* the template type, AMTemplate.DYNAMIC_TEMPLATE
* @return String DN of the AMTemplate
*/
// TBD : get template on flexible naming attribute
try {
// get COS Definition depends on different profile type
switch (objectType) {
case AMObject.FILTERED_ROLE:
.getParentGuid().toString());
case AMObject.ORGANIZATION:
case AMObject.ORGANIZATIONAL_UNIT:
case AMObject.PEOPLE_CONTAINER:
+ entryDN;
+ entryDN);
default:
// entry other that AMObject.ROLE & FILTERED_ROLE & ORG & PC
// does not have COS
}
} catch (UMSException e) {
"DirectoryServicesImpl.getAMTemplateDN() Unable to get "
+ "AMTemplate DN for service: " + serviceName
+ " entryDN: " + entryDN, e);
}
}
/**
* Create an AMTemplate (COSTemplate)
*
* @param token
* token
* @param entryDN
* DN of the profile whose template is to be set
* @param objectType
* the entry type
* @param serviceName
* Service Name
* @param attributes
* attributes to be set
* @param priority
* template priority
* @return String DN of the newly created template
*/
throws AMException {
// TBD, change "cn" to flesible naming attrsibute for AMObject.ROLE
try {
entryDN));
// get COS Definition depends on different profile type
switch (objectType) {
case AMObject.FILTERED_ROLE:
break;
case AMObject.ORGANIZATION:
case AMObject.ORGANIZATIONAL_UNIT:
case AMObject.PEOPLE_CONTAINER:
+ entryDN;
break;
default:
// entry other that AMObject.ROLE & FILTERED_ROLE & ORG & PC
// does not have COS
}
// add template priority
}
roleDN);
} catch (COSNotFoundException e) {
if (debug.messageEnabled()) {
+ "COSDefinition for service: " + serviceName
+ " not found: ", e);
}
args);
} catch (EntryAlreadyExistsException e) {
if (debug.messageEnabled()) {
"DirectoryServicesImpl.createAMTemplate: template "
+ "already exists for " + serviceName, e);
}
"854", params);
} catch (AccessRightsException e) {
if (debug.warningEnabled()) {
+ "Insufficient access rights to create template for: "
}
} catch (UMSException e) {
if (debug.warningEnabled()) {
+ " to create AMTemplate for: " + serviceName
+ " & entryDN: " + entryDN, e);
}
args, e);
} catch (Exception e) {
if (debug.warningEnabled())
}
}
/**
* create COS Template from attribute set for a service, this will involve
* UMS Creation template for COSTemplate
*
* @param serviceID
* Service name
* @param attrSet
* the attribute set
* @param entryDN
* DN of the role
* @return COSTemplate COS Template created
*/
"BasicCOSTemplate", null);
// Now need to add the service object for the "serviceID" to the
// required attribute set of the cos creatation template
// need to use schema manager and service manager (TBD)
// But for now just add "extensibleObject" to it
+ entryDN + "\"");
if (debug.messageEnabled()) {
}
for (int i = 0; i < size; i++) {
}
return cosTemplate;
}
}
/**
* Gets the naming attribute after reading it from the corresponding
* creation template. If not found, a default value will be used
*/
}
/**
* Get the name of the creation template to use for specified object type.
*/
}
return getObjectClass(objectType);
}
}
}
}
/**
* Returns the set of attributes (both optional and required) needed for an
* objectclass based on the LDAP schema
*
* @param objectclass
* @return the attributes for the objectclass
*/
try {
} catch (UMSException ue) {
return Collections.EMPTY_SET;
}
}
/**
* Validate attribute uniqueness
*
* @param newEntry
* true if create a new user
* @throws AMException
* if attribute uniqueness is violated
*/
boolean attrExists = false;
return;
}
try {
// no namespace validation for these objects
return;
}
if (size < 2) {
return;
}
.getInternalToken());
if (debug.messageEnabled()) {
+ "try DN = " + orgDN);
}
int type = -1;
try {
} catch (AMException ame) {
if (debug.warningEnabled()) {
+ "validateAttributeUniqueness: "
+ "Unable to determine object type of "
+ orgDN
+ " :Attribute uniqueness check aborted..",
ame);
}
return;
}
}
}
if (debug.messageEnabled()) {
+ "validateAttributeUniqueness: list ="+ list);
}
/*
* After adding the uniquness attributes 'ou,cn' to the
* list, creating a role with the same name as the existing
* user say 'amadmin' fails with 'Attribute uniqueness
* violation' The filter (|(cn='attrname')) is used for all
* objects. Fixed the code to look for 'Role' profile types
* and set the filter as
* (&(objectclass=ldapsubentry)
* (objectclass=nsroledefinition)
* (cn='attrname'))
*
* The same issue happens when a group is created with
* existing user name. Fixed the code to look for 'Group'
* profile types and set the filter as
* (&(objectClass=groupofuniquenames)
* (objectClass=iplanet-am-managed-group)(cn='attrname'))
* The logic in the while loop is iterate through the
* attribute unique list and check if the list contains the
* naming attribute of the object we are trying to create.
* If the naming attribute is in the list,then look if the
* profile type of the object we are trying to create is
* 'role' or 'group', add appropriate objectclasses and the
* entry rdn to the search filter. This filter is used to
* search the iDS and determine the attribute uniqueness
* violation. The boolean variable 'attrExists' is set to
* false initially. This variable is set to true when the
* profile type is 'role' or 'group'. The check for this
* boolean variable decides the number of matching closing
* parens of the three different types of filters.
*/
if (attrName
&& newEntry) {
|| (profileType ==
|| (profileType ==
{
"(objectclass=ldapsubentry)");
"objectclass=nsroledefinition)");
attrExists = true;
|| (profileType ==
|| (profileType ==
|| (profileType ==
{
"(objectclass=iplanet-am-managed-group)");
"(objectclass=groupofuniquenames)");
attrExists = true;
{
attrExists = true;
}
.append(")");
}
}
} // if
}
}
if (attrExists) {
// pre-pend the creation filter part to the filter
// This is being done so that the filter is
// correctly created as
// (&(<creation-filter)(|(<attr filter>)))
} else {
}
if (debug.messageEnabled()) {
+ "validateAttributeUniqueness: "
}
// Check if the entry that is "violating" uniqueness is
// the same as the one you are checking for.
// In that case,ignore the violation
return;
}
}
"162");
}
}
}
}
} catch (SSOException ex) {
if (debug.warningEnabled()) {
}
}
}
/**
* Private method to convert a comma separated string of attribute names to
* an Array
*
* @param newEntry
* @throws AMException
*/
for (int i = 0; i < size; i++) {
}
return attrList;
}
/**
* Private method to get a set of values for all attributes that exist in
* the stringModMap of this object, from a given list of attribute names
*
* @param newEntry
* @throws AMException
*/
for (int i = 0; i < size; i++) {
}
}
return (retSet);
}
if (debug.messageEnabled()) {
+ "getTopLevelContainers: roleDN=" + roleDN);
}
}
+ ")";
}
boolean toAdd = true;
toAdd = false;
break;
}
}
if (toAdd) {
}
}
if (debug.messageEnabled()) {
}
}
return resultSet;
}
/**
* Gets the Organization DN for the specified entryDN. If the entry itself
* is an org, then same DN is returned.
*
* @param token
* a valid SSOToken
* @param entryDN
* the entry whose parent Organization is to be obtained
* @param childDN
* the immediate entry whose parent Organization is to be
* obtained
* @return the DN String of the parent Organization
* @throws AMException
* if an error occured while obtaining the parent Organization
*/
+ "DN: " + entryDN);
}
boolean errorCondition = false;
try {
// forceful abandon and to avoid multiple
// ABANDON logged in directory server access logs.
while (result.hasMoreElements()) {
}
}
} catch (InvalidSearchFilterException e) {
errorCondition = true;
+ "search filter, unable to get Parent Organization: ", e);
} catch (UMSException ue) {
errorCondition = true;
if (debug.warningEnabled()) {
+ "Unable to Obtain Parent Organization", ue);
}
}
}
if (errorCondition) {
}
return organizationDN;
}
// Registering for notification
// Validate SSOToken
try {
} catch (SSOException ssoe) {
}
// Add to listeners
synchronized (listeners) {
// Check if event service has been started
if (eventManager == null) {
eventManager = new EventManager();
}
}
}
}