8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Copyright (c) 2008 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: IndexCache.java,v 1.3 2009/12/12 00:03:13 veiming Exp $
9f5c397b0f840513ad40c4ee50b260a013438b67Andrew Forrest *
9f5c397b0f840513ad40c4ee50b260a013438b67Andrew Forrest * Portions copyright 2013 ForgeRock, Inc.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterpackage com.sun.identity.entitlement.opensso;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.sun.identity.entitlement.ResourceSaveIndexes;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.sun.identity.entitlement.ResourceSearchIndexes;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.util.HashSet;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.util.Set;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.util.concurrent.locks.ReadWriteLock;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.util.concurrent.locks.ReentrantReadWriteLock;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Caches the indexes which are stored in Directory Server.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterpublic class IndexCache {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public static final String HOST_ID = "host";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public static final String SUBJECT_ID = "subject";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public static final String PATH_ID = "path";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public static final String PARENTPATH_ID = "parentpath";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static final int CACHE_BUCKET_LIMIT = 25;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private int size = 1000000;
9f5c397b0f840513ad40c4ee50b260a013438b67Andrew Forrest private int initCapacity;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private Cache subjectIndexCache;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private Cache hostIndexCache;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private Cache pathIndexCache;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private Cache parentPathIndexCache;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private ReadWriteLock rwlock = new ReentrantReadWriteLock();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Constructs
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param size Size of cache.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public IndexCache(int size) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster this.size = size;
9f5c397b0f840513ad40c4ee50b260a013438b67Andrew Forrest initCapacity = (int) (size * 0.01d);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster clearCaches();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Caches indexes.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param indexes Resource cache indexes.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param subjectIndexes Subject search indexes.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param dn Distinguished name of the privilege.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public void cache(
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ResourceSaveIndexes indexes,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Set<String> subjectIndexes,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String dn) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (subjectIndexes != null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster cache(dn, subjectIndexes, subjectIndexCache);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster cache(dn, indexes.getHostIndexes(), hostIndexCache);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster cache(dn, indexes.getPathIndexes(), pathIndexCache);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster cache(dn, indexes.getParentPathIndexes(), parentPathIndexCache);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private void cache(String dn, Set<String> indexes, Cache cache) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rwlock.writeLock().lock();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster try {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for (String s : indexes) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String lc = s.toLowerCase();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Set<String> setDNs = (Set<String>)cache.get(lc);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (setDNs == null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster setDNs = new HashSet<String>();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster cache.put(lc, setDNs);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster setDNs.add(dn);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String cacheName = cache.getName();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (!CacheTaboo.isTaboo(cacheName, lc)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (setDNs.size() >= CACHE_BUCKET_LIMIT) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster CacheTaboo.taboo(cacheName, lc);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster cache.remove(lc);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster setDNs.add(dn);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } finally {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rwlock.writeLock().unlock();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Clear index cache.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param indexes Resource cache indexes.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param dn Distinguished name of the privilege.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public void clear(ResourceSaveIndexes indexes, String dn) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (indexes != null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster clear(dn, indexes.getHostIndexes(), hostIndexCache);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster clear(dn, indexes.getPathIndexes(), pathIndexCache);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster clear(dn, indexes.getParentPathIndexes(), parentPathIndexCache);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private void clear(String dn, Set<String> indexes, Cache cache) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rwlock.writeLock().lock();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster try {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for (String s : indexes) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Set<String> setDNs = (Set<String>)cache.get(s);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (setDNs != null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster setDNs.remove(dn);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } finally {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rwlock.writeLock().unlock();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private synchronized void clearCaches() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rwlock.writeLock().lock();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster try {
9f5c397b0f840513ad40c4ee50b260a013438b67Andrew Forrest subjectIndexCache = new Cache(SUBJECT_ID, initCapacity, size);
9f5c397b0f840513ad40c4ee50b260a013438b67Andrew Forrest hostIndexCache = new Cache(HOST_ID, initCapacity, size);
9f5c397b0f840513ad40c4ee50b260a013438b67Andrew Forrest pathIndexCache = new Cache(PATH_ID, initCapacity, size);
9f5c397b0f840513ad40c4ee50b260a013438b67Andrew Forrest parentPathIndexCache = new Cache(PARENTPATH_ID, initCapacity, size);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } finally {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rwlock.writeLock().unlock();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Returns a set of DN that matches the resource and subject indexes.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param indexes Resource search indexes.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param subjectIndexes Subject search indexes
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param bSubTree <code>true</code> for sub tree search mode.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return A set of DN that matches the resource and subject indexes.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public Set<String> getMatchingEntries(
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ResourceSearchIndexes indexes,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Set<String> subjectIndexes,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster boolean bSubTree
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rwlock.readLock().lock();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster try {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Set<String> results = new HashSet<String>();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster boolean hasSubjectIndexes = (subjectIndexes != null) &&
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster !subjectIndexes.isEmpty();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (hasSubjectIndexes) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for (String i : subjectIndexes) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Set<String> r = (Set<String>)subjectIndexCache.get(i);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (r != null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster results.addAll(r);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster results.retainAll(getHostIndexes(indexes));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster results.addAll(getHostIndexes(indexes));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (bSubTree) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster results.retainAll(getPathParentIndexes(indexes));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster results.retainAll(getPathIndexes(indexes));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return results;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } finally {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rwlock.readLock().unlock();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private Set<String> getPathParentIndexes(ResourceSearchIndexes indexes) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Set<String> parentPathIndexes = indexes.getParentPathIndexes();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Set<String> results = new HashSet<String>();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for (String i : parentPathIndexes) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Set<String> r = (Set<String>) parentPathIndexCache.get(
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster i.toLowerCase());
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (r != null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster results.addAll(r);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return results;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private Set<String> getPathIndexes(ResourceSearchIndexes indexes) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Set<String> pathIndexes = indexes.getPathIndexes();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Set<String> results = new HashSet<String>();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for (String i : pathIndexes) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Set<String> r = (Set<String>) pathIndexCache.get(i.toLowerCase());
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (r != null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster results.addAll(r);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }return results;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private Set<String> getHostIndexes(ResourceSearchIndexes indexes) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Set<String> results = new HashSet<String>();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Set<String> hostIndexes = indexes.getHostIndexes();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for (String i : hostIndexes) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Set<String> r = (Set<String>) hostIndexCache.get(i.toLowerCase());
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (r != null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster results.addAll(r);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return results;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}