com.googlecode.gwt.test.gin.GInjectorCreateHandler Maven / Gradle / Ivy
package com.googlecode.gwt.test.gin;
import com.google.gwt.core.client.GWT;
import com.google.gwt.inject.client.GinModule;
import com.google.gwt.inject.client.GinModules;
import com.google.gwt.inject.client.Ginjector;
import com.google.gwt.inject.rebind.GinjectorBindings;
import com.google.gwt.inject.rebind.adapter.GinModuleAdapter;
import com.google.gwt.inject.rebind.util.GuiceUtil;
import com.google.gwt.inject.rebind.util.MemberCollector;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.googlecode.gwt.test.GwtCreateHandler;
import com.googlecode.gwt.test.GwtTreeLogger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Handle {@link GWT#create(Class)} for {@link Ginjector}.
*
* @author Alex Dobjanschi
* @author Gael Lazzari
*/
public class GInjectorCreateHandler implements GwtCreateHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(GInjectorCreateHandler.class);
// map used as cache to store bindings between gin and guice proxy injectors
private Map, Object> injectors;
public Object create(Class classLiteral) throws Exception {
// Make sure this is a Ginjector
if (!Ginjector.class.isAssignableFrom(classLiteral)) {
return null;
}
@SuppressWarnings("unchecked")
Class ginjectorClass = (Class) classLiteral;
if (injectors == null) {
injectors = new HashMap, Object>();
}
Object guiceInjectorProxy = injectors.get(classLiteral);
if (guiceInjectorProxy != null) {
LOGGER.debug("Proxy for class '" + ginjectorClass.getName()
+ "'has been found in cache. It is returned");
return guiceInjectorProxy;
}
Class[] ginModules = readGinModules(ginjectorClass);
// create a set of Guice Module bases on the GinModules
Set guiceModules = readGuiceModules(ginModules, ginjectorClass);
// Use Guice SPI to solve deferred binding dependencies
DeferredBindingModule deferredBindingModule = DeferredBindingModule.getDeferredBindingModule(
ginjectorClass, guiceModules);
guiceModules.add(deferredBindingModule);
// Instantiate an injector, based on the modules read above + the
// deferredBindingModule
Injector injector = Guice.createInjector(guiceModules);
LOGGER.debug("creating new Proxy for class '" + ginjectorClass.getName() + "'");
guiceInjectorProxy = Proxy.newProxyInstance(this.getClass().getClassLoader(),
new Class[]{ginjectorClass}, new GinInjectorInvocationHandler(injector));
injectors.put(ginjectorClass, guiceInjectorProxy);
return guiceInjectorProxy;
}
private Class[] readGinModules(Class classLiteral) {
LOGGER.debug("inspecting classLiteral " + classLiteral);
GinModules annotation = classLiteral.getAnnotation(GinModules.class);
if (annotation == null) {
// Throw an exception if we don't find this specific annotation.
throw new IllegalArgumentException(classLiteral.getName()
+ " doesn't have any @GinModules annotation present");
}
Class[] ginModules = annotation.value();
if (ginModules == null || ginModules.length == 0) {
// there are no GinModules present in the Ginjector.
throw new IllegalArgumentException(classLiteral.getName()
+ " doesn't have any GinModules. " + "Runtime should not work.");
}
LOGGER.debug("discovered modules " + annotation);
return ginModules;
}
private Set readGuiceModules(Class[] classLiterals,
Class ginectorClass) throws Exception {
Set modules = new HashSet();
for (Class literal : classLiterals) {
LOGGER.debug("wrapping GinModule literal " + literal);
MemberCollector memberCollector = new MemberCollector(GwtTreeLogger.get());
GuiceUtil guiceUtil = new GuiceUtil(memberCollector);
modules.add(new GinModuleAdapter(literal.newInstance(), new GinjectorBindings(null,
GwtTreeLogger.get(), guiceUtil, ginectorClass, null, memberCollector, null, null)));
}
return modules;
}
}