/** * 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 that updates the cache entries locally. This method does a write through cache */ private void updateCache(SSOToken token, String dn, Map stringAttributes, Map byteAttributes) throws SSOException { String key = MiscUtils.formatToRFC(dn); CacheBlock cb = (CacheBlock) sdkCache.get(key); if (cb != null && !cb.hasExpiredAndUpdated() && cb.isExists()) { String pDN = MiscUtils.getPrincipalDN(token); cb.replaceAttributes(pDN, stringAttributes, byteAttributes); } }
private void dirtyCache(String dn) { String key = MiscUtils.formatToRFC(dn); CacheBlock cb = (CacheBlock) sdkCache.get(key); if (cb != null) { cb.clear(); } }
/** * 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; }
private void dirtyCache(Set entries) { Iterator itr = entries.iterator(); while (itr.hasNext()) { String entryDN = (String) itr.next(); String key = MiscUtils.formatToRFC(entryDN); CacheBlock cb = (CacheBlock) sdkCache.get(key); if (cb != null) { cb.clear(); } } }
/** * 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; }
/** * Create an AMTemplate (COSTemplate) * * @param token token * @param entryDN DN of the profile whose template is to be set * @param objectType the object type * @param serviceName Service Name * @param attributes attributes to be set * @param priority template priority * @return String DN of the newly created template */ public String createAMTemplate( SSOToken token, String entryDN, int objectType, String serviceName, Map attributes, int priority) throws AMException { String templateDN = super.createAMTemplate(token, entryDN, objectType, serviceName, attributes, priority); // Mark the entry as exists in cache String dn = MiscUtils.formatToRFC(templateDN); CacheBlock cb = (CacheBlock) sdkCache.get(dn); if (cb != null) { cb.setExists(true); } return templateDN; }
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; }
private synchronized void removeFromCache(String dn) { String key = MiscUtils.formatToRFC(dn); sdkCache.remove(key); }
/** * This method will be called by <code>AMIdRepoListener</code>. This method will update the cache * by removing all the entires which are affected as a result of an event notification caused * because of changes/deletions/renaming of entries with and without aci's. * * <p>NOTE: The event could have been caused either by changes to an aci entry or a costemplate or * a cosdefinition or changes to a normal entry * * @param dn name of entity being modified * @param eventType type of modification * @param cosType true if it is cos related. false otherwise * @param aciChange true if it is aci related. false otherwise * @param attrNames Set of attribute Names which should be removed from the CacheEntry in the case * of COS change */ public void dirtyCache( String dn, int eventType, boolean cosType, boolean aciChange, Set attrNames) { CacheBlock cb; String origdn = dn; dn = MiscUtils.formatToRFC(dn); switch (eventType) { case AMEvent.OBJECT_ADDED: cb = (CacheBlock) sdkCache.get(dn); if (cb != null) { // Mark an invalid entry as valid now cb.setExists(true); } if (cosType) { // A cos type event remove all affected attributes removeCachedAttributes(dn, attrNames); } break; case AMEvent.OBJECT_REMOVED: cb = (CacheBlock) sdkCache.remove(dn); if (cb != null) { cb.clear(); // Clear anyway & help the GC process } if (cosType) { removeCachedAttributes(dn, attrNames); } break; case AMEvent.OBJECT_RENAMED: // Better to remove the renamed entry, or else it will be just // hanging in the cache, until LRU kicks in. cb = (CacheBlock) sdkCache.remove(dn); if (cb != null) { cb.clear(); // Clear anyway & help the GC process } if (cosType) { removeCachedAttributes(dn, attrNames); } break; case AMEvent.OBJECT_CHANGED: cb = (CacheBlock) sdkCache.get(dn); if (cb != null) { cb.clear(); // Just clear the entry. Don't remove. } if (cosType) { removeCachedAttributes(dn, attrNames); } else if (aciChange) { // Clear all affected entries clearCachedEntries(dn); } break; } if (getDebug().messageEnabled()) { getDebug() .message( "CachedRemoteServicesImpl.dirtyCache(): " + "Cache dirtied because of Event Notification. Parameters" + " - eventType: " + eventType + ", cosType: " + cosType + ", aciChange: " + aciChange + ", fullDN: " + origdn + "; rfcDN =" + dn); } }