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@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 InjectionPoint(TypeLiteral<?> declaringType, Method method, boolean optional)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 InjectionPoint(TypeLiteral<?> declaringType, Constructor<?> constructor)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 InjectionPoint(TypeLiteral<?> declaringType, Field field, boolean optional)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 forMember( Member member, TypeLiteral<?> type, Annotation[][] paramterAnnotations)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 newDependency(Key<T> key, boolean allowsNull, int parameterIndex)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. */ getMember()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 */ getDependencies()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 */ isOptional()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 */ isToolable()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 */ getDeclaringType()180 public TypeLiteral<?> getDeclaringType() { 181 return declaringType; 182 } 183 184 @Override equals(Object o)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 hashCode()192 public int hashCode() { 193 return member.hashCode() ^ declaringType.hashCode(); 194 } 195 196 @Override toString()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 */ forConstructor(Constructor<T> constructor)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 */ forConstructor( Constructor<T> constructor, TypeLiteral<? extends T> type)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 */ forConstructorOf(TypeLiteral<?> type)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 */ forConstructorOf(Class<?> type)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 */ forMethod(Method method, TypeLiteral<T> type)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 */ forStaticMethodsAndFields(TypeLiteral<?> type)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 */ forStaticMethodsAndFields(Class<?> type)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 */ forInstanceMethodsAndFields(TypeLiteral<?> type)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 */ forInstanceMethodsAndFields(Class<?> type)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. */ checkForMisplacedBindingAnnotations(Member member, Errors errors)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 InjectableMember(TypeLiteral<?> declaringType, Annotation atInject)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 toInjectionPoint()445 abstract InjectionPoint toInjectionPoint(); 446 } 447 448 static class InjectableField extends InjectableMember { 449 final Field field; 450 InjectableField(TypeLiteral<?> declaringType, Field field, Annotation atInject)451 InjectableField(TypeLiteral<?> declaringType, Field field, Annotation atInject) { 452 super(declaringType, atInject); 453 this.field = field; 454 } 455 456 @Override toInjectionPoint()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 InjectableMethod(TypeLiteral<?> declaringType, Method method, Annotation atInject)470 InjectableMethod(TypeLiteral<?> declaringType, Method method, Annotation atInject) { 471 super(declaringType, atInject); 472 this.method = method; 473 } 474 475 @Override toInjectionPoint()476 InjectionPoint toInjectionPoint() { 477 return new InjectionPoint(declaringType, method, optional); 478 } 479 isFinal()480 public boolean isFinal() { 481 return Modifier.isFinal(method.getModifiers()); 482 } 483 } 484 getAtInject(AnnotatedElement member)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 add(InjectableMember member)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 remove(InjectableMember member)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 isEmpty()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 OverrideIndex(InjectableMembers injectableMembers)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 */ removeIfOverriddenBy( Method method, boolean alwaysRemove, InjectableMethod injectableMethod)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 */ add(InjectableMethod injectableMethod)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 */ getInjectionPoints( final TypeLiteral<?> type, boolean statics, Errors errors)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 getDeclaredFields(TypeLiteral<?> type)759 private static Field[] getDeclaredFields(TypeLiteral<?> type) { 760 Field[] fields = type.getRawType().getDeclaredFields(); 761 Arrays.sort(fields, FIELD_ORDERING); 762 return fields; 763 } 764 getDeclaredMethods(TypeLiteral<?> type)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 */ isEligibleForInjection(Method method, boolean statics)841 private static boolean isEligibleForInjection(Method method, boolean statics) { 842 return Modifier.isStatic(method.getModifiers()) == statics 843 && !method.isBridge() 844 && !method.isSynthetic(); 845 } 846 isValidMethod(InjectableMethod injectableMethod, Errors errors)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 hierarchyFor(TypeLiteral<?> type)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 */ overrides(Method a, Method b)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 Signature(Method method)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 hashCode()910 public int hashCode() { 911 return this.hash; 912 } 913 914 @Override equals(Object o)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