1 | |
package org.jbehave.core.configuration.guice; |
2 | |
|
3 | |
import java.util.ArrayList; |
4 | |
import java.util.List; |
5 | |
|
6 | |
import org.jbehave.core.annotations.guice.UsingGuice; |
7 | |
import org.jbehave.core.configuration.AnnotationBuilder; |
8 | |
import org.jbehave.core.configuration.AnnotationFinder; |
9 | |
import org.jbehave.core.configuration.AnnotationMonitor; |
10 | |
import org.jbehave.core.configuration.AnnotationRequired; |
11 | |
import org.jbehave.core.configuration.Configuration; |
12 | |
import org.jbehave.core.configuration.PrintStreamAnnotationMonitor; |
13 | |
import org.jbehave.core.steps.CompositeStepsFactory; |
14 | |
import org.jbehave.core.steps.InjectableStepsFactory; |
15 | |
import org.jbehave.core.steps.ParameterConverters; |
16 | |
import org.jbehave.core.steps.ParameterConverters.ParameterConverter; |
17 | |
import org.jbehave.core.steps.guice.GuiceStepsFactory; |
18 | |
|
19 | |
import com.google.inject.AbstractModule; |
20 | |
import com.google.inject.Binding; |
21 | |
import com.google.inject.Guice; |
22 | |
import com.google.inject.Injector; |
23 | |
import com.google.inject.Key; |
24 | |
import com.google.inject.Module; |
25 | |
import com.google.inject.TypeLiteral; |
26 | |
import com.google.inject.util.Modules; |
27 | |
|
28 | |
|
29 | |
|
30 | |
|
31 | |
|
32 | |
|
33 | |
|
34 | |
|
35 | |
public class GuiceAnnotationBuilder extends AnnotationBuilder { |
36 | |
|
37 | |
public Injector injector; |
38 | |
|
39 | |
public GuiceAnnotationBuilder(Class<?> annotatedClass) { |
40 | 13 | this(annotatedClass, new PrintStreamAnnotationMonitor()); |
41 | 13 | } |
42 | |
|
43 | |
public GuiceAnnotationBuilder(Class<?> annotatedClass, AnnotationMonitor annotationMonitor) { |
44 | 14 | super(annotatedClass, annotationMonitor); |
45 | 14 | } |
46 | |
|
47 | |
public Configuration buildConfiguration() throws AnnotationRequired { |
48 | |
|
49 | 14 | AnnotationFinder finder = annotationFinder(); |
50 | 14 | if (finder.isAnnotationPresent(UsingGuice.class)) { |
51 | |
@SuppressWarnings("rawtypes") |
52 | 12 | List<Class> moduleClasses = finder.getAnnotatedValues(UsingGuice.class, Class.class, "modules"); |
53 | 12 | List<Module> modules = new ArrayList<Module>(); |
54 | 12 | for (Class<Module> moduleClass : moduleClasses) { |
55 | |
try { |
56 | 12 | modules.add(moduleClass.newInstance()); |
57 | 1 | } catch (Exception e) { |
58 | 1 | annotationMonitor().elementCreationFailed(moduleClass, e); |
59 | 23 | } |
60 | |
} |
61 | |
|
62 | 12 | if (modules.size() > 0) { |
63 | 9 | injector = createInjector(modules); |
64 | |
} |
65 | 12 | } else { |
66 | 2 | annotationMonitor().annotationNotFound(UsingGuice.class, annotatedClass()); |
67 | |
} |
68 | 14 | return super.buildConfiguration(); |
69 | |
} |
70 | |
|
71 | |
@Override |
72 | |
public InjectableStepsFactory buildStepsFactory(Configuration configuration) { |
73 | 7 | InjectableStepsFactory factoryUsingSteps = super.buildStepsFactory(configuration); |
74 | 7 | if (injector != null) { |
75 | 4 | return new CompositeStepsFactory(new GuiceStepsFactory(configuration, injector), factoryUsingSteps); |
76 | |
} |
77 | 3 | return factoryUsingSteps; |
78 | |
} |
79 | |
|
80 | |
@Override |
81 | |
protected ParameterConverters parameterConverters(AnnotationFinder annotationFinder) { |
82 | 12 | ParameterConverters converters = super.parameterConverters(annotationFinder); |
83 | 12 | if (injector != null) { |
84 | 9 | return converters.addConverters(findConverters(injector)); |
85 | |
} |
86 | 3 | return converters; |
87 | |
} |
88 | |
|
89 | |
|
90 | |
|
91 | |
|
92 | |
|
93 | |
|
94 | |
|
95 | |
|
96 | |
|
97 | |
private List<ParameterConverter> findConverters(Injector injector) { |
98 | 118 | List<Binding<ParameterConverter>> bindingsByType = injector |
99 | 118 | .findBindingsByType(new TypeLiteral<ParameterConverter>() { |
100 | |
}); |
101 | 118 | if (bindingsByType.isEmpty() && injector.getParent() != null) { |
102 | 109 | return findConverters(injector.getParent()); |
103 | |
} |
104 | 9 | List<ParameterConverter> converters = new ArrayList<ParameterConverter>(); |
105 | 9 | for (Binding<ParameterConverter> binding : bindingsByType) { |
106 | 18 | converters.add(binding.getProvider().get()); |
107 | |
} |
108 | 9 | return converters; |
109 | |
} |
110 | |
|
111 | |
@Override |
112 | |
protected <T, V extends T> T instanceOf(final Class<T> type, final Class<V> ofClass) { |
113 | 225 | if (injector != null) { |
114 | 171 | if (!type.equals(Object.class)) { |
115 | |
try { |
116 | 168 | boolean bindingFound = findBinding(injector, type); |
117 | 168 | if (bindingFound) { |
118 | |
|
119 | 64 | return injector.getInstance(type); |
120 | |
} else { |
121 | |
|
122 | |
|
123 | 104 | Module module = new AbstractModule() { |
124 | |
|
125 | |
@Override |
126 | |
protected void configure() { |
127 | 104 | if (!type.equals(ofClass)) { |
128 | 96 | bind(type).to(ofClass); |
129 | |
} else { |
130 | |
|
131 | |
|
132 | 8 | bind(ofClass); |
133 | |
} |
134 | 104 | } |
135 | |
}; |
136 | |
|
137 | 104 | injector = injector.createChildInjector(module); |
138 | 104 | return injector.getInstance(type); |
139 | |
} |
140 | 6 | } catch (Exception e) { |
141 | |
|
142 | 6 | return injector.getInstance(ofClass); |
143 | |
} |
144 | |
} else { |
145 | 3 | return injector.getBinding(ofClass).getProvider().get(); |
146 | |
} |
147 | |
} |
148 | 54 | return super.instanceOf(type, ofClass); |
149 | |
} |
150 | |
|
151 | |
|
152 | |
|
153 | |
|
154 | |
|
155 | |
|
156 | |
|
157 | |
|
158 | |
|
159 | |
|
160 | |
|
161 | |
private boolean findBinding(Injector injector, Class<?> type) { |
162 | 1362 | boolean found = false; |
163 | 1362 | for (Key<?> key : injector.getBindings().keySet()) { |
164 | 5038 | if (key.getTypeLiteral().getRawType().equals(type)) { |
165 | 64 | found = true; |
166 | 64 | break; |
167 | |
} |
168 | |
} |
169 | 1362 | if (!found && injector.getParent() != null) { |
170 | 1194 | return findBinding(injector.getParent(), type); |
171 | |
} |
172 | |
|
173 | 168 | return found; |
174 | |
} |
175 | |
|
176 | |
protected Injector createInjector(List<Module> modules) { |
177 | 8 | if ( injector != null ){ |
178 | 1 | return injector; |
179 | |
} |
180 | 7 | Injector root = Guice.createInjector(new AbstractModule() { |
181 | |
@Override |
182 | |
protected void configure() { |
183 | |
|
184 | 7 | } |
185 | |
}); |
186 | 7 | return root.createChildInjector(Modules.combine(modules)); |
187 | |
} |
188 | |
|
189 | |
protected Injector injector() { |
190 | 2 | return injector; |
191 | |
} |
192 | |
} |