IdRepoPluginsCache.java revision a7587037ca2237ee8a201dd776998171e8cfc00a
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/*
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster *
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster *
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * The contents of this file are subject to the terms
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * of the Common Development and Distribution License
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * (the License). You may not use this file except in
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * compliance with the License.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster *
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * You can obtain a copy of the License at
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * https://opensso.dev.java.net/public/CDDLv1.0.html or
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * opensso/legal/CDDLv1.0.txt
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * See the License for the specific language governing
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * permission and limitations under the License.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster *
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * When distributing Covered Code, include this CDDL
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Header Notice in each file and include the License file
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * at opensso/legal/CDDLv1.0.txt.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * If applicable, add the following below the CDDL Header,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * with the fields enclosed by brackets [] replaced by
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * your own identifying information:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * "Portions Copyrighted [year] [name of copyright owner]"
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster *
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * $Id: IdRepoPluginsCache.java,v 1.8 2009/11/10 01:52:37 hengming Exp $
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster *
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Portions Copyrighted 2015-2016 ForgeRock AS.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterpackage com.sun.identity.idm.server;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport java.security.AccessController;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport java.util.HashMap;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport java.util.HashSet;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport java.util.Hashtable;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport java.util.Iterator;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport java.util.LinkedHashMap;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport java.util.Map;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport java.util.Set;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport java.util.StringTokenizer;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport java.util.concurrent.ScheduledExecutorService;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport java.util.concurrent.TimeUnit;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport org.forgerock.guice.core.InjectorHolder;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport org.forgerock.util.thread.ExecutorServiceFactory;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.iplanet.am.util.SystemProperties;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.iplanet.sso.SSOException;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.iplanet.sso.SSOToken;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.common.DNUtils;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.idm.IdConstants;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.idm.IdOperation;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.idm.IdRepo;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.idm.IdRepoBundle;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.idm.IdRepoErrorCode;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.idm.IdRepoException;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.idm.IdRepoListener;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.idm.IdType;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.security.AdminTokenAction;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.shared.Constants;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.shared.datastruct.OrderedSet;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.shared.debug.Debug;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.sm.DNMapper;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.sm.SMSException;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.sm.SMSThreadPool;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.sm.ServiceConfig;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.sm.ServiceConfigManager;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.sm.ServiceListener;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.sm.ServiceManager;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.sm.ServiceSchemaManager;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/**
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster *
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @author aravind
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterpublic class IdRepoPluginsCache implements ServiceListener {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster static Debug debug = Debug.getInstance("amIdm");
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster static boolean initializedListeners;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster static ServiceConfigManager idRepoServiceConfigManager;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster private static int svcRevisionNumber;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // Cache of IdRepo Plugins
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // The Map contains <orgName, MAP<name, IdRepo object>>
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster private Map idrepoPlugins = new HashMap();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // Needs to synchronized for get(), put() and clear()
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster private Map readonlyPlugins = new Hashtable();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster private final ScheduledExecutorService scheduler;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster protected IdRepoPluginsCache() {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // Initialize listeners
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (debug.messageEnabled()) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster debug.message("IdRepoPluginsCache constructor called");
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster this.scheduler = InjectorHolder.getInstance(ExecutorServiceFactory.class).createScheduledService(1);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster initializeListeners();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster @SuppressWarnings("unchecked")
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster protected Set<IdRepo> getIdRepoPlugins(String orgName)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster throws IdRepoException, SSOException {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (debug.messageEnabled()) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster debug.message("IdRepoPluginsCache.getIdRepoPlugins orgName: " +
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster orgName);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // Check the cache
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster Map orgRepos = null;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster orgName = DNUtils.normalizeDN(orgName);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster Set readOrgRepos = (Set) readonlyPlugins.get(orgName);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if ((readOrgRepos != null) && !readOrgRepos.isEmpty()) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return (readOrgRepos);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster synchronized (idrepoPlugins) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster orgRepos = (Map) idrepoPlugins.get(orgName);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (orgRepos == null) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster try {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (debug.messageEnabled()) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster debug.message("IdRepoPluginsCache.getIdRepoPlugins " +
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster "Not in cache for: " + orgName);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // Initialize the plugins
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster orgRepos = new LinkedHashMap();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster ServiceConfig sc = idRepoServiceConfigManager
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster .getOrganizationConfig(orgName, null);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (sc == null) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // Organization does not exist. Error condition
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster debug.error("IdRepoPluginsCache.getIdRepoPlugins " +
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster "Org does not exisit: " + orgName);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster Object[] args = { orgName };
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster throw new IdRepoException(
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster IdRepoBundle.BUNDLE_NAME, IdRepoErrorCode.REALM_DOESNT_EXIST, args);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster Set subConfigNames = sc.getSubConfigNames();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (debug.messageEnabled()) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster debug.message("IdRepoPluginsCache.getIdRepoPlugins " +
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster "Loading plugins: " + subConfigNames);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (subConfigNames != null && !subConfigNames.isEmpty()) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster for (Iterator items = subConfigNames.iterator();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster items.hasNext();) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster String idRepoName = (String) items.next();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster ServiceConfig reposc = sc.getSubConfig(idRepoName);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (reposc == null) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster debug.error("IdRepoPluginsCache." +
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster "getIdRepoPlugins SubConfig is null for" +
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster " orgName: " + orgName +
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster " subConfig Name: " + idRepoName);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster IdRepo repo = constructIdRepoPlugin(orgName,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster reposc.getAttributesForRead(), idRepoName);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // Add to cache
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster orgRepos.put(idRepoName, repo);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // Add internal repos
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster addInternalRepo(orgRepos, orgName);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster idrepoPlugins.put(orgName, orgRepos);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster } catch (SMSException ex) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster debug.error("IdRepoPluginsCache.getIdRepoPlugins " +
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster "SMS Exception for orgName: " + orgName, ex);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // Cache a readonly copy
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (orgRepos != null) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster readOrgRepos = new OrderedSet();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster readOrgRepos.addAll(orgRepos.values());
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster readonlyPlugins.put(orgName, readOrgRepos);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (debug.messageEnabled() && (readOrgRepos != null)) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster Set ps = new HashSet();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster for (Iterator items = readOrgRepos.iterator(); items.hasNext();) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster ps.add(items.next().getClass().getName());
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster debug.message("IdRepoPluginsCache.getIdRepoPlugins retuned for" +
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster " OrgName: " + orgName + " Plugins: " + ps);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return (readOrgRepos);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster @SuppressWarnings("unchecked")
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster protected Set<IdRepo> getIdRepoPlugins(String orgName, IdOperation op,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster IdType type) throws IdRepoException, SSOException {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (debug.messageEnabled()) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster debug.message("IdRepoPluginsCache.getIdRepoPlugins for " +
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster "OrgName: " + orgName + " Op: " + op + " Type: " + type);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster String cacheName = DNUtils.normalizeDN(orgName) + op.toString() +
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster type.toString();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster Set answer = (Set) readonlyPlugins.get(cacheName);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if ((answer != null) && !answer.isEmpty()) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return (answer);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster answer = new OrderedSet();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster Set plugins = getIdRepoPlugins(orgName);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if ((plugins != null) && !plugins.isEmpty()) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster for (Iterator items = plugins.iterator(); items.hasNext();) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster IdRepo repo = (IdRepo) items.next();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (repo.getSupportedTypes().contains(type)) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster Set ops = repo.getSupportedOperations(type);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (ops.contains(op)) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster answer.add(repo);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (debug.messageEnabled()) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster Set ps = new HashSet();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster for (Iterator items = answer.iterator(); items.hasNext();) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster IdRepo repo = (IdRepo) items.next();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster ps.add(repo.getClass().getName());
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster debug.message("IdRepoPluginsCache.getIdRepoPlugins retuned for" +
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster " OrgName: " + orgName + " Op: " + op + " Type: " + type +
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster " Plugins: " + ps);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster synchronized (idrepoPlugins) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (answer != null) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster readonlyPlugins.put(cacheName, answer);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return (answer);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /**
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Delete an IdRepo plugin
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster private void removeIdRepo(String orgName, String name,
boolean reinitialize) throws IdRepoException, SSOException {
orgName = DNUtils.normalizeDN(orgName);
synchronized (idrepoPlugins) {
// Clear IdRepo plugins first since other threads should
// not access it during shutdown
clearReadOnlyPlugins(orgName);
Map idrepos = (Map) idrepoPlugins.get(orgName);
if (idrepos != null && !idrepos.isEmpty()) {
// Iterate through the plugins
for (Iterator items = idrepos.keySet().iterator();
items.hasNext();) {
String iname = items.next().toString();
if (iname.equalsIgnoreCase(name)) {
IdRepo repo = (IdRepo) idrepos.get(iname);
// Shutting down idrepo
if (debug.messageEnabled()) {
debug.message("IdRepoPluginsCache.removeIdRepo" +
" for OrgName: " + orgName + " Repo Name: " +
name);
}
// Remove from cache first
idrepos.remove(iname);
ShutdownIdRepoPlugin shutdownrepo =
new ShutdownIdRepoPlugin(repo);
// Provide a delay of 500ms for existing operations
// to complete. the delay is in the forked thread.
SMSThreadPool.scheduleTask(shutdownrepo);
break;
}
}
if (reinitialize) {
// Adding plugin back provides the atomic operation
// for the caller. Else, client will get No-plugins
// configured exception.
// Add the plugin back to the cache
addIdRepo(orgName, name);
}
}
}
}
private void clearReadOnlyPlugins(String orgName) {
// clear a readonly copy for the org Name
for (Iterator items = readonlyPlugins.keySet().iterator();
items.hasNext();) {
String name = items.next().toString();
if (name.startsWith(orgName)) {
items.remove();
}
}
}
/**
* Delete all IdRepo plugin for the organization
*/
private void removeIdRepo(String orgName) {
orgName = DNUtils.normalizeDN(orgName);
Map idrepos = null;
synchronized (idrepoPlugins) {
// Clear IdRepo plugins first
clearReadOnlyPlugins(orgName);
idrepos = (Map) idrepoPlugins.remove(orgName);
}
if (debug.messageEnabled()) {
debug.message("IdRepoPluginsCache.removeIdRepo for " +
"OrgName: " + orgName + " Repo Names: " + idrepos.keySet());
}
ShutdownIdRepoPlugin shutdownrepos = new ShutdownIdRepoPlugin(idrepos);
// Provide a delay of 500ms for existing operations
// to complete. the delay is in the forked thread.
scheduler.schedule(shutdownrepos, 500, TimeUnit.MILLISECONDS);
}
/**
* Clears the IdRepo plugin cache
*/
public void clearIdRepoPluginsCache() {
Map cache = null;
synchronized (idrepoPlugins) {
// Clear readonly cache first.
// Don't want other theads to get plugins that are
// shutdown.
readonlyPlugins.clear();
cache = new HashMap(idrepoPlugins);
idrepoPlugins.clear();
readonlyPlugins.clear();
}
// Iterate throught the orgName and shutdown the repos
for (Iterator onames = cache.keySet().iterator(); onames.hasNext();) {
Map repos = (Map) cache.get(onames.next());
for (Iterator items = repos.keySet().iterator(); items.hasNext();) {
String name = items.next().toString();
IdRepo repo = (IdRepo) repos.get(name);
repo.removeListener();
repo.shutdown();
}
}
}
/**
* Adds an IdRepo plugin to an organization given the configuration
* @param orgName organization to which IdRepo would be added
* @param name id repo name
*/
private void addIdRepo(String orgName, String name)
throws IdRepoException, SSOException {
if (debug.messageEnabled()) {
debug.message("IdRepoPluginsCache.addIdRepo called for orgName: " +
orgName + " IdRepo Name: " + name);
}
Map configMap = null;
try {
ServiceConfig sc = idRepoServiceConfigManager
.getOrganizationConfig(orgName, null);
if (sc == null) {
debug.error("IdRepoPluginsCache.addIdRepo orgName: " +
orgName + " does not exisit");
Object[] args = {orgName};
throw new IdRepoException(
IdRepoBundle.BUNDLE_NAME, IdRepoErrorCode.REALM_DOESNT_EXIST, args);
}
sc = sc.getSubConfig(name);
if (sc == null) {
debug.error("IdRepoPluginsCache.addIdRepo orgName: " +
orgName + " subConfig does not exisit: " + name);
Object[] args = {orgName + ":" + name};
throw new IdRepoException(
IdRepoBundle.BUNDLE_NAME, IdRepoErrorCode.REALM_DOESNT_EXIST, args);
}
configMap = sc.getAttributes();
} catch (SMSException smse) {
if (debug.warningEnabled()) {
debug.warning("IdRepoPluginsCache.addIdRepo SMSException " +
"for orgName: " + orgName + " sc name: " + name, smse);
}
return;
}
IdRepo repo = constructIdRepoPlugin(orgName, configMap, name);
// Add to cache
orgName = DNUtils.normalizeDN(orgName);
synchronized (idrepoPlugins) {
// Clear the readonly plugins first.
// Other threads have to wait for the initialization to complete
// Will get updated when getPlugins gets called
clearReadOnlyPlugins(orgName);
Map repos = (Map) idrepoPlugins.get(orgName);
boolean addInternalRepos = false;
if (repos == null) {
repos = new LinkedHashMap();
idrepoPlugins.put(orgName, repos);
addInternalRepos = true;
}
repos.put(name, repo);
if (addInternalRepos) {
addInternalRepo(repos, orgName);
}
}
}
private void addInternalRepo(Map orgRepos, String orgName)
throws SSOException, IdRepoException {
// Check if AMSDK plugin needs to be added
if (ServiceManager.isCoexistenceMode()) {
orgRepos.put(IdConstants.AMSDK_PLUGIN_NAME,
getAMRepoPlugin(orgName));
}
// Check if AgentsRepos needs to be added
if (svcRevisionNumber >= 30) {
orgRepos.put(IdConstants.AGENTREPO_PLUGIN,
getAgentRepoPlugin(orgName));
}
// Check if SpecialRepo needs to be added
if (ServiceManager.isConfigMigratedTo70() &&
ServiceManager.getBaseDN().equalsIgnoreCase(orgName)) {
orgRepos.put(IdConstants.SPECIAL_PLUGIN,
getSpecialRepoPlugin());
}
}
protected void initializeListeners() {
synchronized (debug) {
if (!initializedListeners) {
// Add listeners to Service Schema and Config Managers
if (debug.messageEnabled()) {
debug.message("IdRepoPluginsCache.initializeListeners: " +
"setting up ServiceListener");
}
SSOToken token = getAdminToken();
try {
// Initialize configuration objects
idRepoServiceConfigManager = new ServiceConfigManager(token,
IdConstants.REPO_SERVICE, "1.0");
idRepoServiceConfigManager.addListener(this);
// Initialize schema objects
ServiceSchemaManager idRepoServiceSchemaManager =
new ServiceSchemaManager(token,
IdConstants.REPO_SERVICE, "1.0");
idRepoServiceSchemaManager.addListener(this);
// Get the version number
svcRevisionNumber = idRepoServiceSchemaManager
.getRevisionNumber();
// Initialize listener for JAXRPCObject
IdRepoListener.addRemoteListener(
new JAXRPCObjectImplEventListener());
initializedListeners = true;
} catch (SMSException smse) {
// Exceptions will be throws during install and config
// when these services will not be loaded
String installTime = SystemProperties.get(
Constants.SYS_PROPERTY_INSTALL_TIME, "false");
if (!installTime.equals("true")) {
debug.error("IdRepoPluginsCache.initializeListeners: " +
"Unable to set up a service listener for IdRepo",
smse);
}
} catch (SSOException ssoe) {
debug.error("IdRepoPluginsCache.initializeListeners: " +
"Unable to set up a service listener for IdRepo.",
ssoe);
}
}
}
}
/**
* Constructs IdRepo plugin object and returns.
*/
private IdRepo constructIdRepoPlugin(String orgName, Map configMap,
String name) throws IdRepoException, SSOException {
IdRepo answer = null;
if (debug.messageEnabled()) {
debug.message("IdRepoPluginsCache.constructIdRepoPlugin: config=" +
configMap.get("sunIdRepoClass"));
}
if (configMap == null || configMap.isEmpty()) {
if (debug.warningEnabled()) {
debug.warning("IdRepoPluginsCache.constructIdRepoPlugin: " +
"Cannot construct with empty config data");
}
return (null);
}
Set vals = (Set) configMap.get(IdConstants.ID_REPO);
if ((vals != null) && !vals.isEmpty()) {
String className = (String) vals.iterator().next();
Class thisClass;
try {
thisClass = Thread.currentThread().getContextClassLoader()
.loadClass(className);
answer = (IdRepo) thisClass.newInstance();
} catch (Throwable ex) {
debug.error("IdRepoPluginsCached.constructIdRepoPlugin " +
" OrgName: " + orgName + " ConfigMap: " + configMap, ex);
throw (new IdRepoException(ex.getMessage()));
}
answer.initialize(configMap);
// Add listener to this plugin class!
Map listenerConfig = new HashMap();
listenerConfig.put("realm", orgName);
listenerConfig.put("plugin-name", name);
if (className.equals(
IdConstants.AMSDK_PLUGIN)) {
listenerConfig.put("amsdk", "true");
}
IdRepoListener listener = new IdRepoListener();
listener.setConfigMap(listenerConfig);
answer.addListener(getAdminToken(), listener);
}
return (answer);
}
private static SSOToken getAdminToken() {
return ((SSOToken) AccessController.doPrivileged(
AdminTokenAction.getInstance()));
}
// Internal repos
private IdRepo getSpecialRepoPlugin()
throws SSOException, IdRepoException {
// Valid only for root realm
IdRepo pluginClass = null;
try {
if (debug.messageEnabled()) {
debug.message("Special repo being initialized");
}
Class thisClass = Thread.currentThread().
getContextClassLoader().loadClass(IdConstants.SPECIAL_PLUGIN);
pluginClass = (IdRepo) thisClass.newInstance();
HashMap config = new HashMap(2);
config.put("realm", ServiceManager.getBaseDN());
pluginClass.initialize(config);
IdRepoListener lter = new IdRepoListener();
lter.setConfigMap(config);
pluginClass.addListener(getAdminToken(), lter);
} catch (Exception e) {
debug.error("IdRepoPluginsCache.getSpecialRepoPlugin: " +
"Unable to init plugin: " + IdConstants.SPECIAL_PLUGIN, e);
}
return pluginClass;
}
protected IdRepo getAgentRepoPlugin(String orgName)
throws SSOException, IdRepoException {
IdRepo pluginClass = null;
try {
if (debug.messageEnabled()) {
debug.message("Agents repo being initialized");
}
Class thisClass = Thread.currentThread().
getContextClassLoader().loadClass(IdConstants.AGENTREPO_PLUGIN);
pluginClass = (IdRepo) thisClass.newInstance();
HashMap config = new HashMap(2);
HashSet realmName = new HashSet();
realmName.add(orgName);
config.put("agentsRepoRealmName", realmName);
pluginClass.initialize(config);
} catch (Exception e) {
debug.error("IdRepoPluginsCache.getAgentRepoPlugin: " +
"Unable to init plugin: " + IdConstants.AGENTREPO_PLUGIN, e);
}
// Add listener
if (pluginClass != null) {
Map listenerConfig = new HashMap();
listenerConfig.put("realm", orgName);
IdRepoListener lter = new IdRepoListener();
lter.setConfigMap(listenerConfig);
pluginClass.addListener(getAdminToken(), lter);
}
// Retuns the plugin class
return pluginClass;
}
protected IdRepo getAMRepoPlugin(String orgName)
throws SSOException, IdRepoException {
IdRepo pluginClass = null;
try {
if (debug.messageEnabled()) {
debug.message("AMSDK repo being initialized");
}
Class thisClass = Thread.currentThread().
getContextClassLoader().loadClass(IdConstants.AMSDK_PLUGIN);
pluginClass = (IdRepo) thisClass.newInstance();
Map amsdkConfig = new HashMap();
Set vals = new HashSet();
vals.add(DNMapper.realmNameToAMSDKName(orgName));
amsdkConfig.put("amSDKOrgName", vals);
pluginClass.initialize(amsdkConfig);
} catch (Exception e) {
debug.error("IdRepoPluginsCache.getAMRepoPlugin: " +
"Unable to instantiate plugin for Org: " + orgName, e);
}
if (pluginClass != null) {
// Add listener to this plugin class
Map listenerConfig = new HashMap();
listenerConfig.put("realm", orgName);
listenerConfig.put("amsdk", "true");
IdRepoListener lter = new IdRepoListener();
lter.setConfigMap(listenerConfig);
pluginClass.addListener(getAdminToken(), lter);
}
return pluginClass;
}
/**
* Notification for global config changes to IdRepoService
*/
public void globalConfigChanged(String serviceName, String version,
String groupName, String serviceComponent, int type) {
if (debug.messageEnabled()) {
debug.message("IdRepoPluginsCache: Global Config changed called " +
"ServiceName: " + serviceName + " groupName: " + groupName +
" serviceComp: " + serviceComponent + " Type: " + type);
}
if (serviceComponent.equals("") || serviceComponent.equals("/")) {
return;
}
// FIXME: Clients don't have to call this !!
if (!serviceComponent.startsWith("/users/") &&
!serviceComponent.startsWith("/roles/")) {
if (type != 1) {
clearIdRepoPluginsCache();
}
} else {
// Special identities have changed, clear the cache
((IdServicesImpl) IdServicesImpl.getInstance())
.clearSpecialIdentityCache();
}
}
/**
* Notification for organization config changes to IdRepoService
*/
public void organizationConfigChanged(String serviceName, String version,
String orgName, String groupName, String serviceComponent, int type)
{
if (debug.messageEnabled()) {
debug.message("IdRepoPluginsCache: Org Config changed called " +
"ServiceName: " + serviceName + " orgName: " + orgName +
" groupName: " + groupName + " serviceComp: " +
serviceComponent + " Type: " + type);
}
// ignore componenet is "".
// if component is /" and type is 2(delete), need to remove hidden
// plugins.
if ((type == ServiceListener.REMOVED) &&
(serviceComponent.length() == 0)) {
// Organization has been deleted
removeIdRepo(orgName);
} else if ((serviceComponent.length() != 0) &&
!serviceComponent.equals("/") && !serviceComponent.equals("")) {
// IdRepo has been either added, removed or modified
String idRepoName = null;
StringTokenizer st = new StringTokenizer(serviceComponent, "/");
if (st.hasMoreTokens()) {
idRepoName = st.nextToken();
}
try {
if (type == ServiceListener.ADDED) {
addIdRepo(orgName, idRepoName);
} else if (type == ServiceListener.MODIFIED) {
if (!IdServicesImpl.isShutdownCalled()) {
// Reinitialize the plugin after shutdown
removeIdRepo(orgName, idRepoName, true);
} else {
removeIdRepo(orgName, idRepoName, false);
}
} else if (type == ServiceListener.REMOVED) {
removeIdRepo(orgName, idRepoName, false);
}
} catch (Exception e) {
debug.error("IdRepoPluginsCached.organizationConfigChanged " +
"ServiceName: " + serviceName + " orgName: " + orgName +
" groupName: " + groupName + " serviceComp: " +
serviceComponent + " Type: " + type, e);
}
}
}
/**
* Notification for schema changes to IdRepoService
*/
public void schemaChanged(String serviceName, String version) {
if (debug.messageEnabled()) {
debug.message("IdRepoPluginsCache: Schema changed called" +
" Service name: " + serviceName);
}
clearIdRepoPluginsCache();
}
// Timer task to shutdown IdRepo plugins
private class ShutdownIdRepoPlugin implements Runnable {
IdRepo plugin;
Map idrepos;
public ShutdownIdRepoPlugin(IdRepo plugin) {
this.plugin = plugin;
}
public ShutdownIdRepoPlugin(Map idrepos) {
this.idrepos = idrepos;
}
public void run() {
// Shutdown the repo
if (plugin != null) {
plugin.removeListener();
plugin.shutdown();
plugin = null;
}
if (idrepos != null && !idrepos.isEmpty()) {
// Iterate through the plugins
for (Iterator items = idrepos.keySet().iterator();
items.hasNext();) {
String name = items.next().toString();
IdRepo repo = (IdRepo) idrepos.get(name);
// Shutting down idrepo
repo.removeListener();
repo.shutdown();
}
idrepos = null;
}
}
}
}