ccf9d4a5c6453fa9f8b839baeee25147865fbb7dJames Phillpotts/*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Copyright (c) 2005 Sun Microsystems Inc. All Rights Reserved
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
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 *
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 * opensso/legal/CDDLv1.0.txt
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * See the License for the specific language governing
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * permission and limitations under the License.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * When distributing Covered Code, include this CDDL
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Header Notice in each file and include the License file
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * at opensso/legal/CDDLv1.0.txt.
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 *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * $Id: CacheBlockBase.java,v 1.6 2009/10/29 00:28:46 hengming Exp $
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest * Portions Copyrighted 2011-2016 ForgeRock AS.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
ccf9d4a5c6453fa9f8b839baeee25147865fbb7dJames Phillpotts
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterpackage com.iplanet.am.sdk.common;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
ccf9d4a5c6453fa9f8b839baeee25147865fbb7dJames Phillpottsimport static org.forgerock.openam.utils.Time.*;
ccf9d4a5c6453fa9f8b839baeee25147865fbb7dJames Phillpotts
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.iplanet.am.sdk.AMHashMap;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.iplanet.am.sdk.AMObject;
e4c435db2e64b396f97aabc84fa409decc921989Neil Maddenimport com.sun.identity.common.CaseInsensitiveHashSet;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.sun.identity.shared.debug.Debug;
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.util.Collections;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.util.HashSet;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.util.Iterator;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.util.Map;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.util.Set;
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrestimport java.util.concurrent.locks.ReentrantReadWriteLock;
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrestimport java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrestimport java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This class represents the value part stored in the AMCacheManager's cache.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Each CacheBlock object would represent a Directory entry. It caches the
1f9880666ba8cc0f7ee5dcb20652e33e8ba942c1Mark de Reeper * attributes corresponding to that entry. It also keeps track of the other
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * details such as the Organization DN for the entry.
1f9880666ba8cc0f7ee5dcb20652e33e8ba942c1Mark de Reeper *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * <p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Also, this cache block can be used to serve as dummy block representing a
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * non-existent directory entry (negative caching). This prevents making
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * un-necessary directory calls for non-existent directory entries.
1f9880666ba8cc0f7ee5dcb20652e33e8ba942c1Mark de Reeper *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * <p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Since the attributes that can be retrieved depends on the principal
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * performing the operation (ACI's set), the result set would vary. The
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * attributes that are returned are the ones that are readable by the principal.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Each cache block keeps account of these differences in result sets by storing
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * all the attributes readable (and writable) on a per principal basis. This
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * information is stored in a PrincipalAccess object. In order to avoid
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * duplicate copy of the values, the all attribute values are not cached per
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * principal. A single copy of the attributes is stored in the CacheBlock
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * object. Also this copy of attributes stored in the cache block keeps track of
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * non-existent directory attributes (invalid attributes). This would also
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * prevent un-necessary directory calls for non-existent entry attributes.
1f9880666ba8cc0f7ee5dcb20652e33e8ba942c1Mark de Reeper *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The attribute copy is dirtied by removing the entries which get modified.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterpublic abstract class CacheBlockBase {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Maintains a Cache of cacheEntries.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private AMHashMap cacheEntries;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // CacheBock representation entry DN
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest private final String entryDN;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest private volatile int objectType = AMObject.UNDETERMINED_OBJECT_TYPE; // Not known yet
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private AMHashMap stringAttributes; // Stores all String attributes
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private AMHashMap byteAttributes; // Stores all byte attributes
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest private volatile long lastModifiedTime = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // A true value here makes sures that timestamp is added the very first
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // time
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest private volatile boolean isExpired = false; // indicates if the entry has expired
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // The Organization DN corresponding to this record
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest private volatile String organizationDN = null; // Always pass a RFC lowercase
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // string
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Indicates if this Entry represents a valid DS Entry.
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest private volatile boolean isValidEntry = true;
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest private final ReadLock readLock = lock.readLock();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest private final WriteLock writeLock = lock.writeLock();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public CacheBlockBase(String entryDN, boolean validEntry) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (validEntry) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster cacheEntries = new AMHashMap();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster stringAttributes = new AMHashMap(false);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster byteAttributes = new AMHashMap(true);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Do not intialize CacheEntries, as it represents a invalid entry
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster isValidEntry = false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster setLastModifiedTime();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster this.entryDN = entryDN;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public CacheBlockBase(String entryDN, String orgDN, boolean validEntry) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster this(entryDN, validEntry);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster this.organizationDN = orgDN;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper public abstract boolean isEntryExpirationEnabled();
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper public abstract long getUserEntryExpirationTime();
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper public abstract long getDefaultEntryExpirationTime();
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper public abstract Debug getDebug();
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest public void setExists(boolean exists) {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest writeLock.lock();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest try {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest if (exists) {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest cacheEntries = new AMHashMap();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest stringAttributes = new AMHashMap(false);
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest byteAttributes = new AMHashMap(true);
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest }
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest isValidEntry = exists;
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest updateLastModifiedTime();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest } finally {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest writeLock.unlock();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest private void setLastModifiedTime() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (isEntryExpirationEnabled()) { // First time setup
ccf9d4a5c6453fa9f8b839baeee25147865fbb7dJames Phillpotts lastModifiedTime = currentTimeMillis();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest private void updateLastModifiedTime() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (isEntryExpirationEnabled() && isExpired) {
ccf9d4a5c6453fa9f8b839baeee25147865fbb7dJames Phillpotts lastModifiedTime = currentTimeMillis();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster isExpired = false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest public void setObjectType(int type) {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest writeLock.lock();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest try {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest objectType = type;
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest updateLastModifiedTime();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest } finally {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest writeLock.unlock();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest public void setOrganizationDN(String orgDN) {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest writeLock.lock();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest try {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest organizationDN = orgDN;
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest updateLastModifiedTime();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest } finally {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest writeLock.unlock();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public String getOrganizationDN() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Call this to expire the value if needed. If expired, a null value
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // will be returned. It is okay as the orgDN will be fetched again.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster hasExpiredAndUpdated();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return organizationDN;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public int getObjectType() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return objectType;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public String getEntryDN() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // No need to call expiredAndUpdated here. Because this does not change
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // This block is corresponding to key entryDN in the map. So, it is okay
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // to leave this unchanged.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return entryDN;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Method which specifies if the entry exists in the directory or is an
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * invalid entry. <br>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * <b>NOTE:</b> Call to this method should preceeded with
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * expiredAndUpdated() check. For example, isExists() return value holds
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * good only it the entry has not expired. So, check anywhere it is called
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * the check should be if (!cb.expiredAndUpdated() && cb.isExists()) or
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * similar.
1f9880666ba8cc0f7ee5dcb20652e33e8ba942c1Mark de Reeper *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return true if it represents a valid entry, false otherwise
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest public boolean isExists() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // We cannot call expiredAndUpdated() here as it will change the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // behaviour of the method. Hence it needs to called externally.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return isValidEntry;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper /**
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper * <p>If cache expiry has been enabled then this will return true if the cache has expired.</p>
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper * <b>Note:</b> This call must be made outside of a readLock because if the cache has expired then a writeLock
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper * is required as part of calling {@link CacheBlockBase#clear()} which would result in a deadlock, a readLock
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper * cannot be upgraded to a writeLock.
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper * @return true if cache expiry is enabled and the cache has expired
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper */
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest public boolean hasExpiredAndUpdated() {
eb5a3a5e8c9a94221c5b0e54b511b29c2e9aa2ecKajetan Hemzaczek readLock.lock();
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper try {
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper // We need to have the isExpired variable to make sure
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper // the notifications are sent only once.
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper if (isEntryExpirationEnabled() && !isExpired) { // Happens only if enabled
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper long expirationTime = 0;
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper switch (objectType) {
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper case AMObject.USER:
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper expirationTime = getUserEntryExpirationTime();
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper break;
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper default:
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper expirationTime = getDefaultEntryExpirationTime();
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper break;
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper }
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper long elapsedTime = currentTimeMillis() - lastModifiedTime;
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper if (elapsedTime >= expirationTime) { // Expired
eb5a3a5e8c9a94221c5b0e54b511b29c2e9aa2ecKajetan Hemzaczek readLock.unlock();
eb5a3a5e8c9a94221c5b0e54b511b29c2e9aa2ecKajetan Hemzaczek writeLock.lock();
eb5a3a5e8c9a94221c5b0e54b511b29c2e9aa2ecKajetan Hemzaczek try {
eb5a3a5e8c9a94221c5b0e54b511b29c2e9aa2ecKajetan Hemzaczek elapsedTime = currentTimeMillis() - lastModifiedTime;
eb5a3a5e8c9a94221c5b0e54b511b29c2e9aa2ecKajetan Hemzaczek if (!isExpired && elapsedTime >= expirationTime) { // Expired
eb5a3a5e8c9a94221c5b0e54b511b29c2e9aa2ecKajetan Hemzaczek // Send notifications first to the SDK listeners
eb5a3a5e8c9a94221c5b0e54b511b29c2e9aa2ecKajetan Hemzaczek isExpired = true;
eb5a3a5e8c9a94221c5b0e54b511b29c2e9aa2ecKajetan Hemzaczek clear();
eb5a3a5e8c9a94221c5b0e54b511b29c2e9aa2ecKajetan Hemzaczek if (getDebug().messageEnabled()) {
eb5a3a5e8c9a94221c5b0e54b511b29c2e9aa2ecKajetan Hemzaczek getDebug().message(
eb5a3a5e8c9a94221c5b0e54b511b29c2e9aa2ecKajetan Hemzaczek "CacheBlock.hasExpiredAndUpdated(): "
eb5a3a5e8c9a94221c5b0e54b511b29c2e9aa2ecKajetan Hemzaczek + "Entry with DN " + entryDN + " expired.");
eb5a3a5e8c9a94221c5b0e54b511b29c2e9aa2ecKajetan Hemzaczek }
eb5a3a5e8c9a94221c5b0e54b511b29c2e9aa2ecKajetan Hemzaczek // FIXME: AMObjectImpl.sendExpiryEvent(entryDN, sourceType);
eb5a3a5e8c9a94221c5b0e54b511b29c2e9aa2ecKajetan Hemzaczek // TODO: Add object notification mechanism
eb5a3a5e8c9a94221c5b0e54b511b29c2e9aa2ecKajetan Hemzaczek }
eb5a3a5e8c9a94221c5b0e54b511b29c2e9aa2ecKajetan Hemzaczek readLock.lock();
eb5a3a5e8c9a94221c5b0e54b511b29c2e9aa2ecKajetan Hemzaczek } finally {
eb5a3a5e8c9a94221c5b0e54b511b29c2e9aa2ecKajetan Hemzaczek writeLock.unlock();
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper return isExpired;
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper } finally {
eb5a3a5e8c9a94221c5b0e54b511b29c2e9aa2ecKajetan Hemzaczek readLock.unlock();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest public boolean hasCache(String principalDN) {
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper boolean hasExpired = hasExpiredAndUpdated();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest readLock.lock();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest try {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest CacheEntry ce = (CacheEntry) cacheEntries.get(principalDN);
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper return (ce != null && !hasExpired);
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest } finally {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest readLock.unlock();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest public boolean hasCompleteSet(String principalDN) {
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper boolean hasExpired = hasExpiredAndUpdated();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest readLock.lock();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest try {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest CacheEntry ce = (CacheEntry) cacheEntries.get(principalDN);
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper if (ce != null && !hasExpired) {
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper return ce.isCompleteSet();
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper } else {
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper return false;
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest }
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest } finally {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest readLock.unlock();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest public Map getAttributes(String principalDN, boolean byteValues) {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest return getAttributes(principalDN, null, byteValues);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest public Map getAttributes(String principalDN, Set attrNames, boolean byteValues) {
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper boolean hasExpired = hasExpiredAndUpdated();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Map attributes = new AMHashMap(byteValues);
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest readLock.lock();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest try {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest // Get the cache entry for the principal
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest CacheEntry ce = (CacheEntry) cacheEntries.get(principalDN);
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper if (ce != null && !hasExpired) {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest // Get the names of attributes that this principal can access
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest Set accessibleAttrs = null;
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest if (attrNames == null) {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest accessibleAttrs = ce.getReadableAttrNames();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest } else {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest accessibleAttrs = ce.getReadableAttrNames(attrNames);
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest }
1f9880666ba8cc0f7ee5dcb20652e33e8ba942c1Mark de Reeper if (!accessibleAttrs.isEmpty()) {
1f9880666ba8cc0f7ee5dcb20652e33e8ba942c1Mark de Reeper // Get the attribute values from the appropriate string or binary cache if they exist.
1f9880666ba8cc0f7ee5dcb20652e33e8ba942c1Mark de Reeper if (!byteValues) {
1f9880666ba8cc0f7ee5dcb20652e33e8ba942c1Mark de Reeper attributes = stringAttributes.getCopy(accessibleAttrs);
1f9880666ba8cc0f7ee5dcb20652e33e8ba942c1Mark de Reeper if (attributes.isEmpty()) {
1f9880666ba8cc0f7ee5dcb20652e33e8ba942c1Mark de Reeper if (getDebug().messageEnabled()) {
1f9880666ba8cc0f7ee5dcb20652e33e8ba942c1Mark de Reeper getDebug().message("CacheBlockBase.getAttributes(): accessibleAttrs:" + accessibleAttrs
1f9880666ba8cc0f7ee5dcb20652e33e8ba942c1Mark de Reeper + " not found in stringAttributes, attributes in the byteAttributes cache:"
1f9880666ba8cc0f7ee5dcb20652e33e8ba942c1Mark de Reeper + byteAttributes.keySet());
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
1f9880666ba8cc0f7ee5dcb20652e33e8ba942c1Mark de Reeper } else {
1f9880666ba8cc0f7ee5dcb20652e33e8ba942c1Mark de Reeper attributes = byteAttributes.getCopy(accessibleAttrs);
1f9880666ba8cc0f7ee5dcb20652e33e8ba942c1Mark de Reeper if (attributes.isEmpty()) {
1f9880666ba8cc0f7ee5dcb20652e33e8ba942c1Mark de Reeper if (getDebug().messageEnabled()) {
1f9880666ba8cc0f7ee5dcb20652e33e8ba942c1Mark de Reeper getDebug().message("CacheBlockBase.getAttributes(): accessibleAttrs:" + accessibleAttrs
1f9880666ba8cc0f7ee5dcb20652e33e8ba942c1Mark de Reeper + " not found in byteAttributes, attributes in the stringAttributes cache:"
1f9880666ba8cc0f7ee5dcb20652e33e8ba942c1Mark de Reeper + stringAttributes.keySet());
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest // Get the names of attributes that are invalid/not accessible
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest Set inAccessibleAttrs = ce.getInaccessibleAttrNames(attrNames);
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest ((AMHashMap) attributes).addEmptyValues(inAccessibleAttrs);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest } finally {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest readLock.unlock();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper return attributes;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest public void putAttributes(String principalDN, Map attributes,
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest Set inAccessibleAttrNames, boolean isCompleteSet, boolean byteValues) {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest writeLock.lock();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest try {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest CacheEntry ce = (CacheEntry) cacheEntries.get(principalDN);
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest if (ce == null) {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest ce = new CacheEntry();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest cacheEntries.put(principalDN, ce);
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest // Copy only the attributes in the common place. Store the invalid/
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest // unreadable attrs per principal.
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest if (!byteValues) {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest Set attrsWithValues = stringAttributes.copyValuesOnly(attributes);
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest ce.putAttributes(attrsWithValues, inAccessibleAttrNames,
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest isCompleteSet);
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest } else {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest Set attrsWithValues = byteAttributes.copyValuesOnly(attributes);
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest ce.putAttributes(attrsWithValues, inAccessibleAttrNames,
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest isCompleteSet);
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest updateLastModifiedTime();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest } finally {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest writeLock.unlock();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest public void removeAttributes(String principalDN) {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest writeLock.lock();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest try {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest CacheEntry ce = (CacheEntry) cacheEntries.remove(principalDN);
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest if (ce != null) {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest ce.clear(); // To remove all used references
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest }
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest } finally {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest writeLock.unlock();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest public void removeAttributes(Set attrNames) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ((attrNames != null) && (!attrNames.isEmpty())) {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest writeLock.lock();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest try {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest stringAttributes.removeKeys(attrNames);
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest byteAttributes.removeKeys(attrNames);
fdd3077db2228482076ca7f288c80761f311ea0eMark de Reeper // Remove them from the list of readable attributes of each principal
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest Iterator itr = cacheEntries.keySet().iterator();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest while (itr.hasNext()) {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest String principalDN = (String) itr.next();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest removeAttributes(principalDN, attrNames);
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest }
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest } finally {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest writeLock.unlock();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest private void removeAttributes(String principalDN, Set attrNames) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster CacheEntry ce = (CacheEntry) cacheEntries.get(principalDN);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (ce != null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ce.removeAttributeNames(attrNames);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest public void replaceAttributes(String principalDN, Map sAttributes, Map bAttributes) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (sAttributes != null && !sAttributes.isEmpty()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster putAttributes(principalDN, sAttributes, null, false, false);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else if (bAttributes != null && !bAttributes.isEmpty()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster putAttributes(principalDN, bAttributes, null, false, true);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Should be cleared, only if the entry is still valid only the data has
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * changed. If entry has been deleted then should be removed.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest public void clear() {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest writeLock.lock();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest try {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest if (isValidEntry) { // Clear only if it is a valid entry
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest // If entry is not valid then all these maps will be null
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest stringAttributes.clear();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest byteAttributes.clear();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest cacheEntries.clear();
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest }
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest // Don't have to change isValidEntry as it would have been updated if
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest // the entry was deleted. Also do not change the object type here
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest // it is need. Ideally the object type won't change for a DN
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest lastModifiedTime = 0; // => expired
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest organizationDN = null; // Could have been renamed
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest } finally {
f3a3209406fe426c0c2db3af38ac588f856b52d0Andrew Forrest writeLock.unlock();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public String toString() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster StringBuilder sb = new StringBuilder();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster sb.append("\n----------- START CACHE BLOCK -----------");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster sb.append("\nEntry DN: ").append(entryDN);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster sb.append(" Valid Entry: ").append(isValidEntry);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster sb.append("\nOrganization: ").append(organizationDN);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster sb.append("\nString Attributes: ");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ((stringAttributes != null) && (!stringAttributes.isEmpty())) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster sb.append(MiscUtils.mapSetToString(stringAttributes));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster sb.append("\nByte Attributes: ");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster sb.append(MiscUtils.mapSetToString(byteAttributes));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster sb.append("\nByte Negative Attributes: ");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ((byteAttributes != null) && (!byteAttributes.isEmpty())) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster sb.append(byteAttributes.getNegativeByteAttrClone().toString());
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster sb.append("\nCache Entries: ");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (cacheEntries != null && !cacheEntries.isEmpty()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Iterator itr = cacheEntries.keySet().iterator();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster while (itr.hasNext()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String principal = (String) itr.next();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster CacheEntry ce = (CacheEntry) cacheEntries.get(principal);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster sb.append("\nPrincipal: ").append(principal);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster sb.append(ce.toString());
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster sb.append("<empty>");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster sb.append("\n----------- END CACHE BLOCK -----------");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return sb.toString();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster class CacheEntry {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private boolean completeSet = false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
e4c435db2e64b396f97aabc84fa409decc921989Neil Madden private final Set readableAttrNames;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Names of attributes which are either
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // 1 - not readable by the principal corresponding to this entry or
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // 2 - not present in the directory entry.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Either way there is not need to explictly distinguish them.
e4c435db2e64b396f97aabc84fa409decc921989Neil Madden private final Set inAccessibleAttrNames;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster CacheEntry() {
e4c435db2e64b396f97aabc84fa409decc921989Neil Madden readableAttrNames = new CaseInsensitiveHashSet();
e4c435db2e64b396f97aabc84fa409decc921989Neil Madden inAccessibleAttrNames = new CaseInsensitiveHashSet();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Method to get all the stored attributes
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return a new copy of the map of all attributes
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster protected Set getReadableAttrNames() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return (readableAttrNames);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster protected Set getReadableAttrNames(Set attrNames) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Return the intersection of attribute names present in stored set
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Set attributesPresent = new HashSet();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Iterator itr = attrNames.iterator();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster while (itr.hasNext()) {
e4c435db2e64b396f97aabc84fa409decc921989Neil Madden String name = (String) itr.next();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (readableAttrNames.contains(name)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster attributesPresent.add(name);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return attributesPresent;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster protected Set getInaccessibleAttrNames(Set attrNames) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Return the intersection of attribute names present in stored set
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (attrNames == null || attrNames.isEmpty()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Return empty set
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return Collections.EMPTY_SET;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Set attributesPresent = new HashSet();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Iterator itr = inAccessibleAttrNames.iterator();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Iterator itr = attrNames.iterator();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster while (itr.hasNext()) {
e4c435db2e64b396f97aabc84fa409decc921989Neil Madden String name = (String) itr.next();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (inAccessibleAttrNames.contains(name)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster attributesPresent.add(name);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return attributesPresent;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster protected void putAttributes(Set attrNames, Set invalidAttrs,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster boolean isCompleteSet) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster completeSet = isCompleteSet;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (attrNames != null && !attrNames.isEmpty()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // readableAttrNames.addAll(attrNames);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Iterator it = attrNames.iterator();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster while (it.hasNext()) {
e4c435db2e64b396f97aabc84fa409decc921989Neil Madden String name = (String) it.next();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster readableAttrNames.add(name);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster inAccessibleAttrNames.remove(name);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (invalidAttrs != null && !invalidAttrs.isEmpty()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // inAccessibleAttrNames.addAll(invalidAttrs);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Iterator it = invalidAttrs.iterator();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster while (it.hasNext()) {
e4c435db2e64b396f97aabc84fa409decc921989Neil Madden String name = (String) it.next();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster inAccessibleAttrNames.add(name);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster readableAttrNames.remove(name);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster protected void removeAttributeNames(Set attrNames) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster completeSet = false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Iterator iter = attrNames.iterator();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster while (iter.hasNext()) {
e4c435db2e64b396f97aabc84fa409decc921989Neil Madden String name = (String) iter.next();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster boolean removed = readableAttrNames.remove(name);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (!removed) { // May be in accessible attr. Try removing it.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster inAccessibleAttrNames.remove(name);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster protected boolean isCompleteSet() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return completeSet;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster protected void clear() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster completeSet = false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster readableAttrNames.clear();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster inAccessibleAttrNames.clear();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public String toString() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster StringBuilder sb = new StringBuilder();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster sb.append(" Complete Set: ").append(completeSet);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster sb.append(" Attributes: ").append(readableAttrNames);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster sb.append(" In Accessable attributes: ");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster sb.append(inAccessibleAttrNames);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return sb.toString();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}