/* * JBoss, Home of Professional Open Source * Copyright 2005, JBoss Inc., and individual contributors as indicated * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.security.auth.message.config; import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.security.auth.message.config.AuthConfigFactory; import javax.security.auth.message.config.AuthConfigProvider; import javax.security.auth.message.config.RegistrationListener; import org.jboss.security.PicketBoxMessages; //$Id$ /** * Default Authentication Configuration Factory * * @author <a href="mailto:Anil.Saldhana@jboss.org">Anil Saldhana</a> * @since May 15, 2006 * @version $Revision$ */ public class JBossAuthConfigFactory extends AuthConfigFactory { /** * Map of String key to provider. */ private Map<String, AuthConfigProvider> keyToAuthConfigProviderMap = new HashMap<String, AuthConfigProvider>(); /** * Map of key to listener. */ private Map<String, RegistrationListener> keyToRegistrationListenerMap = new HashMap<String, RegistrationListener>(); /** * Map of key to registration context. */ private Map<String, RegistrationContext> keyToRegistrationContextMap = new HashMap<String, RegistrationContext>(); /** * <p> * Creates an instance of {@code JBossAuthConfigFactory}. * </p> */ public JBossAuthConfigFactory() { Map<String, Object> props = new HashMap<String, Object>(); JBossAuthConfigProvider provider = new JBossAuthConfigProvider(props, null); // register a few default providers for the layers this.registerConfigProvider(provider, "HTTP", null, "Default Provider"); this.registerConfigProvider(provider, "HttpServlet", null, "Default Provider"); } /* * (non-Javadoc) * @see javax.security.auth.message.config.AuthConfigFactory#detachListener(javax.security.auth.message.config.RegistrationListener, java.lang.String, java.lang.String) */ public String[] detachListener(RegistrationListener listener, String layer, String appContext) { if (listener == null) throw PicketBoxMessages.MESSAGES.invalidNullArgument("listener"); String[] arr = new String[0]; String input = layer + appContext; String allLayer = "null" + appContext; String allContext = layer + "null"; String general = "nullnull"; RegistrationListener origListener = null; String key = null; for (int i = 0; i < 4 && origListener == null; i++) { if (i == 0) key = input; if (i == 1) key = allLayer; if (i == 2) key = allContext; if (i == 3) key = general; origListener = keyToRegistrationListenerMap.get(key); } if (origListener == listener) { keyToRegistrationListenerMap.remove(key); // Get the ID List } return arr; } /* * (non-Javadoc) * @see javax.security.auth.message.config.AuthConfigFactory#getConfigProvider(java.lang.String, java.lang.String, javax.security.auth.message.config.RegistrationListener) */ public AuthConfigProvider getConfigProvider(String layer, String appContext, RegistrationListener listener) { String input = new StringBuilder().append(layer).append(appContext).toString(); String allLayer = "null" + appContext; String allContext = layer + "null"; String general = "nullnull"; AuthConfigProvider acp = null; String key = null; for (int i = 0; i < 4; i++) { if (i == 0) key = input; if (i == 1) key = allLayer; if (i == 2) key = allContext; if (i == 3) key = general; if (this.keyToAuthConfigProviderMap.containsKey(key)) { acp = this.keyToAuthConfigProviderMap.get(key); break; } } // if (listener != null) this.keyToRegistrationListenerMap.put(input, listener); return acp; } /* * (non-Javadoc) * @see javax.security.auth.message.config.AuthConfigFactory#getRegistrationContext(java.lang.String) */ public RegistrationContext getRegistrationContext(String registrationID) { return this.keyToRegistrationContextMap.get(registrationID); } /* * (non-Javadoc) * @see javax.security.auth.message.config.AuthConfigFactory#getRegistrationIDs(javax.security.auth.message.config.AuthConfigProvider) */ public String[] getRegistrationIDs(AuthConfigProvider provider) { List<String> al = new ArrayList<String>(); if (provider == null) { al.addAll(keyToAuthConfigProviderMap.keySet()); } else { // get all entries that have the supplied provider as value and store their keys. for (Map.Entry<String, AuthConfigProvider> entry : this.keyToAuthConfigProviderMap.entrySet()) { if (entry.getValue().equals(provider)) al.add(entry.getKey()); } } String[] sarr = new String[al.size()]; al.toArray(sarr); return sarr; } /* * (non-Javadoc) * @see javax.security.auth.message.config.AuthConfigFactory#refresh() */ public void refresh() { } /* * (non-Javadoc) * @see javax.security.auth.message.config.AuthConfigFactory#registerConfigProvider(java.lang.String, java.util.Map, java.lang.String, java.lang.String, java.lang.String) */ public String registerConfigProvider(String className, Map properties, String layer, String appContext, String description) { // Instantiate the provider AuthConfigProvider acp = null; if (className != null) { try { // An AuthConfigProvider must have a two-argument constructor (Map properties, AuthConfigFactory factory). Class<?> provClass = SecurityActions.getContextClassLoader().loadClass(className); Constructor<?> ctr = provClass.getConstructor(new Class[] {Map.class, AuthConfigFactory.class}); acp = (AuthConfigProvider) ctr.newInstance(new Object[] {properties, null}); } catch (Exception e) { throw PicketBoxMessages.MESSAGES.failedToRegisterAuthConfigProvider(className, e); } } // build the provider registration id using layer + appContext, which is a unique pair. String registrationID = new StringBuilder().append(layer).append(appContext).toString(); // check if we already have a registration for the layer/appContext key. AuthConfigProvider oldProvider = this.keyToAuthConfigProviderMap.put(registrationID, acp); if (oldProvider != null) { // registration already exists and provider has been replaced. Update the registration context. JBossRegistrationContext context = (JBossRegistrationContext) this.keyToRegistrationContextMap.get(registrationID); context.setDescription(description); context.setIsPersistent(true); // if there is a listener attached to the registration, notify it that the registration has been replaced. RegistrationListener listener = this.keyToRegistrationListenerMap.get(registrationID); if (listener != null) listener.notify(layer, appContext); } else { // create a registration context for the new registration. RegistrationContext context = new JBossRegistrationContext(layer, appContext, description, true); this.keyToRegistrationContextMap.put(registrationID, context); } return registrationID; } /* * (non-Javadoc) * @see javax.security.auth.message.config.AuthConfigFactory#registerConfigProvider(javax.security.auth.message.config.AuthConfigProvider, java.lang.String, java.lang.String, java.lang.String) */ public String registerConfigProvider(AuthConfigProvider provider, String layer, String appContext, String description) { String registrationID = new StringBuilder().append(layer).append(appContext).toString(); // check if we already have a registration for the layer/appContext key. AuthConfigProvider oldProvider = this.keyToAuthConfigProviderMap.put(registrationID, provider); if (oldProvider != null) { // registration already exists and provider has been replaced. Update the registration context. JBossRegistrationContext context = (JBossRegistrationContext) this.keyToRegistrationContextMap.get(registrationID); context.setDescription(description); context.setIsPersistent(false); // if there is a listener attached to the registration, notify it that the registration has been replaced. RegistrationListener listener = this.keyToRegistrationListenerMap.get(registrationID); if (listener != null) listener.notify(layer, appContext); } else { // create a registration context for the new registration. RegistrationContext context = new JBossRegistrationContext(layer, appContext, description, false); this.keyToRegistrationContextMap.put(registrationID, context); } return registrationID; } /* * (non-Javadoc) * @see javax.security.auth.message.config.AuthConfigFactory#removeRegistration(java.lang.String) */ public boolean removeRegistration(String registrationID) { if (registrationID == null) throw PicketBoxMessages.MESSAGES.invalidNullArgument("registrationID"); RegistrationListener listener = this.keyToRegistrationListenerMap.get(registrationID); RegistrationContext rc = this.keyToRegistrationContextMap.get(registrationID); // remove the provider and notify listener of the change. boolean removed = this.keyToAuthConfigProviderMap.containsKey(registrationID); this.keyToAuthConfigProviderMap.remove(registrationID); if (removed && listener != null) listener.notify(rc.getMessageLayer(), rc.getAppContext()); this.keyToRegistrationContextMap.remove(registrationID); return removed; } static class JBossRegistrationContext implements RegistrationContext { private String messageLayer; private String appContext; private String description; private boolean isPersistent; JBossRegistrationContext(String layer, String appContext, String description, boolean isPersistent) { this.messageLayer = layer; this.appContext = appContext; this.description = description; this.isPersistent = isPersistent; } public String getAppContext() { return this.appContext; } public void setAppContext(String appContext) { this.appContext = appContext; } public String getDescription() { return this.description; } public void setDescription(String description) { this.description = description; } public String getMessageLayer() { return this.messageLayer; } public void setMessageLayer(String messageLayer) { this.messageLayer = messageLayer; } public boolean isPersistent() { return this.isPersistent; } public void setIsPersistent(boolean isPersistent) { this.isPersistent = isPersistent; } } }