PageRenderTime 3750ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/mycila-testing/tags/mycila-testing-1.1/mycila-testing-plugins/mycila-testing-guice2/src/main/java/com/mycila/testing/plugin/guice/Guice2TestPlugin.java

http://mycila.googlecode.com/
Java | 174 lines | 132 code | 22 blank | 20 comment | 13 complexity | 9d0b2bdbbbcbd24a9ef047039867ef14 MD5 | raw file
Possible License(s): Apache-2.0
  1. /**
  2. * Copyright (C) 2008 Mathieu Carbou <mathieu.carbou@gmail.com>
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.mycila.testing.plugin.guice;
  17. import com.google.inject.AbstractModule;
  18. import com.google.inject.Binder;
  19. import com.google.inject.Guice;
  20. import com.google.inject.Inject;
  21. import com.google.inject.Injector;
  22. import com.google.inject.Module;
  23. import com.google.inject.Provider;
  24. import com.google.inject.Stage;
  25. import com.google.inject.TypeLiteral;
  26. import com.google.inject.binder.AnnotatedBindingBuilder;
  27. import com.google.inject.binder.LinkedBindingBuilder;
  28. import com.google.inject.binder.ScopedBindingBuilder;
  29. import com.google.inject.util.Modules;
  30. import com.mycila.testing.core.AbstractTestPlugin;
  31. import com.mycila.testing.core.Context;
  32. import com.mycila.testing.core.TestPluginException;
  33. import java.lang.reflect.Field;
  34. import java.lang.reflect.Method;
  35. import java.lang.reflect.Type;
  36. import java.util.ArrayList;
  37. import java.util.Arrays;
  38. import java.util.List;
  39. /**
  40. * @author Mathieu Carbou (mathieu.carbou@gmail.com)
  41. */
  42. public final class Guice2TestPlugin extends AbstractTestPlugin {
  43. public void prepareTestInstance(final Context context) {
  44. context.setAttribute("guice.providers", new ArrayList<Provider<?>>());
  45. GuiceContext ctx = context.getTest().getTargetClass().getAnnotation(GuiceContext.class);
  46. // create modules
  47. List<Module> modules = new ArrayList<Module>();
  48. modules.add(new AbstractModule() {
  49. @Override
  50. protected void configure() {
  51. bind(ProviderSetup.class).toInstance(new ProviderSetup() {
  52. @Inject
  53. void inject(Injector injector) {
  54. for (Provider<?> provider : context.<List<Provider<?>>>removeAttribute("guice.providers")) {
  55. injector.injectMembers(provider);
  56. }
  57. }
  58. });
  59. }
  60. });
  61. modules.addAll(providedModules(context));
  62. modules.add(bindings(context));
  63. modules.add(providedBindings(context));
  64. if (context.getTest().getTarget() instanceof Module) {
  65. modules.add((Module) context.getTest().getTarget());
  66. }
  67. // create injector
  68. Injector injector = Guice.createInjector(findStage(ctx), Modules.override(contextualModules(ctx)).with(modules));
  69. context.setAttribute("com.google.inject.Injector", injector);
  70. injector.injectMembers(context.getTest().getTarget());
  71. }
  72. private Module bindings(final Context context) {
  73. return new Module() {
  74. public void configure(Binder binder) {
  75. for (final Field field : context.getTest().getFieldsAnnotatedWith(Bind.class)) {
  76. Guice2TestPlugin.this.configure(context, binder, field.getGenericType(), field.getAnnotation(Bind.class), new InjectedProvider<Object>() {
  77. public Object getInternal() {
  78. return context.getTest().get(field);
  79. }
  80. });
  81. }
  82. }
  83. };
  84. }
  85. private Module providedBindings(final Context context) {
  86. return new Module() {
  87. public void configure(Binder binder) {
  88. for (final Method method : context.getTest().getMethodsAnnotatedWith(Bind.class)) {
  89. Guice2TestPlugin.this.configure(context, binder, method.getGenericReturnType(), method.getAnnotation(Bind.class), new InjectedProvider<Object>() {
  90. public Object getInternal() {
  91. return context.getTest().invoke(method);
  92. }
  93. });
  94. }
  95. }
  96. };
  97. }
  98. @SuppressWarnings({"unchecked"})
  99. private <T> void configure(Context context, Binder binder, Type type, Bind annotation, InjectedProvider<T> provider) {
  100. AnnotatedBindingBuilder<T> builder1 = (AnnotatedBindingBuilder<T>) binder.bind(TypeLiteral.get(type));
  101. LinkedBindingBuilder<T> builder2 = annotation.annotatedBy().equals(NoAnnotation.class) ? builder1 : builder1.annotatedWith(annotation.annotatedBy());
  102. ScopedBindingBuilder builder3 = builder2.toProvider(provider);
  103. if (!annotation.scope().equals(NoAnnotation.class)) {
  104. builder3.in(annotation.scope());
  105. }
  106. context.<List<InjectedProvider<T>>>getAttribute("guice.providers").add(provider);
  107. }
  108. @SuppressWarnings({"unchecked"})
  109. private List<Module> providedModules(Context ctx) {
  110. List<Module> modules = new ArrayList<Module>();
  111. for (Method method : ctx.getTest().getMethodsOfTypeAnnotatedWith(Module.class, ModuleProvider.class)) {
  112. modules.add((Module) ctx.getTest().invoke(method));
  113. }
  114. for (Method method : ctx.getTest().getMethodsOfTypeAnnotatedWith(Module[].class, ModuleProvider.class)) {
  115. modules.addAll(Arrays.asList((Module[]) ctx.getTest().invoke(method)));
  116. }
  117. for (Method method : ctx.getTest().getMethodsOfTypeAnnotatedWith(Iterable.class, ModuleProvider.class)) {
  118. for (Module module : (Iterable<Module>) ctx.getTest().invoke(method)) {
  119. modules.add(module);
  120. }
  121. }
  122. return modules;
  123. }
  124. private Stage findStage(GuiceContext ctx) {
  125. return ctx == null ? Stage.DEVELOPMENT : ctx.stage();
  126. }
  127. private List<Module> contextualModules(GuiceContext context) {
  128. List<Module> modules = new ArrayList<Module>();
  129. if (context != null) {
  130. for (Class<? extends Module> moduleClass : context.value()) {
  131. try {
  132. modules.add(moduleClass.newInstance());
  133. } catch (Exception e) {
  134. throw new TestPluginException(e, "Error instanciating module class '%s': %s", moduleClass.getName(), e.getMessage());
  135. }
  136. }
  137. }
  138. return modules;
  139. }
  140. private static interface ProviderSetup {
  141. }
  142. private static abstract class InjectedProvider<T> implements Provider<T> {
  143. @Inject
  144. Injector injector;
  145. public final T get() {
  146. T t = getInternal();
  147. injector.injectMembers(t);
  148. return t;
  149. }
  150. protected abstract T getInternal();
  151. }
  152. }