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.TypeLiteral;
23  import com.google.inject.spi.TypeEncounter;
24  import com.google.inject.spi.TypeListener;
25  
26  import java.lang.annotation.Annotation;
27  import java.lang.reflect.Method;
28  import java.util.List;
29  
30  /**
31   * A Guice {@code TypeListener} to hear annotated methods with lifecycle annotations.
32   */
33  abstract class AbstractMethodTypeListener
34      implements TypeListener
35  {
36  
37      /**
38       * The {@code java} package constants.
39       */
40      private static final String JAVA_PACKAGE = "java";
41  
42      /**
43       * The lifecycle annotations to search on methods in the order to be searched.
44       */
45      protected final List<? extends Class<? extends Annotation>> annotationTypes;
46  
47      /**
48       * Creates a new methods listener instance.
49       *
50       * @param annotationTypes the lifecycle annotations to search on methods in the order to be searched.
51       */
52      public AbstractMethodTypeListener( List<? extends Class<? extends Annotation>> annotationTypes )
53      {
54          this.annotationTypes = annotationTypes;
55      }
56  
57      /**
58       * {@inheritDoc}
59       */
60      @Override
61      public final <I> void hear( TypeLiteral<I> type, TypeEncounter<I> encounter )
62      {
63          hear( type, type.getRawType(), encounter );
64      }
65  
66      /**
67       * Allows traverse the input klass hierarchy.
68       *
69       * @param parentType the owning type being heard
70       * @param klass      encountered by Guice.
71       * @param encounter  the injection context.
72       */
73      private <I> void hear( final TypeLiteral<I> parentType, Class<? super I> klass, TypeEncounter<I> encounter )
74      {
75          Package pkg;
76          if ( klass == null || ( ( pkg = klass.getPackage() ) != null && pkg.getName().startsWith( JAVA_PACKAGE ) ) )
77          {
78              return;
79          }
80  
81          for ( Class<? extends Annotation> annotationType : annotationTypes )
82          {
83              for ( Method method : klass.getDeclaredMethods() )
84              {
85                  if ( method.isAnnotationPresent( annotationType ) )
86                  {
87                      if ( method.getParameterTypes().length != 0 )
88                      {
89                          encounter.addError( "Annotated methods with @%s must not accept any argument, found %s",
90                                              annotationType.getName(), method );
91                      }
92  
93                      hear( method, parentType, encounter, annotationType );
94                  }
95              }
96          }
97  
98          hear( parentType, klass.getSuperclass(), encounter );
99      }
100 
101     /**
102      * Allows implementations to define the behavior when lifecycle annotation is found on the method.
103      *
104      * @param method         encountered by this type handler.
105      * @param parentType     the owning type being heard
106      * @param encounter      the injection context.
107      * @param annotationType the annotation type that was specified.
108      */
109     protected abstract <I> void hear( Method method, TypeLiteral<I> parentType, TypeEncounter<I> encounter,
110                                       Class<? extends Annotation> annotationType );
111 
112 }