8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Copyright (c) 2005 Sun Microsystems Inc. All Rights Reserved
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The contents of this file are subject to the terms
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * of the Common Development and Distribution License
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * (the License). You may not use this file except in
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * compliance with the License.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * You can obtain a copy of the License at
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * https://opensso.dev.java.net/public/CDDLv1.0.html or
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * See the License for the specific language governing
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * permission and limitations under the License.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * When distributing Covered Code, include this CDDL
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Header Notice in each file and include the License file
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * If applicable, add the following below the CDDL Header,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * with the fields enclosed by brackets [] replaced by
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * your own identifying information:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * "Portions Copyrighted [year] [name of copyright owner]"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * $Id: CachedSMSEntry.java,v 1.16 2009/10/08 20:33:54 hengming Exp $
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * Portions Copyrighted 2015 ForgeRock AS.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The class <code>CachedSchemaManagerImpl</code> provides interfaces to
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * manage the SMSEntry. It caches SMSEntries which is used by ServiceSchema and
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * ServiceConfig classes.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Notification method that will be called for ServiceSchemaManagerImpls
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster protected static final String UPDATE_METHOD = "update";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Cache of CachedSMSEntries (static)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster protected static Map smsEntries = Collections.synchronizedMap(
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Instance variables
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Set of ServiceSchemaManagerImpls and ServiceConfigImpls
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // that must be updated where entry changes
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster protected Set serviceObjects = Collections.synchronizedSet(
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster protected Set principals = Collections.synchronizedSet(
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster new HashSet(10)); // Principals who have read access
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster protected SSOToken token; // Valid SSOToken used for read
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Flag that determines if this object can be used
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Flag to determine if the cached entry is dirty and
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // must be refreshed along with the last update time & TTL
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Private constructor, can be instantiated only via getInstance
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Set the SMSEntry as read only
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Register for notifications
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster notificationID = SMSEventListenerManager.notifyChangesToNode(
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster token, smsEntry.getDN(), UPDATE_FUNC, this, null);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Write debug messages
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SMSEntry.debug.message("CachedSMSEntry: New instance: " + dn);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // ----------------------------------------------
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Protected instance methods
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // ----------------------------------------------
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Used by JAXRPCObjectImpl
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ((System.currentTimeMillis() - lastUpdate) > ttl)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster synchronized (dirtyLock) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Invoked by SMSEventListenerManager when entry has been changed.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Mark the entry as dirty and return. The method refresh() must be
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * called to read the attributes.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SMSEntry.debug.message("CachedSMSEntry: update "
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster synchronized (dirtyLock) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Reads the attributes from the datastore and send notifications to
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * objects caching this entry. Used by JAXRPCObjectImpl
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster synchronized (dirtyLock) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SMSEntry.debug.message("CachedSMSEntry: refresh "
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Read the LDAP attributes and update listeners
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster boolean updated = false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SMSEntry.debug.warning("CachedSMSEntry:update No VALID " +
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Error in reading the attribtues, entry could be deleted
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // or does not have permissions to read the object
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SMSEntry.debug.error("Error in reading entry attributes: " +
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Error in reading the attribtues, SSOToken problem
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Might have timed-out
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SMSEntry.debug.error("SSOToken problem in reading entry "
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // No valid SSOToken were foung
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // this entry is no long valid, remove from cache
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Update service listeners either success or failure
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // updateServiceListeners(UPDATE_METHOD);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Updates the attributes from the provided <class>SMSEntry</class>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * and marks the entry as non-dirty.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param e object that contains the updated values for the attributes
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @throws com.sun.identity.sm.SMSException
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster synchronized (dirtyLock) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Clears the local variables and marks the entry as invalid
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Called by the SMS objects that have an instance of CachedSMSEntry
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Marks the object to be invalid and deregisters for notifications.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Called by the static method clearCache()
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param removeFromCache remove itself from cache if set to true
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // this entry is no long valid, remove from cache
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SMSEventListenerManager.removeNotification(notificationID);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster synchronized(dirtyLock) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Remove from cache
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Returns a valid SSOToken that can be used for reading
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Check if the cached SSOToken is valid
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Get a valid ssoToken from cached TokenIDs
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster synchronized (principals) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for (Iterator items = principals.iterator(); items.hasNext();) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // SSOToken has expired, remove from list
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // If there are no valid SSO Tokens return null
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Sends notifications to ServiceSchemaManagerImpl and ServiceConfigImpl
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The method determines the object's method that would be invoked.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * It could be either update() -- in which only the local instances are
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * updated, or updateAndNotify() -- in which case the listeners are also
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param method either "update" or "updateAndNotify"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private void updateServiceListeners(String method) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SMSEntry.debug.message("CachedSMSEntry::updateServiceListeners "
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Inform the ServiceSchemaManager's of changes to attributes
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster synchronized (serviceObjects) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for(Iterator objs = serviceObjects.iterator(); objs.hasNext();) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for(Iterator objs = tmpServiceObjects.iterator(); objs.hasNext();){
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SMSEntry.debug.error("CachedSMSEntry::unable to " +
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Method to add objects that needs notifications
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Method to remove objects that needs notifications
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster protected void removeServiceListener(Object o) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SMSEventListenerManager.removeNotification(notificationID);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Making a local copy to avoid synchronization problems
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return (principals.contains(t.getTokenID().toString()));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SMSEntry.debug.error("Unable to clone SMSEntry: " + smsEntry, c);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // ----------------------------------------------
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // protected static methods
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // ----------------------------------------------
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Used by ServiceSchemaManager
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster static CachedSMSEntry getInstance(SSOToken t, ServiceSchemaManagerImpl ssm,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String serviceName, String version) throws SMSException {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String dn = ServiceManager.getServiceNameDN(serviceName, version);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SMSEntry.debug.error("SMS: Invalid SSOToken: ", ssoe);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public static CachedSMSEntry getInstance(SSOToken t, String dn)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SMSEntry.debug.message("CachedSMSEntry::getInstance: " + dn);
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington String cacheEntry = DN.valueOf(dn).toString().toLowerCase();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster CachedSMSEntry answer = (CachedSMSEntry) smsEntries.get(cacheEntry);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Construct the SMS entry. Should be outside the synchronized
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // block since SMSEntry call delegation which in turn calls
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // policy, idrepo, special repo and SMS again
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster CachedSMSEntry tmp = new CachedSMSEntry(new SMSEntry(t, dn));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster synchronized (smsEntries) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (((answer = (CachedSMSEntry) smsEntries.get(cacheEntry))
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Add it to cache
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Check if user has permissions
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Read the SMS entry as that user, and ignore the results
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SMSEntry.debug.message("CachedSMSEntry: obtained instance: " + dn);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Initialize the TTL
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String ttlEnabledString = SystemProperties.get(
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ttlEnabled = Boolean.valueOf(ttlEnabledString).booleanValue();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String cacheTime = SystemProperties.get(Constants.SMS_CACHE_TTL);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Convert minutes to milliseconds
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SMSEntry.debug.error("CachedSMSEntry:init Invalid time " +
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Clears the cache
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster synchronized (smsEntries) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for (Iterator items = smsEntries.values().iterator();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster CachedSMSEntry cEntry = (CachedSMSEntry) items.next();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // this entry is no long valid
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Remove all entries from cache
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // ----------------------------------------------
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // protected instance methods for ServiceSchemaManager
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // ----------------------------------------------
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String[] schema = smsEntry.getAttributeValues(SMSEntry.ATTR_SCHEMA);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // The entry could be deleted, hence return null
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Since schema is a single valued attribute
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster void writeXMLSchema(SSOToken token, InputStream xmlServiceSchema)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster throws SSOException, SMSException, IOException {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int lengthOfStream = xmlServiceSchema.available();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster xmlServiceSchema.read(byteArray, 0, lengthOfStream);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster void writeXMLSchema(SSOToken token, String xmlSchema) throws SSOException,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Validate SSOtoken
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Replace the attribute in the directory
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster e.setAttribute(SMSEntry.ATTR_SCHEMA, attrValues);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SMSEntry.debug.message("CachedSMSEntry::writeXMLSchema: "
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster + "successfully wrote the XML schema for dn: " + e.getDN());
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Protected static variables
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster "com.sun.identity.sm.CachedSMSEntry");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster UPDATE_FUNC = CACHED_SMSENTRY.getDeclaredMethod(
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Should not happen, ignore