Package grails.plugin.multitenant.core.spring

Source Code of grails.plugin.multitenant.core.spring.ConfiguredTenantScopedBeanProcessor

package grails.plugin.multitenant.core.spring;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.groovy.grails.commons.spring.BeanConfiguration;
import org.codehaus.groovy.grails.commons.spring.DefaultBeanConfiguration;
import org.springframework.aop.scope.ScopedProxyFactoryBean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;

/**
* Creates a tenant scoped proxy around beans configured to be unique per tenant.
* In short terms, this works by lazily creating a new prototyped definition of
* each per-tenant bean for each tenant.
* @author Kim A. Betti
*/
public class ConfiguredTenantScopedBeanProcessor implements BeanFactoryPostProcessor {

    private static final Log log = LogFactory.getLog(ConfiguredTenantScopedBeanProcessor.class);
    private List<String> perTenantBeans;

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        BeanDefinitionRegistry appCtx = (DefaultListableBeanFactory) beanFactory;
        for (String beanName : getPerTenantBeanNames(appCtx)) {
            log.info("Setting tenant scope for: " + beanName);
            BeanDefinition beanDef = appCtx.getBeanDefinition(beanName);
            processBean(beanName, beanDef, appCtx);
        }
    }

    private void processBean(String beanName, BeanDefinition beanDef, BeanDefinitionRegistry appCtx) {
        final String tenantScopedBeanName = "_" + beanName;
        final String prototypeBeanName = tenantScopedBeanName + "_prototype";

        makeTenantScopedCopy(appCtx, beanDef, tenantScopedBeanName);
        makePrototypeScopedCopy(appCtx, beanDef, prototypeBeanName);
        replaceWithScopedProxy(appCtx, beanName, tenantScopedBeanName);
    }

    private List<String> getPerTenantBeanNames(BeanDefinitionRegistry beanFactory) {
        List<String> perTenantBeanNames = new ArrayList<String>();
        for (String beanName : beanFactory.getBeanDefinitionNames()) {
            BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);

            if (perTenantBeans.contains(beanName)) {
                perTenantBeanNames.add(beanName);
            } else if (beanDefinition.getScope() == TenantScope.NAME) {
                perTenantBeanNames.add(beanName);
            }
        }

        return perTenantBeanNames;
    }

    private BeanDefinition makeTenantScopedCopy(BeanDefinitionRegistry appCtx, BeanDefinition beanDef, String tenantScopedBeanName) {
        BeanDefinition tenantScopedBeanDef = copyBeanDefiniton(appCtx, beanDef, tenantScopedBeanName);
        tenantScopedBeanDef.setScope(TenantScope.NAME);
        return tenantScopedBeanDef;
    }

    private BeanDefinition makePrototypeScopedCopy(BeanDefinitionRegistry appCtx, BeanDefinition orgBeanDef, String prototypeBeanName) {
        BeanDefinition prototypeDefinition = copyBeanDefiniton(appCtx, orgBeanDef, prototypeBeanName);
        prototypeDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
        return prototypeDefinition;
    }

    private BeanDefinition copyBeanDefiniton(BeanDefinitionRegistry appCtx, BeanDefinition orgBeanDef, String newBeanName) {
        BeanDefinition copiedBeanDefinition = new GenericBeanDefinition(orgBeanDef);
        appCtx.registerBeanDefinition(newBeanName, copiedBeanDefinition);
        return copiedBeanDefinition;
    }

    private void replaceWithScopedProxy(BeanDefinitionRegistry appCtx, String beanName, String targetBeanName) {
        BeanConfiguration scopedProxy = new DefaultBeanConfiguration(ScopedProxyFactoryBean.class);
        scopedProxy.addProperty("targetBeanName", targetBeanName);

        BeanDefinition scopedBeanDefinition = scopedProxy.getBeanDefinition();
        appCtx.registerBeanDefinition(beanName, scopedBeanDefinition);
    }

    /**
     * Usually configured in the Grails bean DSL
     * @param perTenantBeans
     */
    public void setPerTenantBeans(List<String> perTenantBeans) {
        this.perTenantBeans = perTenantBeans;
    }

}
TOP

Related Classes of grails.plugin.multitenant.core.spring.ConfiguredTenantScopedBeanProcessor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.