/*
* 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;
/**
*
* @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) {
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);
}
}