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