org.solmix.runtime.support.spring.ContainerPostProcessor.java Source code

Java tutorial

Introduction

Here is the source code for org.solmix.runtime.support.spring.ContainerPostProcessor.java

Source

/*
 *  Copyright 2012 The Solmix Project
 *
 * 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 may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.gnu.org/licenses/ 
 * or see the FSF site: http://www.fsf.org. 
 */

package org.solmix.runtime.support.spring;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.solmix.runtime.Container;
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.config.ConstructorArgumentValues;
import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;

/**
 * 
 * @author solmix.f@gmail.com
 * @version $Id$ 2013-11-4
 */

public class ContainerPostProcessor implements BeanFactoryPostProcessor {

    private Container container;

    String name;

    public ContainerPostProcessor() {

    }

    public ContainerPostProcessor(Container container) {
        this.container = container;
    }

    public ContainerPostProcessor(String name) {
        this.name = name;
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        Object inject = container;
        if (inject == null) {
            inject = getContainerByName(Container.DEFAULT_CONTAINER_ID, beanFactory, true, null);
        } else {
            if (!beanFactory.containsBeanDefinition(Container.DEFAULT_CONTAINER_ID)
                    && !beanFactory.containsSingleton(Container.DEFAULT_CONTAINER_ID)) {
                beanFactory.registerSingleton(Container.DEFAULT_CONTAINER_ID, container);
            }
        }
        for (String beanName : beanFactory.getBeanDefinitionNames()) {
            BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
            Object p = beanDefinition.getAttribute(AbstractBeanDefinitionParser.WIRE_CONTAINER_ATTRIBUTE);
            if (p == null)
                continue;
            String name = (String) beanDefinition.getAttribute(AbstractBeanDefinitionParser.WIRE_CONTAINER_NAME);
            String create = (String) beanDefinition
                    .getAttribute(AbstractBeanDefinitionParser.WIRE_CONTAINER_CREATE);
            Object inj = inject;
            if (name != null) {
                if (container != null) {
                    continue;
                }
                inj = getContainerByName(name, beanFactory, create != null, create);
            }
            beanDefinition.removeAttribute(AbstractBeanDefinitionParser.WIRE_CONTAINER_NAME);
            beanDefinition.removeAttribute(AbstractBeanDefinitionParser.WIRE_CONTAINER_ATTRIBUTE);
            beanDefinition.removeAttribute(AbstractBeanDefinitionParser.WIRE_CONTAINER_CREATE);
            if (create == null) {
                if (Boolean.valueOf(p.toString())) {
                    beanDefinition.getPropertyValues().addPropertyValue("container", inj);
                } else {
                    ConstructorArgumentValues constructorArgs = beanDefinition.getConstructorArgumentValues();
                    insertConstructorArg(constructorArgs, inj);
                }
            }
        } //end loop bean.

    }

    private void insertConstructorArg(ConstructorArgumentValues constructorArgs, Object valueToInsert) {
        List<ValueHolder> genericArgs = new ArrayList<ValueHolder>((constructorArgs.getGenericArgumentValues()));
        Map<Integer, ValueHolder> indexedArgs = new HashMap<Integer, ValueHolder>(
                constructorArgs.getIndexedArgumentValues());

        constructorArgs.clear();
        for (ValueHolder genericValue : genericArgs) {
            constructorArgs.addGenericArgumentValue(genericValue);
        }
        for (Map.Entry<Integer, ValueHolder> entry : indexedArgs.entrySet()) {
            constructorArgs.addIndexedArgumentValue(entry.getKey() + 1, entry.getValue());
        }
        constructorArgs.addIndexedArgumentValue(0, valueToInsert);
    }

    private Object getContainerByName(String name, ConfigurableListableBeanFactory factory, boolean create,
            String cn) {

        if (!factory.containsBeanDefinition(name) && (create || Container.DEFAULT_CONTAINER_ID.equals(name))) {
            //
            DefaultListableBeanFactory df = (DefaultListableBeanFactory) factory;
            RootBeanDefinition rbd = new RootBeanDefinition(SpringContainer.class);
            if (cn != null) {
                //  SpringContainer.setConfig
                rbd.setAttribute("config", new RuntimeBeanReference(cn));
            }
            df.registerBeanDefinition(name, rbd);
        } else if (cn != null) {
            BeanDefinition bd = factory.getBeanDefinition(name);
            bd.getPropertyValues().addPropertyValue("config", new RuntimeBeanReference(cn));
        }
        return new RuntimeBeanReference(name);
    }

    private static Container getContainerByName(String name, ApplicationContext context, boolean create) {
        if (!context.containsBean(name) && (create || Container.DEFAULT_CONTAINER_ID.equals(name))) {
            SpringContainer b = new SpringContainer();
            ConfigurableApplicationContext cctx = (ConfigurableApplicationContext) context;
            cctx.getBeanFactory().registerSingleton(name, b);
            b.setApplicationContext(context);
        }
        return context.getBean(name, Container.class);
    }

    /**Container,container?*/
    public static Container addDefault(ApplicationContext ctx) {
        if (!ctx.containsBean(Container.DEFAULT_CONTAINER_ID)) {
            Container b = getContainerByName(Container.DEFAULT_CONTAINER_ID, ctx, true);
            if (ctx instanceof ConfigurableApplicationContext) {
                ConfigurableApplicationContext cctx = (ConfigurableApplicationContext) ctx;
                new ContainerPostProcessor(b).postProcessBeanFactory(cctx.getBeanFactory());
            }
        }
        return Container.class.cast(ctx.getBean(Container.DEFAULT_CONTAINER_ID, Container.class));
    }

    /**??container*/
    public static Container addContainer(ApplicationContext ctx, String name) {
        return getContainerByName(name, ctx, true);
    }
}