View Javadoc
1   package org.apache.onami.lifecycle.core;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import com.google.inject.AbstractModule;
23  import com.google.inject.ProvisionException;
24  import com.google.inject.TypeLiteral;
25  import com.google.inject.matcher.Matcher;
26  import com.google.inject.spi.InjectionListener;
27  import com.google.inject.spi.TypeEncounter;
28  
29  import java.lang.annotation.Annotation;
30  import java.lang.reflect.InvocationTargetException;
31  import java.lang.reflect.Method;
32  import java.util.List;
33  
34  import static com.google.inject.matcher.Matchers.any;
35  import static java.lang.String.format;
36  import static java.util.Arrays.asList;
37  
38  /**
39   * Guice module to register methods to be invoked after injection is complete.
40   */
41  public abstract class LifeCycleModule
42      extends AbstractModule
43  {
44  
45      /**
46       * Binds lifecycle listener.
47       *
48       * @param annotation the lifecycle annotation to be searched.
49       */
50      protected final void bindLifeCycle( Class<? extends Annotation> annotation )
51      {
52          bindLifeCycle( annotation, any() );
53      }
54  
55      /**
56       * Binds lifecycle listener.
57       *
58       * @param annotation  the lifecycle annotation to be searched.
59       * @param typeMatcher the filter for injectee types.
60       */
61      protected final void bindLifeCycle( Class<? extends Annotation> annotation, Matcher<? super TypeLiteral<?>> typeMatcher )
62      {
63          bindLifeCycle( asList( annotation ), typeMatcher );
64      }
65  
66      /**
67       * Binds lifecycle listener.
68       *
69       * @param annotations  the lifecycle annotations to be searched in the order to be searched.
70       * @param typeMatcher the filter for injectee types.
71       */
72      protected final void bindLifeCycle( List<? extends Class<? extends Annotation>> annotations, Matcher<? super TypeLiteral<?>> typeMatcher )
73      {
74          bindListener( typeMatcher, new AbstractMethodTypeListener( annotations )
75          {
76  
77              @Override
78              protected <I> void hear( final Method method, TypeLiteral<I> parentType, TypeEncounter<I> encounter,
79                                       final Class<? extends Annotation> annotationType )
80              {
81                  encounter.register( new InjectionListener<I>()
82                  {
83  
84                      @Override
85                      public void afterInjection( I injectee )
86                      {
87                          try
88                          {
89                              method.invoke( injectee );
90                          }
91                          catch ( IllegalArgumentException e )
92                          {
93                              // should not happen, anyway...
94                              throw new ProvisionException(
95                                  format( "Method @%s %s requires arguments", annotationType.getName(), method ), e );
96                          }
97                          catch ( IllegalAccessException e )
98                          {
99                              throw new ProvisionException(
100                                 format( "Impossible to access to @%s %s on %s", annotationType.getName(), method,
101                                         injectee ), e );
102                         }
103                         catch ( InvocationTargetException e )
104                         {
105                             throw new ProvisionException(
106                                 format( "An error occurred while invoking @%s %s on %s", annotationType.getName(),
107                                         method, injectee ), e.getCause() );
108                         }
109                     }
110 
111                 } );
112             }
113 
114         } );
115     }
116 
117 }