/** * Method to be called to validate the entry before any of the get/put/ remove methods are called. * * @throws AMException if the entry does not exist in the DS */ private void validateEntry(SSOToken token, CacheBlock cb) throws AMException { if (!cb.hasExpiredAndUpdated() && !cb.isExists()) { // Entry does not exist in DS, invalid entry String params[] = {cb.getEntryDN()}; boolean isPresent = super.doesEntryExists(token, params[0]); if (getDebug().messageEnabled()) { getDebug() .message( "CachedRemoteServicesImpl.validateEntry():" + " DN" + params[0] + " got from DS & exists: " + isPresent); } if (isPresent) { // Intialize the CacheBlock based on isPresent // else throw '461' exception/error message. // This is for certain containers created dynamically. // eg. ou=agents,ou=container,ou=agents. String dn = MiscUtils.formatToRFC(params[0]); cb = new CacheBlock(params[0], isPresent); sdkCache.put(dn, cb); } else { String locale = MiscUtils.getUserLocale(token); throw new AMException(AMSDKBundle.getString("461", params, locale), "461", params); } } }
/** * Method to get search filter for the specified object type defined at the specified * Organization. If a search template corresponding to the AMObject, is not found at the specified * Organization, then one defined at global one will be returned. * * @param objectType type of AMObject * @param orgDN the DN of the organization where the AMObject resides. * @param searchTemplateName name of the search template to be used. If this is null, then default * search templates are used. * @param ignoreComplianceFilter if true then modify the compliance related search filters will * not be applied. If false, compliance related filters will be applied. * @return a search filter String in lower case. */ public static String getSearchFilter( int objectType, String orgDN, String searchTemplateName, boolean ignoreComplianceFilter) { String filter; String organizationDN = new DN(orgDN).toRFCString(); // Already in RFC String rootSuffixDN = AMStoreConnection.getAMSdkBaseDN(); if (orgDN != null && organizationDN.equals(rootSuffixDN)) { orgDN = null; } String cacheKey = (new Integer(objectType)).toString() + ":" + searchTemplateName + ":" + organizationDN; if ((filter = (String) searchfilterMap.get(cacheKey)) == null) { IDirectoryServices dsServices = AMDirectoryAccessFactory.getDirectoryServices(); filter = dsServices.getSearchFilterFromTemplate(objectType, orgDN, searchTemplateName); searchfilterMap.put(cacheKey, filter); } // Now modify the obtained search filter if necessary. Also, mostly // do the modification here, if you do not want the modified filter // to be cached. Applicable to cases where filter may change dynamically // Note: Always add lowercase filters, to guarantee a lowercase filter // String to be returned. filter = modifyFilter(filter, objectType); filter = addAdminGroupFilters(filter, orgDN, objectType); filter = addComplianceModeFilters(filter, objectType, ignoreComplianceFilter); return filter; }
/** * 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 */ public String renameEntry( SSOToken token, int objectType, String entryDN, String newName, boolean deleteOldName) throws AMException { String newDN = super.renameEntry(token, objectType, entryDN, newName, deleteOldName); // Just rename the dn in the cache. Don't remove the entry. So when the // event notification happens, it won't find the entry as it is already // renamed. Chances are this cache rename operation may happen before // the notification thread trys clean up. // NOTE: We should have the code to remove the entry for rename // operation as the operation could have been performed by some other // process such as amadmin. String oldDN = MiscUtils.formatToRFC(entryDN); CacheBlock cb = (CacheBlock) sdkCache.remove(oldDN); newDN = MiscUtils.formatToRFC(newDN); sdkCache.put(newDN, cb); return newDN; }
/** * 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 objecttype is unknown * @throws SSOException if ssoToken is invalid or expired. */ public int getObjectType(SSOToken token, String dn) throws AMException, SSOException { int objectType = AMObject.UNDETERMINED_OBJECT_TYPE; String entryDN = MiscUtils.formatToRFC(dn); CacheBlock cb = (CacheBlock) sdkCache.get(entryDN); if (cb != null) { // Check if the entry exists, if not present throw an exception if (!doesEntryExists(token, dn)) { String locale = MiscUtils.getUserLocale(token); String params[] = {cb.getEntryDN()}; throw new AMException(AMSDKBundle.getString("461", params, locale), "461", params); } validateEntry(token, cb); objectType = cb.getObjectType(); if (objectType != AMObject.UNDETERMINED_OBJECT_TYPE) { return objectType; } } // Use admintoken to get object type, so that it can be cached SSOToken adminToken = (SSOToken) AccessController.doPrivileged(AdminTokenAction.getInstance()); // The method below will throw an AMException if the entry does not // exist in the directory. If it exists, then create a cache entry for // this DN if (cb == null) { objectType = super.getObjectType(adminToken, entryDN); cb = new CacheBlock(entryDN, true); sdkCache.put(entryDN, cb); } else { objectType = super.getObjectType( adminToken, entryDN, cb.getAttributes(MiscUtils.getPrincipalDN(adminToken), false)); } cb.setObjectType(objectType); if (objectType == AMObject.ORGANIZATION || objectType == AMObject.ORGANIZATIONAL_UNIT) { cb.setOrganizationDN(entryDN); } return objectType; }
private void setOrganizationDNs(String organizationDN, Set childDNSet) { Iterator itr = childDNSet.iterator(); while (itr.hasNext()) { String cDN = (String) itr.next(); CacheBlock cb = (CacheBlock) sdkCache.get(cDN); if (cb == null) { cb = new CacheBlock(cDN, organizationDN, true); sdkCache.put(cDN, cb); } else { cb.setOrganizationDN(organizationDN); } } if (getDebug().messageEnabled() && !childDNSet.isEmpty()) { getDebug() .message( "CachedRemoteServicesImpl." + "setOrganizationDNs(): Set org DNs as: " + organizationDN + " for children: " + childDNSet); } }
public boolean doesEntryExists(SSOToken token, String entryDN) { String dn = MiscUtils.formatToRFC(entryDN); CacheBlock cb = (CacheBlock) sdkCache.get(dn); if (cb != null && !cb.hasExpiredAndUpdated()) { if (getDebug().messageEnabled()) { getDebug() .message( "CachedRemoteServicesImpl." + "doesEntryExist(): entryDN: " + entryDN + " found in cache & exists: " + cb.isExists()); } return cb.isExists(); } else { boolean isPresent = super.doesEntryExists(token, dn); if (getDebug().messageEnabled()) { getDebug() .message( "CachedRemoteServicesImpl." + "doesEntryExist(): entryDN: " + entryDN + " got from DS & exists: " + isPresent); } // Intialize the CacheBock based on isPresent // Intialize the CacheBock based on isPresent if (cb == null) { cb = new CacheBlock(entryDN, isPresent); sdkCache.put(dn, cb); } else { // Cache Block might have just expired, just reset the // isExists flag once again cb.setExists(isPresent); } return isPresent; } }
/** * 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 */ public Map getAttributes( SSOToken token, String entryDN, Set attrNames, boolean ignoreCompliance, boolean byteValues, int profileType) throws AMException, SSOException { if (attrNames == null || attrNames.isEmpty()) { return getAttributes(token, entryDN, ignoreCompliance, byteValues, profileType); } // Attributes are being requested; increment cache stats request counter cacheStats.incrementRequestCount(getSize()); // Load the whole attrset in the cache, if in DCTree mode // Not good for performance, but fix later TODO (Deepa) if (dcTreeServicesImpl.isRequired()) { // TODO: This needs to be fixed! getAttributes(token, entryDN, ignoreCompliance, byteValues, profileType); } String principalDN = MiscUtils.getPrincipalDN(token); if (getDebug().messageEnabled()) { getDebug() .message( "In CachedRemoteServicesImpl.getAttributes(" + "SSOToken entryDN, attrNames, ignoreCompliance, " + "byteValues) " + "(" + principalDN + ", " + entryDN + ", " + attrNames + ", " + ignoreCompliance + ", " + byteValues + " method."); } String dn = MiscUtils.formatToRFC(entryDN); CacheBlock cb = (CacheBlock) sdkCache.get(dn); if (cb == null) { // Entry not present in cache if (getDebug().messageEnabled()) { getDebug() .message( "CachedRemoteServicesImpl." + "getAttributes(): NO entry found in Cache. Getting" + " all these attributes from DS: " + attrNames); } // If the attributes returned here have an empty set as value, then // such attributes do not have a value or invalid attributes. // Internally keep track of these attributes. AMHashMap attributes = (AMHashMap) super.getAttributes( token, entryDN, attrNames, ignoreCompliance, byteValues, profileType); // These attributes are either not present or not found in DS. // Try to check if they need to be fetched by external // plugins Set missAttrNames = attributes.getMissingAndEmptyKeys(attrNames); cb = new CacheBlock(dn, true); cb.putAttributes(principalDN, attributes, missAttrNames, false, byteValues); sdkCache.put(dn, cb); if (!missAttrNames.isEmpty()) { attributes = getPluginAttrsAndUpdateCache( token, principalDN, entryDN, cb, attributes, missAttrNames, byteValues, profileType); } return attributes; } else { // Entry present in cache validateEntry(token, cb); // Entry may be an invalid entry AMHashMap attributes = (AMHashMap) cb.getAttributes(principalDN, attrNames, byteValues); // Find the missing attributes that need to be obtained from DS // Only find the missing keys as the ones with empty sets are not // found in DS Set missAttrNames = attributes.getMissingKeys(attrNames); if (!missAttrNames.isEmpty()) { boolean isComplete = cb.hasCompleteSet(principalDN); AMHashMap dsAttributes = null; if (!isComplete || // Check for "nsRole" and "nsRoleDN" attributes missAttrNames.contains(NSROLEDN_ATTR) || missAttrNames.contains(NSROLE_ATTR)) { if (getDebug().messageEnabled()) { getDebug() .message( "CachedRemoteServicesImpl." + "getAttributes(): Trying to get these missing" + " attributes from DS: " + missAttrNames); } dsAttributes = (AMHashMap) super.getAttributes( token, entryDN, missAttrNames, ignoreCompliance, byteValues, profileType); if (dsAttributes != null) { attributes.putAll(dsAttributes); // Add these attributes, may be found in DS or just mark // as invalid (Attribute level Negative caching) Set newMissAttrNames = dsAttributes.getMissingAndEmptyKeys(missAttrNames); // Update dsAttributes with rest of the attributes // in cache dsAttributes.putAll(cb.getAttributes(principalDN, byteValues)); // Update the cache cb.putAttributes(principalDN, dsAttributes, newMissAttrNames, isComplete, byteValues); missAttrNames = newMissAttrNames; } } else { // Update cache with invalid attributes cb.putAttributes( principalDN, cb.getAttributes(principalDN, byteValues), missAttrNames, isComplete, byteValues); } if (!missAttrNames.isEmpty()) { attributes = getPluginAttrsAndUpdateCache( token, principalDN, entryDN, cb, attributes, missAttrNames, byteValues, profileType); } } else { // All attributes found in cache if (getDebug().messageEnabled()) { getDebug() .message( "CachedRemoteServicesImpl." + "getAttributes(): found all attributes in " + "Cache."); } cacheStats.updateHitCount(getSize()); } // Remove all the empty values from the return attributes return attributes; } }
/** * 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. * @param byteValues if false StringValues are fetched, if true byte values are fetched. * @param profileType the oject type of entryDN * @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 */ public Map getAttributes( SSOToken token, String entryDN, boolean ignoreCompliance, boolean byteValues, int profileType) throws AMException, SSOException { // Attributes are being requested; increment cache stats request counter cacheStats.incrementRequestCount(getSize()); String principalDN = MiscUtils.getPrincipalDN(token); String dn = MiscUtils.formatToRFC(entryDN); if (getDebug().messageEnabled()) { getDebug() .message( "In CachedRemoteServicesImpl.getAttributes(" + "SSOToken entryDN, ignoreCompliance) " + "(" + principalDN + ", " + entryDN + ", " + ignoreCompliance + " method."); } CacheBlock cb = (CacheBlock) sdkCache.get(dn); AMHashMap attributes = null; if (cb != null) { validateEntry(token, cb); if (cb.hasCompleteSet(principalDN)) { cacheStats.updateHitCount(getSize()); if (getDebug().messageEnabled()) { getDebug() .message( "CachedRemoteServicesImpl." + "getAttributes(): found all attributes in " + "Cache."); } attributes = (AMHashMap) cb.getAttributes(principalDN, byteValues); } else { // Get the whole set from DS and store it; // ignore incomplete set if (getDebug().messageEnabled()) { getDebug() .message( "CachedRemoteServicesImpl." + "getAttributes(): complete attribute set NOT " + "found in cache. Getting from DS."); } attributes = (AMHashMap) super.getAttributes(token, entryDN, ignoreCompliance, byteValues, profileType); cb.putAttributes(principalDN, attributes, null, true, byteValues); } } else { // Attributes not cached // Get all the attributes from DS and store them attributes = (AMHashMap) super.getAttributes(token, entryDN, ignoreCompliance, byteValues, profileType); cb = new CacheBlock(entryDN, true); cb.putAttributes(principalDN, attributes, null, true, byteValues); sdkCache.put(dn, cb); if (getDebug().messageEnabled()) { getDebug() .message( "CachedRemoteServicesImpl." + "getAttributes(): attributes NOT found in cache. " + "Fetched from DS."); } } // Get all external DS attributes by calling plugin modules. // Note these attributes should not be cached. Map extAttributes = getExternalAttributes(token, entryDN, null, profileType); if (extAttributes != null && !extAttributes.isEmpty()) { // Note the attributes stored in the cache are already copied to a // new map. Hence modifying this attributes is okay. if (getDebug().messageEnabled()) { getDebug() .message( "CachedRemoteServicesImpl." + "getAttributes(): External attributes present. Adding" + " them with original list"); } attributes.putAll(extAttributes); } return attributes; }