org.springframework.social.config.support.ProviderConfigurationSupport.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.social.config.support.ProviderConfigurationSupport.java

Source

/*
 * Copyright 2015 the original author or authors.
 *
 * 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.springframework.social.config.support;

import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.scope.ScopedProxyUtils;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.core.GenericTypeResolver;
import org.springframework.social.config.xml.ApiHelper;
import org.springframework.social.connect.ConnectionFactory;
import org.springframework.social.connect.support.ConnectionFactoryRegistry;
import org.springframework.social.security.provider.SocialAuthenticationService;
import org.springframework.util.ClassUtils;

public abstract class ProviderConfigurationSupport {

    private final static Log logger = LogFactory.getLog(ProviderConfigurationSupport.class);

    public ProviderConfigurationSupport(Class<? extends ConnectionFactory<?>> connectionFactoryClass,
            Class<? extends ApiHelper<?>> apiHelperClass) {
        this.connectionFactoryClass = connectionFactoryClass;
        this.apiHelperClass = apiHelperClass;
        this.apiBindingType = GenericTypeResolver.resolveTypeArgument(connectionFactoryClass,
                ConnectionFactory.class);
        if (isSocialSecurityAvailable()) {
            this.authenticationServiceClass = getAuthenticationServiceClass();
        }
    }

    protected Class<? extends SocialAuthenticationService<?>> getAuthenticationServiceClass() {
        return null;
    }

    protected static boolean isSocialSecurityAvailable() {
        try {
            Class.forName("org.springframework.social.security.SocialAuthenticationServiceLocator");
            return true;
        } catch (ClassNotFoundException cnfe) {
            return false;
        }
    }

    /**
     * Creates a BeanDefinition for a provider connection factory.
     * Although most providers will not need to override this method, it does allow for overriding to address any provider-specific needs.
     * @param appId The application's App ID
     * @param appSecret The application's App Secret
     * @param allAttributes All attributes available on the configuration element. Useful for provider-specific configuration.
     * @return a BeanDefinition for the provider's connection factory bean.
     */
    protected BeanDefinition getConnectionFactoryBeanDefinition(String appId, String appSecret,
            Map<String, Object> allAttributes) {
        return BeanDefinitionBuilder.genericBeanDefinition(connectionFactoryClass).addConstructorArgValue(appId)
                .addConstructorArgValue(appSecret).getBeanDefinition();
    }

    protected BeanDefinition getAuthenticationServiceBeanDefinition(String appId, String appSecret,
            Map<String, Object> allAttributes) {
        return BeanDefinitionBuilder.genericBeanDefinition(authenticationServiceClass).addConstructorArgValue(appId)
                .addConstructorArgValue(appSecret).getBeanDefinition();
    }

    protected BeanDefinition registerBeanDefinitions(BeanDefinitionRegistry registry,
            Map<String, Object> allAttributes) {
        if (isSocialSecurityAvailable() && authenticationServiceClass != null) {
            registerAuthenticationServiceBeanDefinitions(registry, allAttributes);
        } else {
            registerConnectionFactoryBeanDefinitions(registry, allAttributes);
        }

        return registerApiBindingBean(registry, apiHelperClass, apiBindingType, allAttributes);
    }

    protected abstract String getAppId(Map<String, Object> allAttributes);

    protected abstract String getAppSecret(Map<String, Object> allAttributes);

    private void registerConnectionFactoryBeanDefinitions(BeanDefinitionRegistry registry,
            Map<String, Object> allAttributes) {
        BeanDefinition connectionFactoryBD = getConnectionFactoryBeanDefinition(getAppId(allAttributes),
                getAppSecret(allAttributes), allAttributes);
        BeanDefinition connectionFactoryLocatorBD = registerConnectionFactoryLocatorBean(registry);
        registerConnectionFactoryBean(connectionFactoryLocatorBD, connectionFactoryBD, connectionFactoryClass);
    }

    @SuppressWarnings("unchecked")
    private void registerAuthenticationServiceBeanDefinitions(BeanDefinitionRegistry registry,
            Map<String, Object> allAttributes) {
        Class<? extends org.springframework.social.security.provider.SocialAuthenticationService<?>> socialAuthenticationServiceClass = (Class<? extends org.springframework.social.security.provider.SocialAuthenticationService<?>>) this.authenticationServiceClass;
        BeanDefinition authenticationServiceBD = getAuthenticationServiceBeanDefinition(getAppId(allAttributes),
                getAppSecret(allAttributes), allAttributes);
        BeanDefinition connectionFactoryLocatorBD = registerConnectionFactoryLocatorBean(registry);
        registerAuthenticationServiceBean(connectionFactoryLocatorBD, authenticationServiceBD,
                socialAuthenticationServiceClass);
    }

    private BeanDefinition registerConnectionFactoryLocatorBean(BeanDefinitionRegistry registry) {
        Class<?> connectionFactoryRegistryClass = isSocialSecurityAvailable()
                ? org.springframework.social.security.SocialAuthenticationServiceRegistry.class
                : ConnectionFactoryRegistry.class;
        if (!registry.containsBeanDefinition(CONNECTION_FACTORY_LOCATOR_ID)) {
            if (logger.isDebugEnabled()) {
                logger.debug("Registering ConnectionFactoryLocator bean ("
                        + connectionFactoryRegistryClass.getName() + ")");
            }
            BeanDefinitionHolder connFactoryLocatorBeanDefHolder = new BeanDefinitionHolder(
                    BeanDefinitionBuilder.genericBeanDefinition(connectionFactoryRegistryClass).getBeanDefinition(),
                    CONNECTION_FACTORY_LOCATOR_ID);
            BeanDefinitionHolder scopedProxy = ScopedProxyUtils.createScopedProxy(connFactoryLocatorBeanDefHolder,
                    registry, false);
            registry.registerBeanDefinition(scopedProxy.getBeanName(), scopedProxy.getBeanDefinition());
        }
        BeanDefinition connectionFactoryLocatorBD = registry
                .getBeanDefinition(ScopedProxyUtils.getTargetBeanName(CONNECTION_FACTORY_LOCATOR_ID));
        return connectionFactoryLocatorBD;
    }

    private BeanDefinition registerConnectionFactoryBean(BeanDefinition connectionFactoryLocatorBD,
            BeanDefinition connectionFactoryBD, Class<? extends ConnectionFactory<?>> connectionFactoryClass) {
        if (logger.isDebugEnabled()) {
            logger.debug("Registering ConnectionFactory: " + connectionFactoryClass.getName());
        }
        PropertyValue connectionFactoriesPropertyValue = connectionFactoryLocatorBD.getPropertyValues()
                .getPropertyValue(CONNECTION_FACTORIES);
        @SuppressWarnings("unchecked")
        List<BeanDefinition> connectionFactoriesList = connectionFactoriesPropertyValue != null
                ? (List<BeanDefinition>) connectionFactoriesPropertyValue.getValue()
                : new ManagedList<BeanDefinition>();
        connectionFactoriesList.add(connectionFactoryBD);
        connectionFactoryLocatorBD.getPropertyValues().addPropertyValue(CONNECTION_FACTORIES,
                connectionFactoriesList);
        return connectionFactoryBD;
    }

    private BeanDefinition registerAuthenticationServiceBean(BeanDefinition authenticationServiceLocatorBD,
            BeanDefinition authenticationServiceBD,
            Class<? extends org.springframework.social.security.provider.SocialAuthenticationService<?>> socialAuthenticationServiceClass) {
        if (logger.isDebugEnabled()) {
            logger.debug("Registering SocialAuthenticationService: " + socialAuthenticationServiceClass.getName());
        }
        PropertyValue authenticationServicesPropertyValue = authenticationServiceLocatorBD.getPropertyValues()
                .getPropertyValue(AUTHENTICATION_SERVICES);
        @SuppressWarnings("unchecked")
        List<BeanDefinition> authenticationServicesList = authenticationServicesPropertyValue != null
                ? (List<BeanDefinition>) authenticationServicesPropertyValue.getValue()
                : new ManagedList<BeanDefinition>();
        authenticationServicesList.add(authenticationServiceBD);
        authenticationServiceLocatorBD.getPropertyValues().addPropertyValue(AUTHENTICATION_SERVICES,
                authenticationServicesList);
        return authenticationServiceBD;
    }

    private BeanDefinition registerApiBindingBean(BeanDefinitionRegistry registry,
            Class<? extends ApiHelper<?>> apiHelperClass, Class<?> apiBindingType,
            Map<String, Object> allAttributes) {
        if (logger.isDebugEnabled()) {
            logger.debug("Registering API Helper bean for " + ClassUtils.getShortName(apiBindingType));
        }
        String helperId = "__" + ClassUtils.getShortNameAsProperty(apiBindingType) + "ApiHelper";
        // TODO: Make the bean IDs here configurable.
        BeanDefinition helperBD = getApiHelperBeanDefinitionBuilder(allAttributes).getBeanDefinition();
        registry.registerBeanDefinition(helperId, helperBD);

        if (logger.isDebugEnabled()) {
            logger.debug("Creating API Binding bean for " + ClassUtils.getShortName(apiBindingType));
        }
        BeanDefinition bindingBD = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
        bindingBD.setFactoryBeanName(helperId);
        bindingBD.setFactoryMethodName("getApi");
        bindingBD.setScope("request");
        BeanDefinitionHolder scopedProxyBDH = ScopedProxyUtils.createScopedProxy(
                new BeanDefinitionHolder(bindingBD, ClassUtils.getShortNameAsProperty(apiBindingType)), registry,
                false);
        registry.registerBeanDefinition(scopedProxyBDH.getBeanName(), scopedProxyBDH.getBeanDefinition());
        return scopedProxyBDH.getBeanDefinition();
    }

    /**
     * Subclassing hook to allow api helper bean to be configured with attributes from annotation
     * @param allAttributes additional attributes that may be used when creating the API helper bean.
     * @return a {@link BeanDefinitionBuilder} for the API Helper
     */
    protected BeanDefinitionBuilder getApiHelperBeanDefinitionBuilder(Map<String, Object> allAttributes) {
        return BeanDefinitionBuilder.genericBeanDefinition(apiHelperClass)
                .addConstructorArgReference("usersConnectionRepository").addConstructorArgReference("userIdSource");
    }

    protected final Class<? extends ConnectionFactory<?>> connectionFactoryClass;

    protected final Class<? extends ApiHelper<?>> apiHelperClass;

    protected final Class<?> apiBindingType;

    protected Class<?> authenticationServiceClass;

    private static final String CONNECTION_FACTORY_LOCATOR_ID = "connectionFactoryLocator";

    private static final String CONNECTION_FACTORIES = "connectionFactories";

    private static final String AUTHENTICATION_SERVICES = "authenticationServices";

}