/* * Copyright 2007-2010 Sun Microsystems, Inc. * * This file is part of Project Darkstar Server. * * Project Darkstar Server is free software: you can redistribute it * and/or modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation and * distributed hereunder to you. * * Project Darkstar Server 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * -- */ package com.sun.sgs.impl.kernel; import com.sun.sgs.auth.Identity; import com.sun.sgs.auth.IdentityAuthenticator; import com.sun.sgs.auth.IdentityCoordinator; import com.sun.sgs.auth.IdentityCredentials; import com.sun.sgs.impl.sharedutil.LoggerWrapper; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.security.auth.login.CredentialException; import javax.security.auth.login.LoginException; /** * This package-private implementation of <code>IdentityCoordinator</code> is * the implementation used by the system when configuring an application. It * manages an ordered collection of <code>IdentityAuthenticator</code>s. The * ordering is used to determine precidence when more than one authenticator * can consume the same credentials. * <p> * This implementation is kept private to this package so that the context * can be assigned, safely, after the coordinator is created. An instance of the * coordinator is needed before the context can be created. */ class IdentityCoordinatorImpl implements IdentityCoordinator { // logger for this class private static final LoggerWrapper logger = new LoggerWrapper(Logger.getLogger(IdentityCoordinatorImpl. class.getName())); // the available authenticators private final HashMap<String, List<IdentityAuthenticator>> authenticatorMap; // a unique collection of the authenticators, for management purposes, // and currently unused private final HashSet<IdentityAuthenticator> authenticatorSet; /** * Creates an instance of <code>IdentityCoordinatorImpl</code> that has * the given <code>IdentityAuthenticators</code> available to authenticate * identities. The order of the authenticators determines precidence * when more than one authenticator supports a given credentials type. * * @param authenticators the available <code>IdentityAuthenticator</code>s */ public IdentityCoordinatorImpl(List<IdentityAuthenticator> authenticators) { if (authenticators == null) { throw new NullPointerException("Authenticators must not be null"); } // add the authenticators in the right order authenticatorMap = new HashMap<String, List<IdentityAuthenticator>>(); for (IdentityAuthenticator authenticator : authenticators) { String [] identifiers = authenticator.getSupportedCredentialTypes(); for (String identifier : identifiers) { List<IdentityAuthenticator> list = authenticatorMap.get(identifier); if (list == null) { list = new ArrayList<IdentityAuthenticator>(); authenticatorMap.put(identifier, list); } list.add(authenticator); } } // keep track of the collection authenticatorSet = new HashSet<IdentityAuthenticator>(authenticators); } /** * {@inheritDoc} * * @throws CredentialException if the authenticator for the credentials * is unknown */ public Identity authenticateIdentity(IdentityCredentials credentials) throws LoginException { if (credentials == null) { throw new NullPointerException("Credentials must not be null"); } List<IdentityAuthenticator> authenticators = authenticatorMap.get(credentials.getCredentialsType()); if (authenticators == null) { throw new CredentialException("Unsupported credentials type: " + credentials.getCredentialsType()); } for (IdentityAuthenticator authenticator : authenticators) { try { return authenticator.authenticateIdentity(credentials); } catch (LoginException le) { // NOTE: because there could be multiple authenticators, it's // not possible to return all errors, and besides it's not // generally meaningful to return errors from different // authenticators since some of them might be expected // behavior. So, for now, these errors are being ignored if (logger.isLoggable(Level.FINEST)) { logger.logThrow(Level.FINEST, le, "Could not " + "authenticate credentials with " + "authenticator {0}", authenticator.getClass().getName()); } } } // no authenticators worked throw new CredentialException("Could not authenticate identity"); } }