Home | History | Annotate | Download | only in spi
      1 /**
      2  * Copyright (C) 2008 Google Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.google.inject.spi;
     18 
     19 import static com.google.inject.internal.MoreTypes.getRawType;
     20 
     21 import com.google.common.collect.ImmutableList;
     22 import com.google.common.collect.ImmutableSet;
     23 import com.google.common.collect.Lists;
     24 import com.google.inject.ConfigurationException;
     25 import com.google.inject.Inject;
     26 import com.google.inject.Key;
     27 import com.google.inject.TypeLiteral;
     28 import com.google.inject.internal.Annotations;
     29 import com.google.inject.internal.Errors;
     30 import com.google.inject.internal.ErrorsException;
     31 import com.google.inject.internal.Nullability;
     32 import com.google.inject.internal.util.Classes;
     33 
     34 import java.lang.annotation.Annotation;
     35 import java.lang.reflect.AnnotatedElement;
     36 import java.lang.reflect.Constructor;
     37 import java.lang.reflect.Field;
     38 import java.lang.reflect.Member;
     39 import java.lang.reflect.Method;
     40 import java.lang.reflect.Modifier;
     41 import java.util.ArrayList;
     42 import java.util.Arrays;
     43 import java.util.Collections;
     44 import java.util.HashMap;
     45 import java.util.Iterator;
     46 import java.util.List;
     47 import java.util.Map;
     48 import java.util.Set;
     49 import java.util.logging.Level;
     50 import java.util.logging.Logger;
     51 
     52 /**
     53  * A constructor, field or method that can receive injections. Typically this is a member with the
     54  * {@literal @}{@link Inject} annotation. For non-private, no argument constructors, the member may
     55  * omit the annotation.
     56  *
     57  * @author crazybob (at) google.com (Bob Lee)
     58  * @since 2.0
     59  */
     60 public final class InjectionPoint {
     61 
     62   private static final Logger logger = Logger.getLogger(InjectionPoint.class.getName());
     63 
     64   private final boolean optional;
     65   private final Member member;
     66   private final TypeLiteral<?> declaringType;
     67   private final ImmutableList<Dependency<?>> dependencies;
     68 
     69   InjectionPoint(TypeLiteral<?> declaringType, Method method, boolean optional) {
     70     this.member = method;
     71     this.declaringType = declaringType;
     72     this.optional = optional;
     73     this.dependencies = forMember(method, declaringType, method.getParameterAnnotations());
     74   }
     75 
     76   InjectionPoint(TypeLiteral<?> declaringType, Constructor<?> constructor) {
     77     this.member = constructor;
     78     this.declaringType = declaringType;
     79     this.optional = false;
     80     this.dependencies = forMember(
     81         constructor, declaringType, constructor.getParameterAnnotations());
     82   }
     83 
     84   InjectionPoint(TypeLiteral<?> declaringType, Field field, boolean optional) {
     85     this.member = field;
     86     this.declaringType = declaringType;
     87     this.optional = optional;
     88 
     89     Annotation[] annotations = field.getAnnotations();
     90 
     91     Errors errors = new Errors(field);
     92     Key<?> key = null;
     93     try {
     94       key = Annotations.getKey(declaringType.getFieldType(field), field, annotations, errors);
     95     } catch (ConfigurationException e) {
     96       errors.merge(e.getErrorMessages());
     97     } catch (ErrorsException e) {
     98       errors.merge(e.getErrors());
     99     }
    100     errors.throwConfigurationExceptionIfErrorsExist();
    101 
    102     this.dependencies = ImmutableList.<Dependency<?>>of(
    103         newDependency(key, Nullability.allowsNull(annotations), -1));
    104   }
    105 
    106   private ImmutableList<Dependency<?>> forMember(Member member, TypeLiteral<?> type,
    107       Annotation[][] paramterAnnotations) {
    108     Errors errors = new Errors(member);
    109     Iterator<Annotation[]> annotationsIterator = Arrays.asList(paramterAnnotations).iterator();
    110 
    111     List<Dependency<?>> dependencies = Lists.newArrayList();
    112     int index = 0;
    113 
    114     for (TypeLiteral<?> parameterType : type.getParameterTypes(member)) {
    115       try {
    116         Annotation[] parameterAnnotations = annotationsIterator.next();
    117         Key<?> key = Annotations.getKey(parameterType, member, parameterAnnotations, errors);
    118         dependencies.add(newDependency(key, Nullability.allowsNull(parameterAnnotations), index));
    119         index++;
    120       } catch (ConfigurationException e) {
    121         errors.merge(e.getErrorMessages());
    122       } catch (ErrorsException e) {
    123         errors.merge(e.getErrors());
    124       }
    125     }
    126 
    127     errors.throwConfigurationExceptionIfErrorsExist();
    128     return ImmutableList.copyOf(dependencies);
    129   }
    130 
    131   // This metohd is necessary to create a Dependency<T> with proper generic type information
    132   private <T> Dependency<T> newDependency(Key<T> key, boolean allowsNull, int parameterIndex) {
    133     return new Dependency<T>(this, key, allowsNull, parameterIndex);
    134   }
    135 
    136   /**
    137    * Returns the injected constructor, field, or method.
    138    */
    139   public Member getMember() {
    140     // TODO: Don't expose the original member (which probably has setAccessible(true)).
    141     return member;
    142   }
    143 
    144   /**
    145    * Returns the dependencies for this injection point. If the injection point is for a method or
    146    * constructor, the dependencies will correspond to that member's parameters. Field injection
    147    * points always have a single dependency for the field itself.
    148    *
    149    * @return a possibly-empty list
    150    */
    151   public List<Dependency<?>> getDependencies() {
    152     return dependencies;
    153   }
    154 
    155   /**
    156    * Returns true if this injection point shall be skipped if the injector cannot resolve bindings
    157    * for all required dependencies. Both explicit bindings (as specified in a module), and implicit
    158    * bindings ({@literal @}{@link com.google.inject.ImplementedBy ImplementedBy}, default
    159    * constructors etc.) may be used to satisfy optional injection points.
    160    */
    161   public boolean isOptional() {
    162     return optional;
    163   }
    164 
    165   /**
    166    * Returns true if the element is annotated with {@literal @}{@link Toolable}.
    167    *
    168    * @since 3.0
    169    */
    170   public boolean isToolable() {
    171     return ((AnnotatedElement)member).isAnnotationPresent(Toolable.class);
    172   }
    173 
    174   /**
    175    * Returns the generic type that defines this injection point. If the member exists on a
    176    * parameterized type, the result will include more type information than the member's {@link
    177    * Member#getDeclaringClass() raw declaring class}.
    178    *
    179    * @since 3.0
    180    */
    181   public TypeLiteral<?> getDeclaringType() {
    182     return declaringType;
    183   }
    184 
    185   @Override public boolean equals(Object o) {
    186     return o instanceof InjectionPoint
    187         && member.equals(((InjectionPoint) o).member)
    188         && declaringType.equals(((InjectionPoint) o).declaringType);
    189   }
    190 
    191   @Override public int hashCode() {
    192     return member.hashCode() ^ declaringType.hashCode();
    193   }
    194 
    195   @Override public String toString() {
    196     return Classes.toString(member);
    197   }
    198 
    199   /**
    200    * Returns a new injection point for the specified constructor. If the declaring type of {@code
    201    * constructor} is parameterized (such as {@code List<T>}), prefer the overload that includes a
    202    * type literal.
    203    *
    204    * @param constructor any single constructor present on {@code type}.
    205    *
    206    * @since 3.0
    207    */
    208   public static <T> InjectionPoint forConstructor(Constructor<T> constructor) {
    209     return new InjectionPoint(TypeLiteral.get(constructor.getDeclaringClass()), constructor);
    210   }
    211 
    212   /**
    213    * Returns a new injection point for the specified constructor of {@code type}.
    214    *
    215    * @param constructor any single constructor present on {@code type}.
    216    * @param type the concrete type that defines {@code constructor}.
    217    *
    218    * @since 3.0
    219    */
    220   public static <T> InjectionPoint forConstructor(
    221       Constructor<T> constructor, TypeLiteral<? extends T> type) {
    222     if (type.getRawType() != constructor.getDeclaringClass()) {
    223       new Errors(type)
    224           .constructorNotDefinedByType(constructor, type)
    225           .throwConfigurationExceptionIfErrorsExist();
    226     }
    227 
    228     return new InjectionPoint(type, constructor);
    229   }
    230 
    231   /**
    232    * Returns a new injection point for the injectable constructor of {@code type}.
    233    *
    234    * @param type a concrete type with exactly one constructor annotated {@literal @}{@link Inject},
    235    *     or a no-arguments constructor that is not private.
    236    * @throws ConfigurationException if there is no injectable constructor, more than one injectable
    237    *     constructor, or if parameters of the injectable constructor are malformed, such as a
    238    *     parameter with multiple binding annotations.
    239    */
    240   public static InjectionPoint forConstructorOf(TypeLiteral<?> type) {
    241     Class<?> rawType = getRawType(type.getType());
    242     Errors errors = new Errors(rawType);
    243 
    244     Constructor<?> injectableConstructor = null;
    245     for (Constructor<?> constructor : rawType.getDeclaredConstructors()) {
    246 
    247       boolean optional;
    248       Inject guiceInject = constructor.getAnnotation(Inject.class);
    249       if (guiceInject == null) {
    250         javax.inject.Inject javaxInject = constructor.getAnnotation(javax.inject.Inject.class);
    251         if (javaxInject == null) {
    252           continue;
    253         }
    254         optional = false;
    255       } else {
    256         optional = guiceInject.optional();
    257       }
    258 
    259       if (optional) {
    260         errors.optionalConstructor(constructor);
    261       }
    262 
    263       if (injectableConstructor != null) {
    264         errors.tooManyConstructors(rawType);
    265       }
    266 
    267       injectableConstructor = constructor;
    268       checkForMisplacedBindingAnnotations(injectableConstructor, errors);
    269     }
    270 
    271     errors.throwConfigurationExceptionIfErrorsExist();
    272 
    273     if (injectableConstructor != null) {
    274       return new InjectionPoint(type, injectableConstructor);
    275     }
    276 
    277     // If no annotated constructor is found, look for a no-arg constructor instead.
    278     try {
    279       Constructor<?> noArgConstructor = rawType.getDeclaredConstructor();
    280 
    281       // Disallow private constructors on non-private classes (unless they have @Inject)
    282       if (Modifier.isPrivate(noArgConstructor.getModifiers())
    283           && !Modifier.isPrivate(rawType.getModifiers())) {
    284         errors.missingConstructor(rawType);
    285         throw new ConfigurationException(errors.getMessages());
    286       }
    287 
    288       checkForMisplacedBindingAnnotations(noArgConstructor, errors);
    289       return new InjectionPoint(type, noArgConstructor);
    290     } catch (NoSuchMethodException e) {
    291       errors.missingConstructor(rawType);
    292       throw new ConfigurationException(errors.getMessages());
    293     }
    294   }
    295 
    296   /**
    297    * Returns a new injection point for the injectable constructor of {@code type}.
    298    *
    299    * @param type a concrete type with exactly one constructor annotated {@literal @}{@link Inject},
    300    *     or a no-arguments constructor that is not private.
    301    * @throws ConfigurationException if there is no injectable constructor, more than one injectable
    302    *     constructor, or if parameters of the injectable constructor are malformed, such as a
    303    *     parameter with multiple binding annotations.
    304    */
    305   public static InjectionPoint forConstructorOf(Class<?> type) {
    306     return forConstructorOf(TypeLiteral.get(type));
    307   }
    308 
    309   /**
    310    * Returns a new injection point for the specified method of {@code type}.
    311    * This is useful for extensions that need to build dependency graphs from
    312    * arbitrary methods.
    313    *
    314    * @param method any single method present on {@code type}.
    315    * @param type the concrete type that defines {@code method}.
    316    *
    317    * @since 4.0
    318    */
    319   public static <T> InjectionPoint forMethod(Method method, TypeLiteral<T> type) {
    320     return new InjectionPoint(type, method, false);
    321   }
    322 
    323   /**
    324    * Returns all static method and field injection points on {@code type}.
    325    *
    326    * @return a possibly empty set of injection points. The set has a specified iteration order. All
    327    *      fields are returned and then all methods. Within the fields, supertype fields are returned
    328    *      before subtype fields. Similarly, supertype methods are returned before subtype methods.
    329    * @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
    330    *      a field with multiple binding annotations. The exception's {@link
    331    *      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
    332    *      of the valid injection points.
    333    */
    334   public static Set<InjectionPoint> forStaticMethodsAndFields(TypeLiteral<?> type) {
    335     Errors errors = new Errors();
    336 
    337     Set<InjectionPoint> result;
    338 
    339     if (type.getRawType().isInterface()) {
    340       errors.staticInjectionOnInterface(type.getRawType());
    341       result = null;
    342     } else {
    343       result = getInjectionPoints(type, true, errors);
    344     }
    345 
    346     if (errors.hasErrors()) {
    347       throw new ConfigurationException(errors.getMessages()).withPartialValue(result);
    348     }
    349     return result;
    350   }
    351 
    352   /**
    353    * Returns all static method and field injection points on {@code type}.
    354    *
    355    * @return a possibly empty set of injection points. The set has a specified iteration order. All
    356    *      fields are returned and then all methods. Within the fields, supertype fields are returned
    357    *      before subtype fields. Similarly, supertype methods are returned before subtype methods.
    358    * @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
    359    *      a field with multiple binding annotations. The exception's {@link
    360    *      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
    361    *      of the valid injection points.
    362    */
    363   public static Set<InjectionPoint> forStaticMethodsAndFields(Class<?> type) {
    364     return forStaticMethodsAndFields(TypeLiteral.get(type));
    365   }
    366 
    367   /**
    368    * Returns all instance method and field injection points on {@code type}.
    369    *
    370    * @return a possibly empty set of injection points. The set has a specified iteration order. All
    371    *      fields are returned and then all methods. Within the fields, supertype fields are returned
    372    *      before subtype fields. Similarly, supertype methods are returned before subtype methods.
    373    * @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
    374    *      a field with multiple binding annotations. The exception's {@link
    375    *      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
    376    *      of the valid injection points.
    377    */
    378   public static Set<InjectionPoint> forInstanceMethodsAndFields(TypeLiteral<?> type) {
    379     Errors errors = new Errors();
    380     Set<InjectionPoint> result = getInjectionPoints(type, false, errors);
    381     if (errors.hasErrors()) {
    382       throw new ConfigurationException(errors.getMessages()).withPartialValue(result);
    383     }
    384     return result;
    385   }
    386 
    387   /**
    388    * Returns all instance method and field injection points on {@code type}.
    389    *
    390    * @return a possibly empty set of injection points. The set has a specified iteration order. All
    391    *      fields are returned and then all methods. Within the fields, supertype fields are returned
    392    *      before subtype fields. Similarly, supertype methods are returned before subtype methods.
    393    * @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
    394    *      a field with multiple binding annotations. The exception's {@link
    395    *      ConfigurationException#getPartialValue() partial value} is a {@code Set<InjectionPoint>}
    396    *      of the valid injection points.
    397    */
    398   public static Set<InjectionPoint> forInstanceMethodsAndFields(Class<?> type) {
    399     return forInstanceMethodsAndFields(TypeLiteral.get(type));
    400   }
    401 
    402   /**
    403    * Returns true if the binding annotation is in the wrong place.
    404    */
    405   private static boolean checkForMisplacedBindingAnnotations(Member member, Errors errors) {
    406     Annotation misplacedBindingAnnotation = Annotations.findBindingAnnotation(
    407         errors, member, ((AnnotatedElement) member).getAnnotations());
    408     if (misplacedBindingAnnotation == null) {
    409       return false;
    410     }
    411 
    412     // don't warn about misplaced binding annotations on methods when there's a field with the same
    413     // name. In Scala, fields always get accessor methods (that we need to ignore). See bug 242.
    414     if (member instanceof Method) {
    415       try {
    416         if (member.getDeclaringClass().getDeclaredField(member.getName()) != null) {
    417           return false;
    418         }
    419       } catch (NoSuchFieldException ignore) {
    420       }
    421     }
    422 
    423     errors.misplacedBindingAnnotation(member, misplacedBindingAnnotation);
    424     return true;
    425   }
    426 
    427   /**
    428    * Node in the doubly-linked list of injectable members (fields and methods).
    429    */
    430   static abstract class InjectableMember {
    431     final TypeLiteral<?> declaringType;
    432     final boolean optional;
    433     final boolean jsr330;
    434     InjectableMember previous;
    435     InjectableMember next;
    436 
    437     InjectableMember(TypeLiteral<?> declaringType, Annotation atInject) {
    438       this.declaringType = declaringType;
    439 
    440       if (atInject.annotationType() == javax.inject.Inject.class) {
    441         optional = false;
    442         jsr330 = true;
    443         return;
    444       }
    445 
    446       jsr330 = false;
    447       optional = ((Inject) atInject).optional();
    448     }
    449 
    450     abstract InjectionPoint toInjectionPoint();
    451   }
    452 
    453   static class InjectableField extends InjectableMember {
    454     final Field field;
    455     InjectableField(TypeLiteral<?> declaringType, Field field,
    456         Annotation atInject) {
    457       super(declaringType, atInject);
    458       this.field = field;
    459     }
    460 
    461     @Override
    462     InjectionPoint toInjectionPoint() {
    463       return new InjectionPoint(declaringType, field, optional);
    464     }
    465   }
    466 
    467   static class InjectableMethod extends InjectableMember {
    468     final Method method;
    469     /**
    470      * true if this method overrode a method that was annotated
    471      * with com.google.inject.Inject.  used to allow different
    472      * override behavior for guice inject vs javax.inject.Inject
    473      */
    474     boolean overrodeGuiceInject;
    475     InjectableMethod(TypeLiteral<?> declaringType, Method method,
    476         Annotation atInject) {
    477       super(declaringType, atInject);
    478       this.method = method;
    479     }
    480 
    481     @Override
    482     InjectionPoint toInjectionPoint() {
    483       return new InjectionPoint(declaringType, method, optional);
    484     }
    485 
    486     public boolean isFinal() {
    487       return Modifier.isFinal(method.getModifiers());
    488     }
    489   }
    490 
    491   static Annotation getAtInject(AnnotatedElement member) {
    492     Annotation a = member.getAnnotation(javax.inject.Inject.class);
    493     return a == null ? member.getAnnotation(Inject.class) : a;
    494   }
    495 
    496   /**
    497    * Linked list of injectable members.
    498    */
    499   static class InjectableMembers {
    500     InjectableMember head;
    501     InjectableMember tail;
    502 
    503     void add(InjectableMember member) {
    504       if (head == null) {
    505         head = tail = member;
    506       } else {
    507         member.previous = tail;
    508         tail.next = member;
    509         tail = member;
    510       }
    511     }
    512 
    513     void remove(InjectableMember member) {
    514       if (member.previous != null) {
    515         member.previous.next = member.next;
    516       }
    517       if (member.next != null) {
    518         member.next.previous = member.previous;
    519       }
    520       if (head == member) {
    521         head = member.next;
    522       }
    523       if (tail == member) {
    524         tail = member.previous;
    525       }
    526     }
    527 
    528     boolean isEmpty() {
    529       return head == null;
    530     }
    531   }
    532 
    533   /** Position in type hierarchy. */
    534   enum Position {
    535     TOP, // No need to check for overridden methods
    536     MIDDLE,
    537     BOTTOM // Methods won't be overridden
    538   }
    539 
    540   /**
    541    * Keeps track of injectable methods so we can remove methods that get overridden in O(1) time.
    542    * Uses our position in the type hierarchy to perform optimizations.
    543    */
    544   static class OverrideIndex {
    545     final InjectableMembers injectableMembers;
    546     Map<Signature, List<InjectableMethod>> bySignature;
    547     Position position = Position.TOP;
    548 
    549     OverrideIndex(InjectableMembers injectableMembers) {
    550       this.injectableMembers = injectableMembers;
    551     }
    552 
    553     /* Caches the signature for the last method. */
    554     Method lastMethod;
    555     Signature lastSignature;
    556 
    557     /**
    558      * Removes a method overridden by the given method, if present. In order to
    559      * remain backwards compatible with prior Guice versions, this will *not*
    560      * remove overridden methods if 'alwaysRemove' is false and the overridden
    561      * signature was annotated with a com.google.inject.Inject.
    562      *
    563      * @param method
    564      *          The method used to determine what is overridden and should be
    565      *          removed.
    566      * @param alwaysRemove
    567      *          true if overridden methods should be removed even if they were
    568      *          guice @Inject
    569      * @param injectableMethod
    570      *          if this method overrode any guice @Inject methods,
    571      *          {@link InjectableMethod#overrodeGuiceInject} is set to true
    572      */
    573     boolean removeIfOverriddenBy(Method method, boolean alwaysRemove,
    574         InjectableMethod injectableMethod) {
    575       if (position == Position.TOP) {
    576         // If we're at the top of the hierarchy, there's nothing to override.
    577         return false;
    578       }
    579 
    580       if (bySignature == null) {
    581         // We encountered a method in a subclass. Time to index the
    582         // methods in the parent class.
    583         bySignature = new HashMap<Signature, List<InjectableMethod>>();
    584         for (InjectableMember member = injectableMembers.head; member != null;
    585             member = member.next) {
    586           if (!(member instanceof InjectableMethod)) continue;
    587           InjectableMethod im = (InjectableMethod) member;
    588           if (im.isFinal()) continue;
    589           List<InjectableMethod> methods = new ArrayList<InjectableMethod>();
    590           methods.add(im);
    591           bySignature.put(new Signature(im.method), methods);
    592         }
    593       }
    594 
    595       lastMethod = method;
    596       Signature signature = lastSignature = new Signature(method);
    597       List<InjectableMethod> methods = bySignature.get(signature);
    598       boolean removed = false;
    599       if (methods != null) {
    600         for (Iterator<InjectableMethod> iterator = methods.iterator();
    601             iterator.hasNext();) {
    602           InjectableMethod possiblyOverridden = iterator.next();
    603           if (overrides(method, possiblyOverridden.method)) {
    604             boolean wasGuiceInject =
    605               !possiblyOverridden.jsr330 || possiblyOverridden.overrodeGuiceInject;
    606             if(injectableMethod != null) {
    607               injectableMethod.overrodeGuiceInject = wasGuiceInject;
    608             }
    609             // Only actually remove the methods if we want to force
    610             // remove or if the signature never specified @com.google.inject.Inject
    611             // somewhere.
    612             if(alwaysRemove || !wasGuiceInject) {
    613               removed = true;
    614               iterator.remove();
    615               injectableMembers.remove(possiblyOverridden);
    616             }
    617           }
    618         }
    619       }
    620       return removed;
    621     }
    622 
    623     /**
    624      * Adds the given method to the list of injection points. Keeps track of it in this index
    625      * in case it gets overridden.
    626      */
    627     void add(InjectableMethod injectableMethod) {
    628       injectableMembers.add(injectableMethod);
    629       if (position == Position.BOTTOM
    630           || injectableMethod.isFinal()) {
    631         // This method can't be overridden, so there's no need to index it.
    632         return;
    633       }
    634       if (bySignature != null) {
    635         // Try to reuse the signature we created during removal
    636         Signature signature = injectableMethod.method == lastMethod
    637             ? lastSignature : new Signature(injectableMethod.method);
    638         List<InjectableMethod> methods = bySignature.get(signature);
    639         if (methods == null) {
    640           methods = new ArrayList<InjectableMethod>();
    641           bySignature.put(signature, methods);
    642         }
    643         methods.add(injectableMethod);
    644       }
    645     }
    646   }
    647 
    648   /**
    649    * Returns an ordered, immutable set of injection points for the given type. Members in
    650    * superclasses come before members in subclasses. Within a class, fields come before methods.
    651    * Overridden methods are filtered out.
    652    *
    653    * @param statics true is this method should return static members, false for instance members
    654    * @param errors used to record errors
    655    */
    656   private static Set<InjectionPoint> getInjectionPoints(final TypeLiteral<?> type,
    657       boolean statics, Errors errors) {
    658     InjectableMembers injectableMembers = new InjectableMembers();
    659     OverrideIndex overrideIndex = null;
    660 
    661     List<TypeLiteral<?>> hierarchy = hierarchyFor(type);
    662     int topIndex = hierarchy.size() - 1;
    663     for (int i = topIndex; i >= 0; i--) {
    664       if (overrideIndex != null && i < topIndex) {
    665         // Knowing the position within the hierarchy helps us make optimizations.
    666         if (i == 0) {
    667           overrideIndex.position = Position.BOTTOM;
    668         } else {
    669           overrideIndex.position = Position.MIDDLE;
    670         }
    671       }
    672 
    673       TypeLiteral<?> current = hierarchy.get(i);
    674 
    675       for (Field field : current.getRawType().getDeclaredFields()) {
    676         if (Modifier.isStatic(field.getModifiers()) == statics) {
    677           Annotation atInject = getAtInject(field);
    678           if (atInject != null) {
    679             InjectableField injectableField = new InjectableField(current, field, atInject);
    680             if (injectableField.jsr330 && Modifier.isFinal(field.getModifiers())) {
    681               errors.cannotInjectFinalField(field);
    682             }
    683             injectableMembers.add(injectableField);
    684           }
    685         }
    686       }
    687 
    688       for (Method method : current.getRawType().getDeclaredMethods()) {
    689         if (isEligibleForInjection(method, statics)) {
    690           Annotation atInject = getAtInject(method);
    691           if (atInject != null) {
    692             InjectableMethod injectableMethod = new InjectableMethod(
    693                 current, method, atInject);
    694             if (checkForMisplacedBindingAnnotations(method, errors)
    695                 || !isValidMethod(injectableMethod, errors)) {
    696               if (overrideIndex != null) {
    697                 boolean removed = overrideIndex.removeIfOverriddenBy(method, false, injectableMethod);
    698                 if(removed) {
    699                   logger.log(Level.WARNING, "Method: {0} is not a valid injectable method ("
    700                       + "because it either has misplaced binding annotations "
    701                       + "or specifies type parameters) but is overriding a method that is valid. "
    702                       + "Because it is not valid, the method will not be injected. "
    703                       + "To fix this, make the method a valid injectable method.", method);
    704                 }
    705               }
    706               continue;
    707             }
    708             if (statics) {
    709               injectableMembers.add(injectableMethod);
    710             } else {
    711               if (overrideIndex == null) {
    712                 /*
    713                  * Creating the override index lazily means that the first type in the hierarchy
    714                  * with injectable methods (not necessarily the top most type) will be treated as
    715                  * the TOP position and will enjoy the same optimizations (no checks for overridden
    716                  * methods, etc.).
    717                  */
    718                 overrideIndex = new OverrideIndex(injectableMembers);
    719               } else {
    720                 // Forcibly remove the overriden method, otherwise we'll inject
    721                 // it twice.
    722                 overrideIndex.removeIfOverriddenBy(method, true, injectableMethod);
    723               }
    724               overrideIndex.add(injectableMethod);
    725             }
    726           } else {
    727             if(overrideIndex != null) {
    728               boolean removed = overrideIndex.removeIfOverriddenBy(method, false, null);
    729               if(removed) {
    730                 logger.log(Level.WARNING, "Method: {0} is not annotated with @Inject but "
    731                     + "is overriding a method that is annotated with @javax.inject.Inject.  Because "
    732                     + "it is not annotated with @Inject, the method will not be injected. "
    733                     + "To fix this, annotate the method with @Inject.", method);
    734               }
    735             }
    736           }
    737         }
    738       }
    739     }
    740 
    741     if (injectableMembers.isEmpty()) {
    742       return Collections.emptySet();
    743     }
    744 
    745     ImmutableSet.Builder<InjectionPoint> builder = ImmutableSet.builder();
    746     for (InjectableMember im = injectableMembers.head; im != null;
    747         im = im.next) {
    748       try {
    749         builder.add(im.toInjectionPoint());
    750       } catch (ConfigurationException ignorable) {
    751         if (!im.optional) {
    752           errors.merge(ignorable.getErrorMessages());
    753         }
    754       }
    755     }
    756     return builder.build();
    757   }
    758 
    759   /**
    760    * Returns true if the method is eligible to be injected.  This is different than
    761    * {@link #isValidMethod}, because ineligibility will not drop a method
    762    * from being injected if a superclass was eligible & valid.
    763    * Bridge & synthetic methods are excluded from eligibility for two reasons:
    764    *
    765    * <p>Prior to Java8, javac would generate these methods in subclasses without
    766    * annotations, which means this would accidentally stop injecting a method
    767    * annotated with {@link javax.inject.Inject}, since the spec says to stop
    768    * injecting if a subclass isn't annotated with it.
    769    *
    770    * <p>Starting at Java8, javac copies the annotations to the generated subclass
    771    * method, except it leaves out the generic types.  If this considered it a valid
    772    * injectable method, this would eject the parent's overridden method that had the
    773    * proper generic types, and would use invalid injectable parameters as a result.
    774    *
    775    * <p>The fix for both is simply to ignore these synthetic bridge methods.
    776    */
    777   private static boolean isEligibleForInjection(Method method, boolean statics) {
    778     return Modifier.isStatic(method.getModifiers()) == statics
    779         && !method.isBridge()
    780         && !method.isSynthetic();
    781   }
    782 
    783   private static boolean isValidMethod(InjectableMethod injectableMethod,
    784       Errors errors) {
    785     boolean result = true;
    786     if (injectableMethod.jsr330) {
    787       Method method = injectableMethod.method;
    788       if (Modifier.isAbstract(method.getModifiers())) {
    789         errors.cannotInjectAbstractMethod(method);
    790         result = false;
    791       }
    792       if (method.getTypeParameters().length > 0) {
    793         errors.cannotInjectMethodWithTypeParameters(method);
    794         result = false;
    795       }
    796     }
    797     return result;
    798   }
    799 
    800   private static List<TypeLiteral<?>> hierarchyFor(TypeLiteral<?> type) {
    801     List<TypeLiteral<?>> hierarchy = new ArrayList<TypeLiteral<?>>();
    802     TypeLiteral<?> current = type;
    803     while (current.getRawType() != Object.class) {
    804       hierarchy.add(current);
    805       current = current.getSupertype(current.getRawType().getSuperclass());
    806     }
    807     return hierarchy;
    808   }
    809 
    810   /**
    811    * Returns true if a overrides b. Assumes signatures of a and b are the same and a's declaring
    812    * class is a subclass of b's declaring class.
    813    */
    814   private static boolean overrides(Method a, Method b) {
    815     // See JLS section 8.4.8.1
    816     int modifiers = b.getModifiers();
    817     if (Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers)) {
    818       return true;
    819     }
    820     if (Modifier.isPrivate(modifiers)) {
    821       return false;
    822     }
    823     // b must be package-private
    824     return a.getDeclaringClass().getPackage().equals(b.getDeclaringClass().getPackage());
    825   }
    826 
    827   /**
    828    * A method signature. Used to handle method overridding.
    829    */
    830   static class Signature {
    831 
    832     final String name;
    833     final Class[] parameterTypes;
    834     final int hash;
    835 
    836     Signature(Method method) {
    837       this.name = method.getName();
    838       this.parameterTypes = method.getParameterTypes();
    839 
    840       int h = name.hashCode();
    841       h = h * 31 + parameterTypes.length;
    842       for (Class parameterType : parameterTypes) {
    843         h = h * 31 + parameterType.hashCode();
    844       }
    845       this.hash = h;
    846     }
    847 
    848     @Override public int hashCode() {
    849       return this.hash;
    850     }
    851 
    852     @Override public boolean equals(Object o) {
    853       if (!(o instanceof Signature)) {
    854         return false;
    855       }
    856 
    857       Signature other = (Signature) o;
    858       if (!name.equals(other.name)) {
    859         return false;
    860       }
    861 
    862       if (parameterTypes.length != other.parameterTypes.length) {
    863         return false;
    864       }
    865 
    866       for (int i = 0; i < parameterTypes.length; i++) {
    867         if (parameterTypes[i] != other.parameterTypes[i]) {
    868           return false;
    869         }
    870       }
    871 
    872       return true;
    873     }
    874   }
    875 }
    876