1 package org.apache.onami.autobind.scanner.features;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 import static java.lang.String.format;
21 import static java.util.logging.Level.FINE;
22 import static java.util.logging.Level.INFO;
23 import static java.util.logging.Logger.getLogger;
24
25 import java.lang.annotation.Annotation;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.Map;
29 import java.util.Set;
30 import java.util.logging.Logger;
31
32 import javax.inject.Inject;
33 import javax.inject.Provider;
34
35 import org.apache.onami.autobind.install.BindingStage;
36 import org.apache.onami.autobind.install.BindingTracer;
37 import org.apache.onami.autobind.install.InstallationContext;
38 import org.apache.onami.autobind.install.InstallationContext.StageableRequest;
39 import org.apache.onami.autobind.install.bindjob.BindingJob;
40 import org.apache.onami.autobind.install.bindjob.ConstantBindingJob;
41 import org.apache.onami.autobind.install.bindjob.ImplementationBindingJob;
42 import org.apache.onami.autobind.install.bindjob.InstanceBindingJob;
43 import org.apache.onami.autobind.install.bindjob.InterfaceBindingJob;
44 import org.apache.onami.autobind.install.bindjob.ProviderBindingJob;
45 import org.apache.onami.autobind.scanner.ScannerModule;
46 import org.apache.onami.autobind.utils.VariableResolver;
47
48 import com.google.inject.Binder;
49 import com.google.inject.Injector;
50 import com.google.inject.binder.AnnotatedBindingBuilder;
51 import com.google.inject.binder.LinkedBindingBuilder;
52 import com.google.inject.binder.ScopedBindingBuilder;
53 import com.google.inject.util.Providers;
54
55
56
57
58
59
60 public abstract class BindingScannerFeature
61 implements ScannerFeature
62 {
63
64 private final Logger _logger = getLogger( getClass().getName() );
65
66 protected Set<String> others = new HashSet<String>();
67
68 protected Set<String> qualifiers = new HashSet<String>();
69
70 protected Binder _binder;
71
72 @Inject
73 protected Injector injector;
74
75 @Inject
76 protected BindingTracer tracer;
77
78 @Inject
79 protected VariableResolver resolver;
80
81 protected InstallationContext context;
82
83 public void setBinder( Binder binder )
84 {
85 _binder = binder;
86 }
87
88 @Inject
89 public void configure( InstallationContext context )
90 {
91 this.context = context;
92 }
93
94 @Override
95 public void found( final Class<Object> annotatedClass, final Map<String, Annotation> annotations )
96 {
97 final BindingStage stage = accept( annotatedClass, annotations );
98 if ( stage != BindingStage.IGNORE )
99 {
100 context.add( new StageableRequest()
101 {
102 private Class<Object> _annotatedClass = annotatedClass;
103
104 private Map<String, Annotation> _annotations = new HashMap<String, Annotation>( annotations );
105
106 @Override
107 public Void call()
108 throws Exception
109 {
110 process( _annotatedClass, _annotations );
111 return null;
112 }
113
114 @Override
115 public BindingStage getExecutionStage()
116 {
117 return stage;
118 }
119 } );
120 }
121 }
122
123 public abstract BindingStage accept( Class<Object> annotatedClass, Map<String, Annotation> annotations );
124
125 public abstract void process( Class<Object> annotatedClass, Map<String, Annotation> annotations );
126
127 protected <T, V extends T> void bindProvider( final Provider<V> provider, Class<T> interf, Annotation annotation,
128 Class<? extends Annotation> scope )
129 {
130 BindingJob job = new ProviderBindingJob( scope, provider.getClass(), annotation, interf.getName() );
131 if ( !tracer.contains( job ) )
132 {
133 LinkedBindingBuilder<T> builder;
134 synchronized ( _binder )
135 {
136 builder = _binder.bind( interf );
137 if ( annotation != null )
138 {
139 builder = ( (AnnotatedBindingBuilder<T>) builder ).annotatedWith( annotation );
140 }
141 ScopedBindingBuilder scopedBuilder = builder.toProvider( Providers.guicify( provider ) );
142 if ( scope != null )
143 {
144 scopedBuilder.in( scope );
145 }
146 }
147 tracer.add( job );
148 }
149 else
150 {
151 String message = format( "Ignoring BindingJob \"%s\", because it was already bound.", job );
152
153 if ( _logger.isLoggable( FINE ) )
154 {
155 _logger.log( FINE, message, new Exception( message ) );
156 }
157 else if ( _logger.isLoggable( INFO ) )
158 {
159 _logger.log( INFO, message );
160 }
161 }
162 }
163
164 protected <T, V extends T> void bindProvider( final Class<? extends Provider<V>> provider, Class<T> interf,
165 Annotation annotation, Class<? extends Annotation> scope )
166 {
167 BindingJob job = new ProviderBindingJob( scope, provider, annotation, interf.getName() );
168 if ( !tracer.contains( job ) )
169 {
170 LinkedBindingBuilder<T> builder;
171 synchronized ( _binder )
172 {
173 builder = _binder.bind( interf );
174 if ( annotation != null )
175 {
176 builder = ( (AnnotatedBindingBuilder<T>) builder ).annotatedWith( annotation );
177 }
178 ScopedBindingBuilder scopedBuilder = builder.toProvider( provider );
179 if ( scope != null )
180 {
181 scopedBuilder.in( scope );
182 }
183 }
184 tracer.add( job );
185 }
186 else
187 {
188 String message = format( "Ignoring BindingJob \"%s\", because it was already bound.", job );
189
190 if ( _logger.isLoggable( FINE ) )
191 {
192 _logger.log( FINE, message, new Exception( message ) );
193 }
194 else if ( _logger.isLoggable( INFO ) )
195 {
196 _logger.log( INFO, message );
197 }
198 }
199 }
200
201 protected <T, V extends T> void bindInstance( V implementation, Class<T> interf, Annotation annotation,
202 Class<? extends Annotation> scope )
203 {
204 BindingJob job =
205 new InstanceBindingJob( scope, annotation, implementation.getClass().getName(), interf.getName() );
206
207 if ( !tracer.contains( job ) )
208 {
209 LinkedBindingBuilder<T> builder;
210 synchronized ( _binder )
211 {
212 builder = _binder.bind( interf );
213 if ( annotation != null )
214 {
215 builder = ( (AnnotatedBindingBuilder<T>) builder ).annotatedWith( annotation );
216 }
217 builder.toInstance( implementation );
218 }
219 tracer.add( job );
220 }
221 else
222 {
223 String message = format( "Ignoring BindingJob \"%s\", because it was already bound.", job );
224
225 if ( _logger.isLoggable( FINE ) )
226 {
227 _logger.log( FINE, message, new Exception( message ) );
228 }
229 else if ( _logger.isLoggable( INFO ) )
230 {
231 _logger.log( INFO, message );
232 }
233 }
234 }
235
236 protected void bindConstant( String value, Annotation annotation )
237 {
238 BindingJob job = new ConstantBindingJob( annotation, value.getClass().getName() );
239 if ( !tracer.contains( job ) )
240 {
241 synchronized ( _binder )
242 {
243 _binder.bindConstant().annotatedWith( annotation ).to( value );
244 }
245 tracer.add( job );
246 }
247 else
248 {
249 String message = format( "Ignoring BindingJob \"%s\", because it was already bound.", job );
250
251 if ( _logger.isLoggable( FINE ) )
252 {
253 _logger.log( FINE, message, new Exception( message ) );
254 }
255 else if ( _logger.isLoggable( INFO ) )
256 {
257 _logger.log( INFO, message );
258 }
259 }
260 }
261
262 protected <T, V extends T> void bind( Class<V> implementationClass, Class<T> interf, Annotation annotation,
263 Class<? extends Annotation> scope )
264 {
265 BindingJob job = new InterfaceBindingJob( scope, annotation, implementationClass.getName(), interf.getName() );
266
267 if ( !tracer.contains( job ) )
268 {
269 LinkedBindingBuilder<T> builder;
270 synchronized ( _binder )
271 {
272 builder = _binder.bind( interf );
273 if ( annotation != null )
274 {
275 builder = ( (AnnotatedBindingBuilder<T>) builder ).annotatedWith( annotation );
276 }
277 ScopedBindingBuilder scopedBindingBuilder = builder.to( implementationClass );
278 if ( scope != null )
279 {
280 scopedBindingBuilder.in( scope );
281 }
282 }
283 tracer.add( job );
284 }
285 else
286 {
287 String message = format( "Ignoring BindingJob \"%s\", because it was already bound.", job );
288
289 if ( _logger.isLoggable( FINE ) )
290 {
291 _logger.log( FINE, message, new Exception( message ) );
292 }
293 else if ( _logger.isLoggable( INFO ) )
294 {
295 _logger.log( INFO, message );
296 }
297 }
298 }
299
300 protected <T> void bind( Class<T> implementationClass, Annotation annotation, Class<? extends Annotation> scope )
301 {
302 BindingJob job = new ImplementationBindingJob( scope, annotation, implementationClass.getName() );
303
304 if ( !tracer.contains( job ) )
305 {
306 LinkedBindingBuilder<T> builder;
307 synchronized ( _binder )
308 {
309 builder = _binder.bind( implementationClass );
310 if ( annotation != null )
311 {
312 builder = ( (AnnotatedBindingBuilder<T>) builder ).annotatedWith( annotation );
313 }
314 if ( scope != null )
315 {
316 builder.in( scope );
317 }
318 }
319 tracer.add( job );
320 }
321 else
322 {
323 String message = format( "Ignoring BindingJob \"%s\", because it was already bound.", job );
324
325 if ( _logger.isLoggable( FINE ) )
326 {
327 _logger.log( FINE, message, new Exception( message ) );
328 }
329 else if ( _logger.isLoggable( INFO ) )
330 {
331 _logger.log( INFO, message );
332 }
333 }
334 }
335
336 }