/*! ******************************************************************************
*
* Pentaho Data Integration
*
* Copyright (C) 2002-2013 by Pentaho : http://www.pentaho.com
*
*******************************************************************************
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
package org.pentaho.di.core.auth.core;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.pentaho.di.core.auth.core.impl.DefaultAuthenticationConsumerFactory;
import org.pentaho.di.core.auth.core.impl.DefaultAuthenticationPerformerFactory;
import org.pentaho.di.i18n.BaseMessages;
public class AuthenticationManager {
private static final Class<?> PKG = AuthenticationManager.class;
private final Map<Class<?>, Map<Class<?>, Map<Class<?>, AuthenticationConsumerFactory<?, ?, ?>>>> factoryMap =
new HashMap<Class<?>, Map<Class<?>, Map<Class<?>, AuthenticationConsumerFactory<?, ?, ?>>>>();
private AuthenticationPerformerFactory authenticationPerformerFactory = new DefaultAuthenticationPerformerFactory();
private final List<AuthenticationProvider> authenticationProviders = new ArrayList<AuthenticationProvider>();
public void registerAuthenticationProvider( AuthenticationProvider authenticationProvider ) {
synchronized ( authenticationProviders ) {
authenticationProviders.add( authenticationProvider );
}
}
public boolean unregisterAuthenticationProvider( AuthenticationProvider authenticationProvider ) {
synchronized ( authenticationProviders ) {
return authenticationProviders.remove( authenticationProvider );
}
}
public <ReturnType, CreateArgType, ConsumedType> void registerConsumerFactory(
AuthenticationConsumerFactory<ReturnType, CreateArgType, ConsumedType> factory ) throws AuthenticationFactoryException {
if ( !factory.getConsumedType().isInterface()
&& !AuthenticationProvider.class.isAssignableFrom( factory.getConsumedType() ) ) {
throw new AuthenticationFactoryException( BaseMessages.getString( PKG, "AuthenticationManager.ConsumedTypeError",
factory ) );
}
Map<Class<?>, AuthenticationConsumerFactory<?, ?, ?>> createTypeMap =
getRelevantConsumerFactoryMap( factory.getReturnType(), factory.getCreateArgType() );
synchronized ( createTypeMap ) {
createTypeMap.put( factory.getConsumedType(), factory );
}
}
public <ReturnType, ConsumedType> void registerConsumerClass(
Class<? extends AuthenticationConsumer<? extends ReturnType, ? extends ConsumedType>> consumerClass ) throws AuthenticationFactoryException {
registerConsumerFactory( new DefaultAuthenticationConsumerFactory( consumerClass ) );
}
public <ReturnType, CreateArgType, ConsumedType> List<AuthenticationPerformer<ReturnType, CreateArgType>>
getSupportedAuthenticationPerformers( Class<ReturnType> returnType, Class<CreateArgType> createArgType ) {
Map<Class<?>, AuthenticationConsumerFactory<?, ?, ?>> createTypeMap =
getRelevantConsumerFactoryMap( returnType, createArgType );
synchronized ( createTypeMap ) {
createTypeMap = new HashMap<Class<?>, AuthenticationConsumerFactory<?, ?, ?>>( createTypeMap );
}
List<AuthenticationProvider> authenticationProviders;
synchronized ( this.authenticationProviders ) {
authenticationProviders = new ArrayList<AuthenticationProvider>( this.authenticationProviders );
}
List<AuthenticationPerformer<ReturnType, CreateArgType>> result =
new ArrayList<AuthenticationPerformer<ReturnType, CreateArgType>>();
for ( Entry<Class<?>, AuthenticationConsumerFactory<?, ?, ?>> entry : createTypeMap.entrySet() ) {
for ( AuthenticationProvider provider : authenticationProviders ) {
@SuppressWarnings( "unchecked" )
AuthenticationPerformer<ReturnType, CreateArgType> authenticationPerformer =
(AuthenticationPerformer<ReturnType, CreateArgType>) authenticationPerformerFactory.create( provider, entry
.getValue() );
if ( authenticationPerformer != null && authenticationPerformer.getDisplayName() != null ) {
result.add( authenticationPerformer );
}
}
}
Collections.sort( result, new Comparator<AuthenticationPerformer<ReturnType, CreateArgType>>() {
@Override
public int compare( AuthenticationPerformer<ReturnType, CreateArgType> o1,
AuthenticationPerformer<ReturnType, CreateArgType> o2 ) {
return o1.getDisplayName().toUpperCase().compareTo( o2.getDisplayName().toUpperCase() );
}
} );
return result;
}
public <ReturnType, CreateArgType, ConsumedType> AuthenticationPerformer<ReturnType, CreateArgType>
getAuthenticationPerformer( Class<ReturnType> returnType, Class<CreateArgType> createArgType, String providerId ) {
List<AuthenticationPerformer<ReturnType, CreateArgType>> performers =
getSupportedAuthenticationPerformers( returnType, createArgType );
for ( AuthenticationPerformer<ReturnType, CreateArgType> candidatePerformer : performers ) {
if ( candidatePerformer.getAuthenticationProvider().getId().equals( providerId ) ) {
return candidatePerformer;
}
}
return null;
}
private <ReturnType, CreateArgType> Map<Class<?>, AuthenticationConsumerFactory<?, ?, ?>>
getRelevantConsumerFactoryMap( Class<ReturnType> returnType, Class<CreateArgType> createArgType ) {
synchronized ( factoryMap ) {
Map<Class<?>, Map<Class<?>, AuthenticationConsumerFactory<?, ?, ?>>> returnTypeMap = factoryMap.get( returnType );
if ( returnTypeMap == null ) {
returnTypeMap = new HashMap<Class<?>, Map<Class<?>, AuthenticationConsumerFactory<?, ?, ?>>>();
factoryMap.put( returnType, returnTypeMap );
}
Map<Class<?>, AuthenticationConsumerFactory<?, ?, ?>> createTypeMap = returnTypeMap.get( createArgType );
if ( createTypeMap == null ) {
createTypeMap = new HashMap<Class<?>, AuthenticationConsumerFactory<?, ?, ?>>();
returnTypeMap.put( createArgType, createTypeMap );
}
return createTypeMap;
}
}
protected void setAuthenticationPerformerFactory( AuthenticationPerformerFactory authenticationPerformerFactory ) {
this.authenticationPerformerFactory = authenticationPerformerFactory;
}
}