/*
* Copyright 2013-2014 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.guice.annotation;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map.Entry;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.guice.module.SpringModule;
import com.google.inject.Binding;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.name.Named;
@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE + 10)
public class ModuleRegistryConfiguration implements BeanDefinitionRegistryPostProcessor, ApplicationContextAware {
ApplicationContext applicationContext;
private Injector createInjector(Collection<Module> modules) {
return Guice.createInjector(modules);
}
private void mapBindings(Injector injector, BeanDefinitionRegistry registry)
{
for (Entry<Key<?>, Binding<?>> entry : injector.getBindings().entrySet()) {
if (entry.getKey().getTypeLiteral().getRawType().equals(Injector.class) ||
"spring-guice".equals(entry.getValue().getSource().toString())) {
continue;
}
entry.getValue().getKey().toString();
RootBeanDefinition bean = new RootBeanDefinition(GuiceFactoryBean.class);
ConstructorArgumentValues args = new ConstructorArgumentValues();
args.addIndexedArgumentValue(0, entry.getKey().getTypeLiteral().getRawType());
args.addIndexedArgumentValue(1, entry.getValue().getProvider());
bean.setConstructorArgumentValues(args);
registry.registerBeanDefinition(extractName(entry.getValue().getKey()), bean);
}
if(injector.getParent() != null)
{
mapBindings(injector.getParent(), registry);
}
((ConfigurableListableBeanFactory) registry).registerResolvableDependency(Injector.class, injector);
}
private String extractName(Key<?> key) {
if (key.getAnnotation() instanceof Named) {
return ((Named) key.getAnnotation()).value();
}
return key.getTypeLiteral().getRawType().getSimpleName();
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
List<Module> modules = new ArrayList<Module>(((DefaultListableBeanFactory)registry).getBeansOfType(Module.class).values());
modules.add(new SpringModule(this.applicationContext));
Injector injector = createInjector(modules);
mapBindings(injector, registry);
((ConfigurableListableBeanFactory) registry).registerSingleton(Injector.class.getName(), injector);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext=applicationContext;
}
}