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
17package com.google.inject.spi;
18
19import static com.google.inject.internal.MoreTypes.getRawType;
20
21import com.google.common.collect.ImmutableList;
22import com.google.common.collect.ImmutableSet;
23import com.google.common.collect.Lists;
24import com.google.inject.ConfigurationException;
25import com.google.inject.Inject;
26import com.google.inject.Key;
27import com.google.inject.TypeLiteral;
28import com.google.inject.internal.Annotations;
29import com.google.inject.internal.Errors;
30import com.google.inject.internal.ErrorsException;
31import com.google.inject.internal.Nullability;
32import com.google.inject.internal.util.Classes;
33
34import java.lang.annotation.Annotation;
35import java.lang.reflect.AnnotatedElement;
36import java.lang.reflect.Constructor;
37import java.lang.reflect.Field;
38import java.lang.reflect.Member;
39import java.lang.reflect.Method;
40import java.lang.reflect.Modifier;
41import java.util.ArrayList;
42import java.util.Arrays;
43import java.util.Collections;
44import java.util.HashMap;
45import java.util.Iterator;
46import java.util.List;
47import java.util.Map;
48import java.util.Set;
49import java.util.logging.Level;
50import 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@google.com (Bob Lee)
58 * @since 2.0
59 */
60public 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