View Javadoc

1   package org.apache.onami.autobind.scanner.features;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one or more
5    * contributor license agreements.  See the NOTICE file distributed with
6    * this work for additional information regarding copyright ownership.
7    * The ASF licenses this file to You under the Apache License, Version 2.0
8    * (the "License"); you may not use this file except in compliance with
9    * the License.  You may obtain a copy of the License at
10   *
11   *  http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
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   * Default Implementation for Annotation Listeners, which should stay informed
57   * abbout found annotated classes. Due the fact, that we need the Binder of the
58   * Child Injector, it will be set at runtime by the {@link ScannerModule}.
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 }