1 16 17 package com.google.inject; 18 19 import com.google.inject.spi.SourceProviders; 20 import com.google.inject.util.GuiceFastClass; 21 import com.google.inject.util.Objects; 22 import com.google.inject.util.ReferenceCache; 23 import com.google.inject.util.StackTraceElements; 24 import com.google.inject.util.Strings; 25 import com.google.inject.util.ToStringBuilder; 26 import java.lang.annotation.Annotation ; 27 import java.lang.reflect.AccessibleObject ; 28 import java.lang.reflect.AnnotatedElement ; 29 import java.lang.reflect.Constructor ; 30 import java.lang.reflect.Field ; 31 import java.lang.reflect.InvocationTargetException ; 32 import java.lang.reflect.Member ; 33 import java.lang.reflect.Method ; 34 import java.lang.reflect.Modifier ; 35 import java.lang.reflect.ParameterizedType ; 36 import java.lang.reflect.Type ; 37 import java.util.ArrayList ; 38 import java.util.Arrays ; 39 import java.util.Collections ; 40 import java.util.HashMap ; 41 import java.util.Iterator ; 42 import java.util.List ; 43 import java.util.Map ; 44 import net.sf.cglib.reflect.FastClass; 45 import net.sf.cglib.reflect.FastMethod; 46 47 53 class InjectorImpl implements Injector { 54 55 58 private static final Map <Class <?>, Class <?>> PRIMITIVE_COUNTERPARTS; 59 static { 60 Map <Class <?>, Class <?>> primitiveToWrapper = 61 new HashMap <Class <?>, Class <?>>() {{ 62 put(int.class, Integer .class); 63 put(long.class, Long .class); 64 put(boolean.class, Boolean .class); 65 put(byte.class, Byte .class); 66 put(short.class, Short .class); 67 put(float.class, Float .class); 68 put(double.class, Double .class); 69 put(char.class, Character .class); 70 }}; 71 72 Map <Class <?>, Class <?>> counterparts = new HashMap <Class <?>, Class <?>>(); 73 for (Map.Entry <Class <?>, Class <?>> entry : primitiveToWrapper.entrySet()) { 74 Class <?> key = entry.getKey(); 75 Class <?> value = entry.getValue(); 76 counterparts.put(key, value); 77 counterparts.put(value, key); 78 } 79 80 PRIMITIVE_COUNTERPARTS = Collections.unmodifiableMap(counterparts); 81 } 82 83 private static final Map <Class <?>, Converter<?>> PRIMITIVE_CONVERTERS 84 = new PrimitiveConverters(); 85 86 final ConstructionProxyFactory constructionProxyFactory; 87 final Map <Key<?>, BindingImpl<?>> bindings; 88 final BindingsMultimap bindingsMultimap = new BindingsMultimap(); 89 final Map <Class <? extends Annotation >, Scope> scopes; 90 91 ErrorHandler errorHandler = new InvalidErrorHandler(); 92 Object defaultSource = SourceProviders.UNKNOWN_SOURCE; 93 94 InjectorImpl(ConstructionProxyFactory constructionProxyFactory, 95 Map <Key<?>, BindingImpl<?>> bindings, 96 Map <Class <? extends Annotation >, Scope> scopes) { 97 this.constructionProxyFactory = constructionProxyFactory; 98 this.bindings = bindings; 99 this.scopes = scopes; 100 } 101 102 105 void index() { 106 for (BindingImpl<?> binding : bindings.values()) { 107 index(binding); 108 } 109 } 110 111 <T> void index(BindingImpl<T> binding) { 112 bindingsMultimap.put(binding.getKey().getTypeLiteral(), binding); 113 } 114 115 public <T> List <Binding<T>> findBindingsByType(TypeLiteral<T> type) { 117 return Collections.<Binding<T>>unmodifiableList( 118 bindingsMultimap.getAll(type)); 119 } 120 121 <T> List <String > getNamesOfBindingAnnotations(TypeLiteral<T> type) { 123 List <String > names = new ArrayList <String >(); 124 for (Binding<T> binding : findBindingsByType(type)) { 125 Key<T> key = binding.getKey(); 126 if (!key.hasAnnotationType()) { 127 names.add("[no annotation]"); 128 } else { 129 names.add(key.getAnnotationName()); 130 } 131 } 132 return names; 133 } 134 135 138 void withDefaultSource(Object defaultSource, Runnable runnable) { 139 Object previous = this.defaultSource; 140 this.defaultSource = defaultSource; 141 try { 142 runnable.run(); 143 } 144 finally { 145 this.defaultSource = previous; 146 } 147 } 148 149 void setErrorHandler(ErrorHandler errorHandler) { 150 this.errorHandler = errorHandler; 151 } 152 153 <T> InternalFactory<? extends T> getInternalFactory( 154 final Member member, Key<T> key) { 155 157 BindingImpl<T> binding = getBinding(key); 159 if (binding != null) { 160 return binding.getInternalFactory(); 161 } 162 163 Class <? super T> rawType = key.getTypeLiteral().getRawType(); 164 165 if (rawType.equals(Provider.class)) { 167 Type providerType = key.getTypeLiteral().getType(); 168 if (!(providerType instanceof ParameterizedType )) { 169 return null; 171 } 172 Type entryType 173 = ((ParameterizedType ) providerType).getActualTypeArguments()[0]; 174 175 try { 176 final Provider<?> provider = getProvider(key.ofType(entryType)); 177 return new InternalFactory<T>() { 178 @SuppressWarnings ("unchecked") 179 public T get(InternalContext context) { 180 return (T) provider; 181 } 182 }; 183 } 184 catch (ConfigurationException e) { 185 if (key.hasAttributes()) { 188 return getInternalFactory(member, key.withoutAttributes()); 189 } 190 191 ErrorMessages.handleMissingBinding(errorHandler, member, key, 193 getNamesOfBindingAnnotations(key.getTypeLiteral())); 194 return invalidFactory(); 195 } 196 } 197 198 Class <?> primitiveCounterpart 200 = PRIMITIVE_COUNTERPARTS.get(rawType); 201 if (primitiveCounterpart != null) { 202 BindingImpl<?> counterpartBinding 203 = getBinding(key.ofType(primitiveCounterpart)); 204 if (counterpartBinding != null) { 205 return (InternalFactory<? extends T>) 206 counterpartBinding.getInternalFactory(); 207 } 208 } 209 210 214 Key<String > stringKey = key.ofType(String .class); 216 BindingImpl<String > stringBinding = getBinding(stringKey); 217 if (stringBinding != null && stringBinding.isConstant()) { 218 String value = stringBinding.getInternalFactory().get(null); 221 222 225 Converter<T> converter = (Converter<T>) PRIMITIVE_CONVERTERS.get(rawType); 227 if (converter != null) { 228 try { 229 T t = converter.convert(member, key, value); 230 return new ConstantFactory<T>(t); 231 } 232 catch (ConstantConversionException e) { 233 return handleConstantConversionError( 234 member, stringBinding, rawType, e); 235 } 236 } 237 238 if (Enum .class.isAssignableFrom(rawType)) { 240 T t; 241 try { 242 t = (T) Enum.valueOf((Class ) rawType, value); 243 } 244 catch (IllegalArgumentException e) { 245 return handleConstantConversionError( 246 member, stringBinding, rawType, e); 247 } 248 return new ConstantFactory<T>(t); 249 } 250 251 if (rawType == Class .class) { 253 try { 254 return new ConstantFactory<T>((T) Class.forName(value)); 256 } 257 catch (ClassNotFoundException e) { 258 return handleConstantConversionError( 259 member, stringBinding, rawType, e); 260 } 261 } 262 } 263 264 int modifiers = rawType.getModifiers(); 266 if (rawType.isArray() || rawType.isEnum() || rawType.isPrimitive()) { 267 if (key.hasAttributes()) { 270 return getInternalFactory(member, key.withoutAttributes()); 271 } 272 273 return null; 274 } 275 276 if (key.hasAnnotationType()) { 279 if (key.hasAttributes()) { 282 return getInternalFactory(member, key.withoutAttributes()); 283 } 284 285 return null; 286 } 287 288 if (member != null) { 290 final ErrorHandler previous = this.errorHandler; 292 this.errorHandler = new AbstractErrorHandler() { 293 public void handle(Object source, String message) { 294 previous.handle(source, "Error while injecting at " 295 + StackTraceElements.forMember(member) + ": " + message); 296 } 297 }; 298 try { 299 return (InternalFactory<? extends T>) getImplicitBinding(member, 301 rawType, null); 302 } 303 finally { 304 this.errorHandler = previous; 305 } 306 } 307 return (InternalFactory<? extends T>) getImplicitBinding(member, rawType, 309 null); 310 } 311 312 private <T> InternalFactory<T> handleConstantConversionError( 313 Member member, Binding<String > stringBinding, Class <?> rawType, 314 Exception e) { 315 errorHandler.handle( 316 StackTraceElements.forMember(member), 317 ErrorMessages.CONSTANT_CONVERSION_ERROR, 318 stringBinding.getSource(), 319 rawType, 320 e.getMessage()); 321 return invalidFactory(); 322 } 323 324 327 final Map <Class <?>, List <SingleMemberInjector>> injectors 328 = new ReferenceCache<Class <?>, List <SingleMemberInjector>>() { 329 protected List <SingleMemberInjector> create(Class <?> key) { 330 List <SingleMemberInjector> injectors 331 = new ArrayList <SingleMemberInjector>(); 332 addInjectors(key, injectors); 333 return injectors; 334 } 335 }; 336 337 341 void addInjectors(Class clazz, List <SingleMemberInjector> injectors) { 342 if (clazz == Object .class) { 343 return; 344 } 345 346 addInjectors(clazz.getSuperclass(), injectors); 348 349 addSingleInjectorsForFields(clazz.getDeclaredFields(), false, injectors); 351 addSingleInjectorsForMethods(clazz.getDeclaredMethods(), false, injectors); 352 } 353 354 void addSingleInjectorsForMethods(Method [] methods, boolean statics, 355 List <SingleMemberInjector> injectors) { 356 addInjectorsForMembers(Arrays.asList(methods), statics, injectors, 357 new SingleInjectorFactory<Method >() { 358 public SingleMemberInjector create(InjectorImpl injector, 359 Method method) throws MissingDependencyException { 360 return new SingleMethodInjector(injector, method); 361 } 362 }); 363 } 364 365 void addSingleInjectorsForFields(Field [] fields, boolean statics, 366 List <SingleMemberInjector> injectors) { 367 addInjectorsForMembers(Arrays.asList(fields), statics, injectors, 368 new SingleInjectorFactory<Field >() { 369 public SingleMemberInjector create(InjectorImpl injector, 370 Field field) throws MissingDependencyException { 371 return new SingleFieldInjector(injector, field); 372 } 373 }); 374 } 375 376 <M extends Member & AnnotatedElement > void addInjectorsForMembers( 377 List <M> members, boolean statics, List <SingleMemberInjector> injectors, 378 SingleInjectorFactory<M> injectorFactory) { 379 for (M member : members) { 380 if (isStatic(member) == statics) { 381 Inject inject = member.getAnnotation(Inject.class); 382 if (inject != null) { 383 try { 384 injectors.add(injectorFactory.create(this, member)); 385 } 386 catch (MissingDependencyException e) { 387 if (!inject.optional()) { 388 e.handle(errorHandler); 390 } 391 } 392 } 393 } 394 } 395 } 396 397 Map <Key<?>, BindingImpl<?>> internalBindings() { 398 return bindings; 399 } 400 401 public Map <Key<?>, Binding<?>> getBindings() { 403 return Collections.<Key<?>, Binding<?>>unmodifiableMap(bindings); 404 } 405 406 @SuppressWarnings ("unchecked") 407 public <T> BindingImpl<T> getBinding(Key<T> key) { 408 return (BindingImpl<T>) bindings.get(key); 409 } 410 411 interface SingleInjectorFactory<M extends Member & AnnotatedElement > { 412 SingleMemberInjector create(InjectorImpl injector, M member) 413 throws MissingDependencyException; 414 } 415 416 private boolean isStatic(Member member) { 417 return Modifier.isStatic(member.getModifiers()); 418 } 419 420 private static class BindingsMultimap { 421 private final Map <TypeLiteral<?>, List <? extends BindingImpl<?>>> map 422 = new HashMap <TypeLiteral<?>, List <? extends BindingImpl<?>>>(); 423 424 public <T> void put(TypeLiteral<T> type, BindingImpl<T> binding) { 425 List <BindingImpl<T>> bindingsForThisType = getFromMap(type); 426 if (bindingsForThisType == null) { 427 bindingsForThisType = new ArrayList <BindingImpl<T>>(); 428 map.put(type, bindingsForThisType); 430 } 431 bindingsForThisType.add(binding); 432 } 433 434 public <T> List <BindingImpl<T>> getAll(TypeLiteral<T> type) { 435 List <BindingImpl<T>> list = getFromMap(type); 436 return list == null ? Collections.<BindingImpl<T>>emptyList() : list; 437 } 438 439 @SuppressWarnings ("unchecked") 441 private <T> List <BindingImpl<T>> getFromMap(TypeLiteral<T> type) { 442 return (List <BindingImpl<T>>) map.get(type); 443 } 444 } 445 446 class SingleFieldInjector implements SingleMemberInjector { 447 448 final Field field; 449 final InternalFactory<?> factory; 450 final ExternalContext<?> externalContext; 451 452 public SingleFieldInjector(InjectorImpl injector, Field field) 453 throws MissingDependencyException { 454 this.field = field; 455 456 field.setAccessible(true); 458 459 Key<?> key = Key.get( 460 field.getGenericType(), field, field.getAnnotations(), errorHandler); 461 factory = injector.getInternalFactory(field, key); 462 if (factory == null) { 463 throw new MissingDependencyException(key, field); 464 } 465 466 this.externalContext = ExternalContext.newInstance(field, key, injector); 467 } 468 469 public void inject(InternalContext context, Object o) { 470 ExternalContext<?> previous = context.getExternalContext(); 471 context.setExternalContext(externalContext); 472 try { 473 Object value = factory.get(context); 474 if (value == null) { 475 throw new AssertionError (); } 477 field.set(o, value); 478 } 479 catch (IllegalAccessException e) { 480 throw new AssertionError (e); 481 } 482 catch (ConfigurationException e) { 483 throw e; 484 } 485 catch (Throwable throwable) { 486 throw new ProvisionException(externalContext, throwable); 487 } 488 finally { 489 context.setExternalContext(previous); 490 } 491 } 492 } 493 494 502 <M extends AccessibleObject & Member > 503 SingleParameterInjector<?>[] getParametersInjectors(M member, 504 Annotation [][] annotations, Type [] parameterTypes) 505 throws MissingDependencyException { 506 SingleParameterInjector<?>[] parameterInjectors 507 = new SingleParameterInjector<?>[parameterTypes.length]; 508 Iterator <Annotation []> annotationsIterator 509 = Arrays.asList(annotations).iterator(); 510 int index = 0; 511 for (Type parameterType : parameterTypes) { 512 Annotation [] parameterAnnotations = annotationsIterator.next(); 513 Key<?> key = Key.get( 514 parameterType, member, parameterAnnotations, errorHandler); 515 parameterInjectors[index] = createParameterInjector(key, member, index); 516 index++; 517 } 518 519 return parameterInjectors; 520 } 521 522 <T> SingleParameterInjector<T> createParameterInjector( 523 Key<T> key, Member member, int index) throws MissingDependencyException { 524 InternalFactory<? extends T> factory = getInternalFactory(member, key); 525 if (factory == null) { 526 throw new MissingDependencyException(key, member); 527 } 528 529 ExternalContext<T> externalContext 530 = ExternalContext.newInstance(member, index, key, this); 531 return new SingleParameterInjector<T>(externalContext, factory); 532 } 533 534 static class SingleMethodInjector implements SingleMemberInjector { 535 536 final MethodInvoker methodInvoker; 537 final SingleParameterInjector<?>[] parameterInjectors; 538 539 public SingleMethodInjector(InjectorImpl injector, final Method method) 540 throws MissingDependencyException { 541 if (Modifier.isPrivate(method.getModifiers()) 543 || Modifier.isProtected(method.getModifiers())) { 544 method.setAccessible(true); 545 this.methodInvoker = new MethodInvoker() { 546 public Object invoke(Object target, Object ... parameters) throws 547 IllegalAccessException , InvocationTargetException { 548 Objects.assertNoNulls(parameters); 549 return method.invoke(target, parameters); 550 } 551 }; 552 } 553 else { 554 FastClass fastClass = GuiceFastClass.create(method.getDeclaringClass()); 555 final FastMethod fastMethod = fastClass.getMethod(method); 556 557 this.methodInvoker = new MethodInvoker() { 558 public Object invoke(Object target, Object ... parameters) 559 throws IllegalAccessException , InvocationTargetException { 560 Objects.assertNoNulls(parameters); 561 return fastMethod.invoke(target, parameters); 562 } 563 }; 564 } 565 566 Type [] parameterTypes = method.getGenericParameterTypes(); 567 parameterInjectors = parameterTypes.length > 0 568 ? injector.getParametersInjectors( 569 method, method.getParameterAnnotations(), parameterTypes) 570 : null; 571 } 572 573 public void inject(InternalContext context, Object o) { 574 try { 575 methodInvoker.invoke(o, getParameters(context, parameterInjectors)); 576 } 577 catch (Exception e) { 578 throw new RuntimeException (e); 579 } 580 } 581 } 582 583 586 interface MethodInvoker { 587 Object invoke(Object target, Object ... parameters) throws 588 IllegalAccessException , InvocationTargetException ; 589 } 590 591 final Map <Class <?>, ConstructorInjector> constructors 592 = new ReferenceCache<Class <?>, ConstructorInjector>() { 593 @SuppressWarnings ("unchecked") 594 protected ConstructorInjector<?> create(Class <?> implementation) { 595 if (implementation.isInterface()) { 596 errorHandler.handle(defaultSource, 597 ErrorMessages.CANNOT_INJECT_ABSTRACT_TYPE, implementation); 598 return ConstructorInjector.invalidConstructor(); 599 } 600 601 return new ConstructorInjector(InjectorImpl.this, implementation); 602 } 603 }; 604 605 609 static class InvalidConstructor { 610 InvalidConstructor() { 611 throw new AssertionError (); 612 } 613 } 614 615 @SuppressWarnings ("unchecked") 616 static <T> Constructor <T> invalidConstructor() { 617 try { 618 return (Constructor <T>) InvalidConstructor.class.getDeclaredConstructor(); 619 } 620 catch (NoSuchMethodException e) { 621 throw new AssertionError (e); 622 } 623 } 624 625 static class SingleParameterInjector<T> { 626 627 final ExternalContext<T> externalContext; 628 final InternalFactory<? extends T> factory; 629 630 public SingleParameterInjector(ExternalContext<T> externalContext, 631 InternalFactory<? extends T> factory) { 632 this.externalContext = externalContext; 633 this.factory = factory; 634 } 635 636 T inject(InternalContext context) { 637 ExternalContext<?> previous = context.getExternalContext(); 638 context.setExternalContext(externalContext); 639 try { 640 return factory.get(context); 641 } 642 catch (ConfigurationException e) { 643 throw e; 644 } 645 catch (Throwable throwable) { 646 throw new ProvisionException(externalContext, throwable); 647 } 648 finally { 649 context.setExternalContext(previous); 650 } 651 } 652 } 653 654 658 static Object [] getParameters(InternalContext context, 659 SingleParameterInjector[] parameterInjectors) { 660 if (parameterInjectors == null) { 661 return null; 662 } 663 664 Object [] parameters = new Object [parameterInjectors.length]; 665 for (int i = 0; i < parameters.length; i++) { 666 parameters[i] = parameterInjectors[i].inject(context); 667 } 668 return parameters; 669 } 670 671 void injectMembers(Object o, InternalContext context) { 672 List <SingleMemberInjector> injectorsForClass = injectors.get(o.getClass()); 673 for (SingleMemberInjector injector : injectorsForClass) { 674 injector.inject(context, o); 675 } 676 } 677 678 public void injectMembers(final Object o) { 680 callInContext(new ContextualCallable<Void >() { 681 public Void call(InternalContext context) { 682 injectMembers(o, context); 683 return null; 684 } 685 }); 686 } 687 688 public <T> Provider<T> getProvider(Class <T> type) { 689 return getProvider(Key.get(type)); 690 } 691 692 public <T> Provider<T> getProvider(final Key<T> key) { 693 final InternalFactory<? extends T> factory = getInternalFactory(null, key); 694 695 if (factory == null) { 696 throw new ConfigurationException( 697 "Missing binding to " + ErrorMessages.convert(key) + "."); 698 } 699 700 return new Provider<T>() { 701 public T get() { 702 return callInContext(new ContextualCallable<T>() { 703 public T call(InternalContext context) { 704 ExternalContext<?> previous = context.getExternalContext(); 705 context.setExternalContext( 706 ExternalContext.newInstance(null, key, InjectorImpl.this)); 707 try { 708 return factory.get(context); 709 } 710 finally { 711 context.setExternalContext(previous); 712 } 713 } 714 }); 715 } 716 717 public String toString() { 718 return factory.toString(); 719 } 720 }; 721 } 722 723 public <T> T getInstance(Key<T> key) { 724 return getProvider(key).get(); 725 } 726 727 public <T> T getInstance(Class <T> type) { 728 return getProvider(type).get(); 729 } 730 731 final ThreadLocal <InternalContext[]> localContext 732 = new ThreadLocal <InternalContext[]>() { 733 protected InternalContext[] initialValue() { 734 return new InternalContext[1]; 735 } 736 }; 737 738 742 <T> T callInContext(ContextualCallable<T> callable) { 743 InternalContext[] reference = localContext.get(); 744 if (reference[0] == null) { 745 reference[0] = new InternalContext(this); 746 try { 747 return callable.call(reference[0]); 748 } 749 finally { 750 reference[0] = null; 752 } 753 } 754 else { 755 return callable.call(reference[0]); 757 } 758 } 759 760 763 @SuppressWarnings ("unchecked") 764 <T> ConstructorInjector<T> getConstructor(Class <T> implementation) { 765 return constructors.get(implementation); 766 } 767 768 @SuppressWarnings ("unchecked") 769 <T> ConstructorInjector<T> getConstructor(TypeLiteral<T> implementation) { 770 return constructors.get(implementation.getRawType()); 771 } 772 773 776 interface SingleMemberInjector { 777 void inject(InternalContext context, Object o); 778 } 779 780 class MissingDependencyException extends Exception { 781 782 final Key<?> key; 783 final Member member; 784 785 MissingDependencyException(Key<?> key, Member member) { 786 this.key = key; 787 this.member = member; 788 } 789 790 void handle(ErrorHandler errorHandler) { 791 ErrorMessages.handleMissingBinding(errorHandler, member, key, 792 getNamesOfBindingAnnotations(key.getTypeLiteral())); 793 } 794 } 795 796 799 static class PrimitiveConverters extends HashMap <Class <?>, Converter<?>> { 800 801 PrimitiveConverters() { 802 putParser(int.class); 803 putParser(long.class); 804 putParser(boolean.class); 805 putParser(byte.class); 806 putParser(short.class); 807 putParser(float.class); 808 putParser(double.class); 809 810 Converter<Character > characterConverter = new Converter<Character >() { 812 public Character convert(Member member, Key<Character > key, 813 String value) throws ConstantConversionException { 814 value = value.trim(); 815 if (value.length() != 1) { 816 throw new ConstantConversionException(member, key, value, 817 "Length != 1."); 818 } 819 return value.charAt(0); 820 } 821 }; 822 put(char.class, characterConverter); 823 put(Character .class, characterConverter); 824 } 825 826 <T> void putParser(final Class <T> primitive) { 827 try { 828 Class <?> wrapper = PRIMITIVE_COUNTERPARTS.get(primitive); 829 final Method parser = wrapper.getMethod( 830 "parse" + Strings.capitalize(primitive.getName()), String .class); 831 Converter<T> converter = new Converter<T>() { 832 @SuppressWarnings ("unchecked") 833 public T convert(Member member, Key<T> key, String value) 834 throws ConstantConversionException { 835 try { 836 return (T) parser.invoke(null, value); 837 } 838 catch (IllegalAccessException e) { 839 throw new AssertionError (e); 840 } 841 catch (InvocationTargetException e) { 842 throw new ConstantConversionException(member, key, value, 843 e.getTargetException()); 844 } 845 } 846 }; 847 put(wrapper, converter); 848 put(primitive, converter); 849 } 850 catch (NoSuchMethodException e) { 851 throw new AssertionError (e); 852 } 853 } 854 } 855 856 859 interface Converter<T> { 860 861 864 T convert(Member member, Key<T> key, String value) 865 throws ConstantConversionException; 866 } 867 868 Map <Class <?>, InternalFactory<?>> implicitBindings = 869 new HashMap <Class <?>, InternalFactory<?>>(); 870 871 876 <T> InternalFactory<? extends T> getImplicitBinding(Member member, 877 final Class <T> type, Scope scope) { 878 ImplementedBy implementedBy = 880 type.getAnnotation(ImplementedBy.class); 881 if (implementedBy != null) { 882 Class <?> implementationType = implementedBy.value(); 883 884 if (implementationType == type) { 886 errorHandler.handle(StackTraceElements.forType(type), 887 ErrorMessages.RECURSIVE_IMPLEMENTATION_TYPE, type); 888 return invalidFactory(); 889 } 890 891 if (!type.isAssignableFrom(implementationType)) { 893 errorHandler.handle(StackTraceElements.forType(type), 894 ErrorMessages.NOT_A_SUBTYPE, implementationType, type); 895 return invalidFactory(); 896 } 897 898 return (InternalFactory<T>) getInternalFactory( 899 member, Key.get(implementationType)); 900 } 901 902 ProvidedBy providedBy = type.getAnnotation(ProvidedBy.class); 904 if (providedBy != null) { 905 final Class <? extends Provider<?>> providerType = providedBy.value(); 906 907 if (providerType == type) { 909 errorHandler.handle(StackTraceElements.forType(type), 910 ErrorMessages.RECURSIVE_PROVIDER_TYPE, type); 911 return invalidFactory(); 912 } 913 914 917 InternalFactory<? extends Provider<?>> providerFactory 918 = getInternalFactory(member, Key.get(providerType)); 919 Key<? extends Provider<?>> providerKey = Key.get(providerType); 920 return (InternalFactory<T>) new BoundProviderFactory( 921 providerKey, providerFactory, StackTraceElements.forType(type)) { 922 public Object get(InternalContext context) { 923 Object o = super.get(context); 924 try { 925 return type.cast(o); 926 } catch (ClassCastException e) { 927 errorHandler.handle(StackTraceElements.forType(type), 928 ErrorMessages.SUBTYPE_NOT_PROVIDED, providerType, type); 929 throw new AssertionError (); 930 } 931 } 932 }; 933 } 934 935 if (Modifier.isAbstract(type.getModifiers())) { 938 return null; 939 } 940 941 synchronized (implicitBindings) { 943 @SuppressWarnings ("unchecked") 944 InternalFactory<T> factory = 945 (InternalFactory<T>) implicitBindings.get(type); 946 if (factory != null) { 947 return factory; 948 } 949 950 ImplicitBinding<T> implicitBinding = new ImplicitBinding<T>(type); 952 953 955 if (scope == null) { 958 scope = Scopes.getScopeForType(type, scopes, errorHandler); 959 } 960 961 InternalFactory<? extends T> scoped; 962 if (scope != null) { 963 scoped = Scopes.scope(Key.get(type), this, implicitBinding, scope); 964 } else { 965 scoped = implicitBinding; 966 } 967 968 implicitBindings.put(type, scoped); 969 970 try { 971 ConstructorInjector<T> constructor = getConstructor(type); 974 implicitBinding.setConstructorInjector(constructor); 975 } 976 catch (RuntimeException e) { 977 implicitBindings.remove(type); 979 throw e; 980 } 981 catch (Throwable t) { 982 implicitBindings.remove(type); 984 throw new AssertionError (t); 985 } 986 987 return scoped; 988 } 989 } 990 991 static class ImplicitBinding<T> implements InternalFactory<T> { 992 993 final Class <T> implementation; 994 ConstructorInjector<T> constructorInjector; 995 996 ImplicitBinding(Class <T> implementation) { 997 this.implementation = implementation; 998 } 999 1000 void setConstructorInjector( 1001 ConstructorInjector<T> constructorInjector) { 1002 this.constructorInjector = constructorInjector; 1003 } 1004 1005 public T get(InternalContext context) { 1006 return (T) constructorInjector.construct(context, 1007 context.getExpectedType()); 1008 } 1009 } 1010 1011 private static final InternalFactory<?> INVALID_FACTORY 1012 = new InternalFactory<Object >() { 1013 public Object get(InternalContext context) { 1014 throw new AssertionError (); 1015 } 1016 }; 1017 1018 @SuppressWarnings ("unchecked") 1019 static <T> InternalFactory<T> invalidFactory() { 1020 return (InternalFactory<T>) INVALID_FACTORY; 1021 } 1022 1023 public String toString() { 1024 return new ToStringBuilder(Injector.class) 1025 .add("bindings", bindings) 1026 .toString(); 1027 } 1028} 1029 | Popular Tags |