package com.googlecode.gwt.test.internal.patchers; import com.google.gwt.core.client.GWT; import com.google.gwt.inject.rebind.adapter.GwtDotCreateProvider; import com.google.inject.Binding; import com.google.inject.Inject; import com.google.inject.binder.LinkedBindingBuilder; import com.google.inject.binder.ScopedBindingBuilder; import com.google.inject.internal.AbstractBindingBuilder; import com.googlecode.gwt.test.gin.GwtTestGinException; import com.googlecode.gwt.test.patchers.InitMethod; import com.googlecode.gwt.test.patchers.PatchClass; import com.googlecode.gwt.test.patchers.PatchMethod; import com.googlecode.gwt.test.utils.GwtReflectionUtils; import javassist.CannotCompileException; import javassist.CtClass; import javassist.CtField; import java.lang.reflect.Constructor; import java.lang.reflect.Type; @SuppressWarnings("unchecked") @PatchClass(target = "com.google.gwt.inject.rebind.adapter.GwtDotCreateProvider") class GwtDotCreateProviderPatcher { private static final String BINDED_CLASS_FIELD = "gwtTestUtilsBindedClass"; @PatchMethod static <T> ScopedBindingBuilder bind(LinkedBindingBuilder<T> builder) { if (!(builder instanceof AbstractBindingBuilder)) { throw new GwtTestGinException("Not managed " + LinkedBindingBuilder.class.getSimpleName() + " implementation : " + builder.getClass().getName()); } Binding<T> binding = GwtReflectionUtils.<Binding<T>>getPrivateFieldValue(builder, "binding"); Type type = binding.getKey().getTypeLiteral().getType(); if (!(type instanceof Class)) { throw new GwtTestGinException("Not managed binded type : " + type); } Constructor<T> atInjectConstructor = getAtInjectConstructor((Class<T>) type); if (atInjectConstructor != null) { return builder.toConstructor(atInjectConstructor); } GwtDotCreateProvider<T> gwtDotCreateProvider = GwtReflectionUtils.instantiateClass(GwtDotCreateProvider.class); GwtReflectionUtils.setPrivateFieldValue(gwtDotCreateProvider, BINDED_CLASS_FIELD, type); return builder.toProvider(gwtDotCreateProvider); } @PatchMethod static <T> T get(GwtDotCreateProvider<?> gwtDotCreateProvider) { Class<T> bindedType = GwtReflectionUtils.<Class<T>>getPrivateFieldValue( gwtDotCreateProvider, BINDED_CLASS_FIELD); return GWT.<T>create(bindedType); } @InitMethod static void initClass(CtClass ctClass) throws CannotCompileException { CtField field = CtField.make("private Class " + BINDED_CLASS_FIELD + ";", ctClass); ctClass.addField(field); } private static <T> Constructor<T> getAtInjectConstructor(Class<T> toInstanciate) { for (Constructor<?> cons : toInstanciate.getDeclaredConstructors()) { if (cons.getAnnotation(Inject.class) != null) { return (Constructor<T>) cons; } } return null; } }