All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
br.com.caelum.vraptor.ioc.guice.GuiceComponentRegistry Maven / Gradle / Ivy
/***
* Copyright (c) 2009 Caelum - www.caelum.com.br/opensource All rights reserved.
*
* 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 br.com.caelum.vraptor.ioc.guice;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.inject.Named;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import br.com.caelum.vraptor.ComponentRegistry;
import br.com.caelum.vraptor.ioc.Cacheable;
import br.com.caelum.vraptor.ioc.ComponentFactory;
import br.com.caelum.vraptor.ioc.ComponentFactoryIntrospector;
import br.com.caelum.vraptor.ioc.StereotypeHandler;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.inject.Binder;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Scope;
import com.google.inject.ScopeAnnotation;
import com.google.inject.TypeLiteral;
import com.google.inject.binder.ScopedBindingBuilder;
import com.google.inject.matcher.Matchers;
import com.google.inject.multibindings.Multibinder;
import com.google.inject.spi.TypeEncounter;
import com.google.inject.spi.TypeListener;
import com.google.inject.util.Types;
/**
* ComponentRegistry for Guice
*
* @author Lucas Cavalcanti
* @author Sergio Lopes
* @since 3.2
*
*/
public class GuiceComponentRegistry implements ComponentRegistry {
private static final Logger logger = LoggerFactory.getLogger(GuiceComponentRegistry.class);
private final Binder binder;
private final Set> boundClasses = new HashSet>();
private final Set> listTypes = new HashSet>();
private final Multibinder stereotypeHandlers;
public GuiceComponentRegistry(Binder binder, Multibinder stereotypeHandlers) {
this.binder = binder;
this.stereotypeHandlers = stereotypeHandlers;
}
public void register(Class requiredType, Class componentType) {
boundClasses.add(requiredType);
logger.debug("Binding {} to {}", requiredType, componentType);
if (StereotypeHandler.class.isAssignableFrom(requiredType)) {
stereotypeHandlers.addBinding().to(requiredType);
}
ScopedBindingBuilder binding = bindToConstructor(requiredType, componentType);
if (defaultScope(componentType)) {
binding.in(GuiceProvider.REQUEST);
}
registerFactory(componentType);
}
private boolean defaultScope(Class componentType) {
for(Annotation annotation : componentType.getAnnotations()) {
if (annotation.annotationType().isAnnotationPresent(ScopeAnnotation.class)) {
return false;
}
}
return true;
}
public void deepRegister(Class componentType) {
register(componentType, componentType);
deepRegister(componentType, componentType);
}
private void deepRegister(Class required, Class component) {
if (required == null || required.equals(Object.class)) {
return;
}
// try register named component
if (component.isAnnotationPresent(Named.class)) {
Named named = ((Class>) component).getAnnotation(Named.class);
logger.debug("Binding {} to {} with @Named({})", new Object[] { required, component, named.value() });
binder.bind(required).annotatedWith(named).to(component);
} else if (!boundClasses.contains(required)) {
logger.debug("Binding {} to {}", required, component);
binder.bind(required).to(component);
boundClasses.add(required);
} else {
logger.debug("Ignoring binding of {} to {}", required, component);
}
for (Class> c : required.getInterfaces()) {
deepRegister(c, component);
}
deepRegister(required.getSuperclass(), component);
}
public void registerInScope(Map classes, Scope scope) {
for (Entry entry : classes.entrySet()) {
bindToConstructor(entry.getKey(), entry.getValue()).in(scope);
registerFactory(entry.getValue());
}
}
private ScopedBindingBuilder bindToConstructor(Class requiredType, Class componentType) {
if (componentType.isAnnotationPresent(Cacheable.class)) {
return binder.bind(requiredType).annotatedWith(Cacheable.class).toConstructor(componentType.getDeclaredConstructors()[0]);
}
Constructor constructor = getConstructor(componentType);
for (Type type : constructor.getGenericParameterTypes()) {
if (type instanceof ParameterizedType) {
ParameterizedType ptype =((ParameterizedType) type);
if (ptype.getRawType() instanceof Class> && List.class.isAssignableFrom((Class>) ptype.getRawType())
&& ptype.getRawType() instanceof Class> && !listTypes.contains(ptype.getActualTypeArguments()[0])) {
listTypes.add((Class>) ptype.getActualTypeArguments()[0]);
registerListType((Class>) ptype.getActualTypeArguments()[0], binder);
}
}
}
return binder.bind(requiredType).toConstructor(constructor);
}
private Constructor getConstructor(Class componentType) {
Constructor[] constructors = componentType.getDeclaredConstructors();
Iterable filteredConstructor = Iterables.filter(Lists.newArrayList(constructors), new Predicate() {
public boolean apply(Constructor constructor) {
return constructor.isAnnotationPresent(Inject.class) || constructor.isAnnotationPresent(javax.inject.Inject.class);
}
});
return Iterables.getFirst(filteredConstructor, constructors[0]);
}
private void registerFactory(Class componentType) {
if (ComponentFactory.class.isAssignableFrom(componentType)) {
final Class> target = new ComponentFactoryIntrospector().targetTypeForComponentFactory(componentType);
Type adapterType = Types.newParameterizedType(ComponentFactoryProviderAdapter.class, target);
Type factoryType = Types.newParameterizedType(ComponentFactory.class, target);
// binder.bind(TypeLiteral.get(adapterType));
binder.bind(TypeLiteral.get(factoryType)).to(componentType);
binder.bind(target).toProvider((TypeLiteral) TypeLiteral.get(adapterType));
}
}
private void registerListType(Class type, Binder binder) {
final AllImplementationsProvider provider = new AllImplementationsProvider();
binder.bindListener(VRaptorAbstractModule.type(Matchers.subclassesOf(type)), new TypeListener() {
public void hear(TypeLiteral literal, TypeEncounter encounter) {
provider.addType(literal.getRawType());
}
});
binder.bind(TypeLiteral.get(Types.listOf(type))).toProvider((Provider)provider);
binder.requestInjection(provider);
}
}