0001: /**
0002: * Copyright (C) 2006 Google Inc.
0003: *
0004: * Licensed under the Apache License, Version 2.0 (the "License");
0005: * you may not use this file except in compliance with the License.
0006: * You may obtain a copy of the License at
0007: *
0008: * http://www.apache.org/licenses/LICENSE-2.0
0009: *
0010: * Unless required by applicable law or agreed to in writing, software
0011: * distributed under the License is distributed on an "AS IS" BASIS,
0012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013: * See the License for the specific language governing permissions and
0014: * limitations under the License.
0015: */package com.google.inject;
0016:
0017: import com.google.inject.spi.SourceProviders;
0018: import com.google.inject.util.GuiceFastClass;
0019: import com.google.inject.util.Objects;
0020: import com.google.inject.util.ReferenceCache;
0021: import com.google.inject.util.StackTraceElements;
0022: import com.google.inject.util.Strings;
0023: import com.google.inject.util.ToStringBuilder;
0024: import java.lang.annotation.Annotation;
0025: import java.lang.reflect.AccessibleObject;
0026: import java.lang.reflect.AnnotatedElement;
0027: import java.lang.reflect.Constructor;
0028: import java.lang.reflect.Field;
0029: import java.lang.reflect.InvocationTargetException;
0030: import java.lang.reflect.Member;
0031: import java.lang.reflect.Method;
0032: import java.lang.reflect.Modifier;
0033: import java.lang.reflect.ParameterizedType;
0034: import java.lang.reflect.Type;
0035: import java.util.ArrayList;
0036: import java.util.Arrays;
0037: import java.util.Collections;
0038: import java.util.HashMap;
0039: import java.util.Iterator;
0040: import java.util.List;
0041: import java.util.Map;
0042: import net.sf.cglib.reflect.FastClass;
0043: import net.sf.cglib.reflect.FastMethod;
0044:
0045: /**
0046: * Default {@link Injector} implementation.
0047: *
0048: * @author crazybob@google.com (Bob Lee)
0049: * @see BinderImpl
0050: */
0051: class InjectorImpl implements Injector {
0052:
0053: /**
0054: * Maps between primitive types and their wrappers and vice versa.
0055: */
0056: private static final Map<Class<?>, Class<?>> PRIMITIVE_COUNTERPARTS;
0057: static {
0058: Map<Class<?>, Class<?>> primitiveToWrapper = new HashMap<Class<?>, Class<?>>() {
0059: {
0060: put(int.class, Integer.class);
0061: put(long.class, Long.class);
0062: put(boolean.class, Boolean.class);
0063: put(byte.class, Byte.class);
0064: put(short.class, Short.class);
0065: put(float.class, Float.class);
0066: put(double.class, Double.class);
0067: put(char.class, Character.class);
0068: }
0069: };
0070:
0071: Map<Class<?>, Class<?>> counterparts = new HashMap<Class<?>, Class<?>>();
0072: for (Map.Entry<Class<?>, Class<?>> entry : primitiveToWrapper
0073: .entrySet()) {
0074: Class<?> key = entry.getKey();
0075: Class<?> value = entry.getValue();
0076: counterparts.put(key, value);
0077: counterparts.put(value, key);
0078: }
0079:
0080: PRIMITIVE_COUNTERPARTS = Collections
0081: .unmodifiableMap(counterparts);
0082: }
0083:
0084: private static final Map<Class<?>, Converter<?>> PRIMITIVE_CONVERTERS = new PrimitiveConverters();
0085:
0086: final ConstructionProxyFactory constructionProxyFactory;
0087: final Map<Key<?>, BindingImpl<?>> bindings;
0088: final BindingsMultimap bindingsMultimap = new BindingsMultimap();
0089: final Map<Class<? extends Annotation>, Scope> scopes;
0090:
0091: ErrorHandler errorHandler = new InvalidErrorHandler();
0092: Object defaultSource = SourceProviders.UNKNOWN_SOURCE;
0093:
0094: InjectorImpl(ConstructionProxyFactory constructionProxyFactory,
0095: Map<Key<?>, BindingImpl<?>> bindings,
0096: Map<Class<? extends Annotation>, Scope> scopes) {
0097: this .constructionProxyFactory = constructionProxyFactory;
0098: this .bindings = bindings;
0099: this .scopes = scopes;
0100: }
0101:
0102: /**
0103: * Indexes bindings by type.
0104: */
0105: void index() {
0106: for (BindingImpl<?> binding : bindings.values()) {
0107: index(binding);
0108: }
0109: }
0110:
0111: <T> void index(BindingImpl<T> binding) {
0112: bindingsMultimap
0113: .put(binding.getKey().getTypeLiteral(), binding);
0114: }
0115:
0116: // not test-covered
0117: public <T> List<Binding<T>> findBindingsByType(TypeLiteral<T> type) {
0118: return Collections
0119: .<Binding<T>> unmodifiableList(bindingsMultimap
0120: .getAll(type));
0121: }
0122:
0123: // not test-covered
0124: <T> List<String> getNamesOfBindingAnnotations(TypeLiteral<T> type) {
0125: List<String> names = new ArrayList<String>();
0126: for (Binding<T> binding : findBindingsByType(type)) {
0127: Key<T> key = binding.getKey();
0128: if (!key.hasAnnotationType()) {
0129: names.add("[no annotation]");
0130: } else {
0131: names.add(key.getAnnotationName());
0132: }
0133: }
0134: return names;
0135: }
0136:
0137: /**
0138: * This is only used during Injector building.
0139: */
0140: void withDefaultSource(Object defaultSource, Runnable runnable) {
0141: Object previous = this .defaultSource;
0142: this .defaultSource = defaultSource;
0143: try {
0144: runnable.run();
0145: } finally {
0146: this .defaultSource = previous;
0147: }
0148: }
0149:
0150: void setErrorHandler(ErrorHandler errorHandler) {
0151: this .errorHandler = errorHandler;
0152: }
0153:
0154: <T> InternalFactory<? extends T> getInternalFactory(
0155: final Member member, Key<T> key) {
0156: // TODO: Clean up unchecked type warnings.
0157:
0158: // Do we have a factory for the specified type and name?
0159: BindingImpl<T> binding = getBinding(key);
0160: if (binding != null) {
0161: return binding.getInternalFactory();
0162: }
0163:
0164: Class<? super T> rawType = key.getTypeLiteral().getRawType();
0165:
0166: // Handle cases where T is a Provider<?>.
0167: if (rawType.equals(Provider.class)) {
0168: Type providerType = key.getTypeLiteral().getType();
0169: if (!(providerType instanceof ParameterizedType)) {
0170: // Raw Provider.
0171: return null;
0172: }
0173: Type entryType = ((ParameterizedType) providerType)
0174: .getActualTypeArguments()[0];
0175:
0176: try {
0177: final Provider<?> provider = getProvider(key
0178: .ofType(entryType));
0179: return new InternalFactory<T>() {
0180: @SuppressWarnings("unchecked")
0181: public T get(InternalContext context) {
0182: return (T) provider;
0183: }
0184: };
0185: } catch (ConfigurationException e) {
0186: // Look for a factory bound to a key without annotation attributes if
0187: // necessary.
0188: if (key.hasAttributes()) {
0189: return getInternalFactory(member, key
0190: .withoutAttributes());
0191: }
0192:
0193: // End of the road.
0194: ErrorMessages.handleMissingBinding(errorHandler,
0195: member, key, getNamesOfBindingAnnotations(key
0196: .getTypeLiteral()));
0197: return invalidFactory();
0198: }
0199: }
0200:
0201: // Auto[un]box primitives.
0202: Class<?> primitiveCounterpart = PRIMITIVE_COUNTERPARTS
0203: .get(rawType);
0204: if (primitiveCounterpart != null) {
0205: BindingImpl<?> counterpartBinding = getBinding(key
0206: .ofType(primitiveCounterpart));
0207: if (counterpartBinding != null) {
0208: return (InternalFactory<? extends T>) counterpartBinding
0209: .getInternalFactory();
0210: }
0211: }
0212:
0213: // TODO: Should we try to convert from a String first, or should we look
0214: // for a binding to the annotation type sans attributes? Right now, we
0215: // convert from a String.
0216:
0217: // Can we convert from a String constant?
0218: Key<String> stringKey = key.ofType(String.class);
0219: BindingImpl<String> stringBinding = getBinding(stringKey);
0220: if (stringBinding != null && stringBinding.isConstant()) {
0221: // We don't need do pass in an InternalContext because we know this is
0222: // a ConstantFactory which will not use it.
0223: String value = stringBinding.getInternalFactory().get(null);
0224:
0225: // TODO: Generalize everything below here and enable users to plug in
0226: // their own converters.
0227:
0228: // Do we need a primitive?
0229: Converter<T> converter = (Converter<T>) PRIMITIVE_CONVERTERS
0230: .get(rawType);
0231: if (converter != null) {
0232: try {
0233: T t = converter.convert(member, key, value);
0234: return new ConstantFactory<T>(t);
0235: } catch (ConstantConversionException e) {
0236: return handleConstantConversionError(member,
0237: stringBinding, rawType, e);
0238: }
0239: }
0240:
0241: // Do we need an enum?
0242: if (Enum.class.isAssignableFrom(rawType)) {
0243: T t;
0244: try {
0245: t = (T) Enum.valueOf((Class) rawType, value);
0246: } catch (IllegalArgumentException e) {
0247: return handleConstantConversionError(member,
0248: stringBinding, rawType, e);
0249: }
0250: return new ConstantFactory<T>(t);
0251: }
0252:
0253: // Do we need a class?
0254: if (rawType == Class.class) {
0255: try {
0256: // TODO: Make sure we use the right classloader.
0257: return new ConstantFactory<T>((T) Class
0258: .forName(value));
0259: } catch (ClassNotFoundException e) {
0260: return handleConstantConversionError(member,
0261: stringBinding, rawType, e);
0262: }
0263: }
0264: }
0265:
0266: // Don't try to inject primitives, arrays, or enums.
0267: int modifiers = rawType.getModifiers();
0268: if (rawType.isArray() || rawType.isEnum()
0269: || rawType.isPrimitive()) {
0270: // Look for a factory bound to a key without annotation attributes if
0271: // necessary.
0272: if (key.hasAttributes()) {
0273: return getInternalFactory(member, key
0274: .withoutAttributes());
0275: }
0276:
0277: return null;
0278: }
0279:
0280: // We don't want to implicitly inject a member if we have a binding
0281: // annotation.
0282: if (key.hasAnnotationType()) {
0283: // Look for a factory bound to a key without annotation attributes if
0284: // necessary.
0285: if (key.hasAttributes()) {
0286: return getInternalFactory(member, key
0287: .withoutAttributes());
0288: }
0289:
0290: return null;
0291: }
0292:
0293: // Last resort: inject the type itself.
0294: if (member != null) {
0295: // If we're injecting into a member, include it in the error messages.
0296: final ErrorHandler previous = this .errorHandler;
0297: this .errorHandler = new AbstractErrorHandler() {
0298: public void handle(Object source, String message) {
0299: previous.handle(source, "Error while injecting at "
0300: + StackTraceElements.forMember(member)
0301: + ": " + message);
0302: }
0303: };
0304: try {
0305: // note: intelliJ thinks this cast is superfluous, but is it?
0306: return (InternalFactory<? extends T>) getImplicitBinding(
0307: member, rawType, null);
0308: } finally {
0309: this .errorHandler = previous;
0310: }
0311: }
0312: // note: intelliJ thinks this cast is superfluous, but is it?
0313: return (InternalFactory<? extends T>) getImplicitBinding(
0314: member, rawType, null);
0315: }
0316:
0317: private <T> InternalFactory<T> handleConstantConversionError(
0318: Member member, Binding<String> stringBinding,
0319: Class<?> rawType, Exception e) {
0320: errorHandler.handle(StackTraceElements.forMember(member),
0321: ErrorMessages.CONSTANT_CONVERSION_ERROR, stringBinding
0322: .getSource(), rawType, e.getMessage());
0323: return invalidFactory();
0324: }
0325:
0326: /**
0327: * Field and method injectors.
0328: */
0329: final Map<Class<?>, List<SingleMemberInjector>> injectors = new ReferenceCache<Class<?>, List<SingleMemberInjector>>() {
0330: protected List<SingleMemberInjector> create(Class<?> key) {
0331: List<SingleMemberInjector> injectors = new ArrayList<SingleMemberInjector>();
0332: addInjectors(key, injectors);
0333: return injectors;
0334: }
0335: };
0336:
0337: /**
0338: * Recursively adds injectors for fields and methods from the given class to
0339: * the given list. Injects parent classes before sub classes.
0340: */
0341: void addInjectors(Class clazz, List<SingleMemberInjector> injectors) {
0342: if (clazz == Object.class) {
0343: return;
0344: }
0345:
0346: // Add injectors for superclass first.
0347: addInjectors(clazz.getSuperclass(), injectors);
0348:
0349: // TODO (crazybob): Filter out overridden members.
0350: addSingleInjectorsForFields(clazz.getDeclaredFields(), false,
0351: injectors);
0352: addSingleInjectorsForMethods(clazz.getDeclaredMethods(), false,
0353: injectors);
0354: }
0355:
0356: void addSingleInjectorsForMethods(Method[] methods,
0357: boolean statics, List<SingleMemberInjector> injectors) {
0358: addInjectorsForMembers(Arrays.asList(methods), statics,
0359: injectors, new SingleInjectorFactory<Method>() {
0360: public SingleMemberInjector create(
0361: InjectorImpl injector, Method method)
0362: throws MissingDependencyException {
0363: return new SingleMethodInjector(injector,
0364: method);
0365: }
0366: });
0367: }
0368:
0369: void addSingleInjectorsForFields(Field[] fields, boolean statics,
0370: List<SingleMemberInjector> injectors) {
0371: addInjectorsForMembers(Arrays.asList(fields), statics,
0372: injectors, new SingleInjectorFactory<Field>() {
0373: public SingleMemberInjector create(
0374: InjectorImpl injector, Field field)
0375: throws MissingDependencyException {
0376: return new SingleFieldInjector(injector, field);
0377: }
0378: });
0379: }
0380:
0381: <M extends Member & AnnotatedElement> void addInjectorsForMembers(
0382: List<M> members, boolean statics,
0383: List<SingleMemberInjector> injectors,
0384: SingleInjectorFactory<M> injectorFactory) {
0385: for (M member : members) {
0386: if (isStatic(member) == statics) {
0387: Inject inject = member.getAnnotation(Inject.class);
0388: if (inject != null) {
0389: try {
0390: injectors.add(injectorFactory.create(this ,
0391: member));
0392: } catch (MissingDependencyException e) {
0393: if (!inject.optional()) {
0394: // TODO: Report errors for more than one parameter per member.
0395: e.handle(errorHandler);
0396: }
0397: }
0398: }
0399: }
0400: }
0401: }
0402:
0403: Map<Key<?>, BindingImpl<?>> internalBindings() {
0404: return bindings;
0405: }
0406:
0407: // not test-covered
0408: public Map<Key<?>, Binding<?>> getBindings() {
0409: return Collections
0410: .<Key<?>, Binding<?>> unmodifiableMap(bindings);
0411: }
0412:
0413: @SuppressWarnings("unchecked")
0414: public <T> BindingImpl<T> getBinding(Key<T> key) {
0415: return (BindingImpl<T>) bindings.get(key);
0416: }
0417:
0418: interface SingleInjectorFactory<M extends Member & AnnotatedElement> {
0419: SingleMemberInjector create(InjectorImpl injector, M member)
0420: throws MissingDependencyException;
0421: }
0422:
0423: private boolean isStatic(Member member) {
0424: return Modifier.isStatic(member.getModifiers());
0425: }
0426:
0427: private static class BindingsMultimap {
0428: private final Map<TypeLiteral<?>, List<? extends BindingImpl<?>>> map = new HashMap<TypeLiteral<?>, List<? extends BindingImpl<?>>>();
0429:
0430: public <T> void put(TypeLiteral<T> type, BindingImpl<T> binding) {
0431: List<BindingImpl<T>> bindingsForThisType = getFromMap(type);
0432: if (bindingsForThisType == null) {
0433: bindingsForThisType = new ArrayList<BindingImpl<T>>();
0434: // We only put matching entries into the map
0435: map.put(type, bindingsForThisType);
0436: }
0437: bindingsForThisType.add(binding);
0438: }
0439:
0440: public <T> List<BindingImpl<T>> getAll(TypeLiteral<T> type) {
0441: List<BindingImpl<T>> list = getFromMap(type);
0442: return list == null ? Collections
0443: .<BindingImpl<T>> emptyList() : list;
0444: }
0445:
0446: // safe because we only put matching entries into the map
0447: @SuppressWarnings("unchecked")
0448: private <T> List<BindingImpl<T>> getFromMap(TypeLiteral<T> type) {
0449: return (List<BindingImpl<T>>) map.get(type);
0450: }
0451: }
0452:
0453: class SingleFieldInjector implements SingleMemberInjector {
0454:
0455: final Field field;
0456: final InternalFactory<?> factory;
0457: final ExternalContext<?> externalContext;
0458:
0459: public SingleFieldInjector(InjectorImpl injector, Field field)
0460: throws MissingDependencyException {
0461: this .field = field;
0462:
0463: // Ewwwww...
0464: field.setAccessible(true);
0465:
0466: Key<?> key = Key.get(field.getGenericType(), field, field
0467: .getAnnotations(), errorHandler);
0468: factory = injector.getInternalFactory(field, key);
0469: if (factory == null) {
0470: throw new MissingDependencyException(key, field);
0471: }
0472:
0473: this .externalContext = ExternalContext.newInstance(field,
0474: key, injector);
0475: }
0476:
0477: public void inject(InternalContext context, Object o) {
0478: ExternalContext<?> previous = context.getExternalContext();
0479: context.setExternalContext(externalContext);
0480: try {
0481: Object value = factory.get(context);
0482: if (value == null) {
0483: throw new AssertionError(); // we should have prevented this
0484: }
0485: field.set(o, value);
0486: } catch (IllegalAccessException e) {
0487: throw new AssertionError(e);
0488: } catch (ConfigurationException e) {
0489: throw e;
0490: } catch (Throwable throwable) {
0491: throw new ProvisionException(externalContext, throwable);
0492: } finally {
0493: context.setExternalContext(previous);
0494: }
0495: }
0496: }
0497:
0498: /**
0499: * Gets parameter injectors.
0500: *
0501: * @param member to which the parameters belong
0502: * @param annotations on the parameters
0503: * @param parameterTypes parameter types
0504: * @return injections
0505: */
0506: <M extends AccessibleObject & Member> SingleParameterInjector<?>[] getParametersInjectors(
0507: M member, Annotation[][] annotations, Type[] parameterTypes)
0508: throws MissingDependencyException {
0509: SingleParameterInjector<?>[] parameterInjectors = new SingleParameterInjector<?>[parameterTypes.length];
0510: Iterator<Annotation[]> annotationsIterator = Arrays.asList(
0511: annotations).iterator();
0512: int index = 0;
0513: for (Type parameterType : parameterTypes) {
0514: Annotation[] parameterAnnotations = annotationsIterator
0515: .next();
0516: Key<?> key = Key.get(parameterType, member,
0517: parameterAnnotations, errorHandler);
0518: parameterInjectors[index] = createParameterInjector(key,
0519: member, index);
0520: index++;
0521: }
0522:
0523: return parameterInjectors;
0524: }
0525:
0526: <T> SingleParameterInjector<T> createParameterInjector(Key<T> key,
0527: Member member, int index) throws MissingDependencyException {
0528: InternalFactory<? extends T> factory = getInternalFactory(
0529: member, key);
0530: if (factory == null) {
0531: throw new MissingDependencyException(key, member);
0532: }
0533:
0534: ExternalContext<T> externalContext = ExternalContext
0535: .newInstance(member, index, key, this );
0536: return new SingleParameterInjector<T>(externalContext, factory);
0537: }
0538:
0539: static class SingleMethodInjector implements SingleMemberInjector {
0540:
0541: final MethodInvoker methodInvoker;
0542: final SingleParameterInjector<?>[] parameterInjectors;
0543:
0544: public SingleMethodInjector(InjectorImpl injector,
0545: final Method method) throws MissingDependencyException {
0546: // We can't use FastMethod if the method is private.
0547: if (Modifier.isPrivate(method.getModifiers())
0548: || Modifier.isProtected(method.getModifiers())) {
0549: method.setAccessible(true);
0550: this .methodInvoker = new MethodInvoker() {
0551: public Object invoke(Object target,
0552: Object... parameters)
0553: throws IllegalAccessException,
0554: InvocationTargetException {
0555: Objects.assertNoNulls(parameters);
0556: return method.invoke(target, parameters);
0557: }
0558: };
0559: } else {
0560: FastClass fastClass = GuiceFastClass.create(method
0561: .getDeclaringClass());
0562: final FastMethod fastMethod = fastClass
0563: .getMethod(method);
0564:
0565: this .methodInvoker = new MethodInvoker() {
0566: public Object invoke(Object target,
0567: Object... parameters)
0568: throws IllegalAccessException,
0569: InvocationTargetException {
0570: Objects.assertNoNulls(parameters);
0571: return fastMethod.invoke(target, parameters);
0572: }
0573: };
0574: }
0575:
0576: Type[] parameterTypes = method.getGenericParameterTypes();
0577: parameterInjectors = parameterTypes.length > 0 ? injector
0578: .getParametersInjectors(method, method
0579: .getParameterAnnotations(), parameterTypes)
0580: : null;
0581: }
0582:
0583: public void inject(InternalContext context, Object o) {
0584: try {
0585: methodInvoker.invoke(o, getParameters(context,
0586: parameterInjectors));
0587: } catch (Exception e) {
0588: throw new RuntimeException(e);
0589: }
0590: }
0591: }
0592:
0593: /**
0594: * Invokes a method.
0595: */
0596: interface MethodInvoker {
0597: Object invoke(Object target, Object... parameters)
0598: throws IllegalAccessException,
0599: InvocationTargetException;
0600: }
0601:
0602: final Map<Class<?>, ConstructorInjector> constructors = new ReferenceCache<Class<?>, ConstructorInjector>() {
0603: @SuppressWarnings("unchecked")
0604: protected ConstructorInjector<?> create(Class<?> implementation) {
0605: if (implementation.isInterface()) {
0606: errorHandler.handle(defaultSource,
0607: ErrorMessages.CANNOT_INJECT_ABSTRACT_TYPE,
0608: implementation);
0609: return ConstructorInjector.invalidConstructor();
0610: }
0611:
0612: return new ConstructorInjector(InjectorImpl.this ,
0613: implementation);
0614: }
0615: };
0616:
0617: /**
0618: * A placeholder. This enables us to continue processing and gather more
0619: * errors but blows up if you actually try to use it.
0620: */
0621: static class InvalidConstructor {
0622: InvalidConstructor() {
0623: throw new AssertionError();
0624: }
0625: }
0626:
0627: @SuppressWarnings("unchecked")
0628: static <T> Constructor<T> invalidConstructor() {
0629: try {
0630: return (Constructor<T>) InvalidConstructor.class
0631: .getDeclaredConstructor();
0632: } catch (NoSuchMethodException e) {
0633: throw new AssertionError(e);
0634: }
0635: }
0636:
0637: static class SingleParameterInjector<T> {
0638:
0639: final ExternalContext<T> externalContext;
0640: final InternalFactory<? extends T> factory;
0641:
0642: public SingleParameterInjector(
0643: ExternalContext<T> externalContext,
0644: InternalFactory<? extends T> factory) {
0645: this .externalContext = externalContext;
0646: this .factory = factory;
0647: }
0648:
0649: T inject(InternalContext context) {
0650: ExternalContext<?> previous = context.getExternalContext();
0651: context.setExternalContext(externalContext);
0652: try {
0653: return factory.get(context);
0654: } catch (ConfigurationException e) {
0655: throw e;
0656: } catch (Throwable throwable) {
0657: throw new ProvisionException(externalContext, throwable);
0658: } finally {
0659: context.setExternalContext(previous);
0660: }
0661: }
0662: }
0663:
0664: /**
0665: * Iterates over parameter injectors and creates an array of parameter
0666: * values.
0667: */
0668: static Object[] getParameters(InternalContext context,
0669: SingleParameterInjector[] parameterInjectors) {
0670: if (parameterInjectors == null) {
0671: return null;
0672: }
0673:
0674: Object[] parameters = new Object[parameterInjectors.length];
0675: for (int i = 0; i < parameters.length; i++) {
0676: parameters[i] = parameterInjectors[i].inject(context);
0677: }
0678: return parameters;
0679: }
0680:
0681: void injectMembers(Object o, InternalContext context) {
0682: List<SingleMemberInjector> injectorsForClass = injectors.get(o
0683: .getClass());
0684: for (SingleMemberInjector injector : injectorsForClass) {
0685: injector.inject(context, o);
0686: }
0687: }
0688:
0689: // Not test-covered
0690: public void injectMembers(final Object o) {
0691: callInContext(new ContextualCallable<Void>() {
0692: public Void call(InternalContext context) {
0693: injectMembers(o, context);
0694: return null;
0695: }
0696: });
0697: }
0698:
0699: public <T> Provider<T> getProvider(Class<T> type) {
0700: return getProvider(Key.get(type));
0701: }
0702:
0703: public <T> Provider<T> getProvider(final Key<T> key) {
0704: final InternalFactory<? extends T> factory = getInternalFactory(
0705: null, key);
0706:
0707: if (factory == null) {
0708: throw new ConfigurationException("Missing binding to "
0709: + ErrorMessages.convert(key) + ".");
0710: }
0711:
0712: return new Provider<T>() {
0713: public T get() {
0714: return callInContext(new ContextualCallable<T>() {
0715: public T call(InternalContext context) {
0716: ExternalContext<?> previous = context
0717: .getExternalContext();
0718: context.setExternalContext(ExternalContext
0719: .newInstance(null, key,
0720: InjectorImpl.this ));
0721: try {
0722: return factory.get(context);
0723: } finally {
0724: context.setExternalContext(previous);
0725: }
0726: }
0727: });
0728: }
0729:
0730: public String toString() {
0731: return factory.toString();
0732: }
0733: };
0734: }
0735:
0736: public <T> T getInstance(Key<T> key) {
0737: return getProvider(key).get();
0738: }
0739:
0740: public <T> T getInstance(Class<T> type) {
0741: return getProvider(type).get();
0742: }
0743:
0744: final ThreadLocal<InternalContext[]> localContext = new ThreadLocal<InternalContext[]>() {
0745: protected InternalContext[] initialValue() {
0746: return new InternalContext[1];
0747: }
0748: };
0749:
0750: /**
0751: * Looks up thread local context. Creates (and removes) a new context if
0752: * necessary.
0753: */
0754: <T> T callInContext(ContextualCallable<T> callable) {
0755: InternalContext[] reference = localContext.get();
0756: if (reference[0] == null) {
0757: reference[0] = new InternalContext(this );
0758: try {
0759: return callable.call(reference[0]);
0760: } finally {
0761: // Only remove the context if this call created it.
0762: reference[0] = null;
0763: }
0764: } else {
0765: // Someone else will clean up this context.
0766: return callable.call(reference[0]);
0767: }
0768: }
0769:
0770: /**
0771: * Gets a constructor function for a given implementation class.
0772: */
0773: @SuppressWarnings("unchecked")
0774: <T> ConstructorInjector<T> getConstructor(Class<T> implementation) {
0775: return constructors.get(implementation);
0776: }
0777:
0778: @SuppressWarnings("unchecked")
0779: <T> ConstructorInjector<T> getConstructor(
0780: TypeLiteral<T> implementation) {
0781: return constructors.get(implementation.getRawType());
0782: }
0783:
0784: /**
0785: * Injects a field or method in a given object.
0786: */
0787: interface SingleMemberInjector {
0788: void inject(InternalContext context, Object o);
0789: }
0790:
0791: class MissingDependencyException extends Exception {
0792:
0793: final Key<?> key;
0794: final Member member;
0795:
0796: MissingDependencyException(Key<?> key, Member member) {
0797: this .key = key;
0798: this .member = member;
0799: }
0800:
0801: void handle(ErrorHandler errorHandler) {
0802: ErrorMessages.handleMissingBinding(errorHandler, member,
0803: key, getNamesOfBindingAnnotations(key
0804: .getTypeLiteral()));
0805: }
0806: }
0807:
0808: /**
0809: * Map of primitive type converters.
0810: */
0811: static class PrimitiveConverters extends
0812: HashMap<Class<?>, Converter<?>> {
0813:
0814: PrimitiveConverters() {
0815: putParser(int.class);
0816: putParser(long.class);
0817: putParser(boolean.class);
0818: putParser(byte.class);
0819: putParser(short.class);
0820: putParser(float.class);
0821: putParser(double.class);
0822:
0823: // Character doesn't follow the same pattern.
0824: Converter<Character> characterConverter = new Converter<Character>() {
0825: public Character convert(Member member,
0826: Key<Character> key, String value)
0827: throws ConstantConversionException {
0828: value = value.trim();
0829: if (value.length() != 1) {
0830: throw new ConstantConversionException(member,
0831: key, value, "Length != 1.");
0832: }
0833: return value.charAt(0);
0834: }
0835: };
0836: put(char.class, characterConverter);
0837: put(Character.class, characterConverter);
0838: }
0839:
0840: <T> void putParser(final Class<T> primitive) {
0841: try {
0842: Class<?> wrapper = PRIMITIVE_COUNTERPARTS
0843: .get(primitive);
0844: final Method parser = wrapper.getMethod("parse"
0845: + Strings.capitalize(primitive.getName()),
0846: String.class);
0847: Converter<T> converter = new Converter<T>() {
0848: @SuppressWarnings("unchecked")
0849: public T convert(Member member, Key<T> key,
0850: String value)
0851: throws ConstantConversionException {
0852: try {
0853: return (T) parser.invoke(null, value);
0854: } catch (IllegalAccessException e) {
0855: throw new AssertionError(e);
0856: } catch (InvocationTargetException e) {
0857: throw new ConstantConversionException(
0858: member, key, value, e
0859: .getTargetException());
0860: }
0861: }
0862: };
0863: put(wrapper, converter);
0864: put(primitive, converter);
0865: } catch (NoSuchMethodException e) {
0866: throw new AssertionError(e);
0867: }
0868: }
0869: }
0870:
0871: /**
0872: * Converts a {@code String} to another type.
0873: */
0874: interface Converter<T> {
0875:
0876: /**
0877: * Converts {@code String} value.
0878: */
0879: T convert(Member member, Key<T> key, String value)
0880: throws ConstantConversionException;
0881: }
0882:
0883: Map<Class<?>, InternalFactory<?>> implicitBindings = new HashMap<Class<?>, InternalFactory<?>>();
0884:
0885: /**
0886: * Gets a factory for the specified type. Used when an explicit binding
0887: * was not made. Uses synchronization here so it's not necessary in the
0888: * factory itself. Returns {@code null} if the type isn't injectable.
0889: */
0890: <T> InternalFactory<? extends T> getImplicitBinding(Member member,
0891: final Class<T> type, Scope scope) {
0892: // Look for @DefaultImplementation.
0893: ImplementedBy implementedBy = type
0894: .getAnnotation(ImplementedBy.class);
0895: if (implementedBy != null) {
0896: Class<?> implementationType = implementedBy.value();
0897:
0898: // Make sure it's not the same type. TODO: Can we check for deeper loops?
0899: if (implementationType == type) {
0900: errorHandler.handle(StackTraceElements.forType(type),
0901: ErrorMessages.RECURSIVE_IMPLEMENTATION_TYPE,
0902: type);
0903: return invalidFactory();
0904: }
0905:
0906: // Make sure implementationType extends type.
0907: if (!type.isAssignableFrom(implementationType)) {
0908: errorHandler.handle(StackTraceElements.forType(type),
0909: ErrorMessages.NOT_A_SUBTYPE,
0910: implementationType, type);
0911: return invalidFactory();
0912: }
0913:
0914: return (InternalFactory<T>) getInternalFactory(member, Key
0915: .get(implementationType));
0916: }
0917:
0918: // Look for @DefaultProvider.
0919: ProvidedBy providedBy = type.getAnnotation(ProvidedBy.class);
0920: if (providedBy != null) {
0921: final Class<? extends Provider<?>> providerType = providedBy
0922: .value();
0923:
0924: // Make sure it's not the same type. TODO: Can we check for deeper loops?
0925: if (providerType == type) {
0926: errorHandler.handle(StackTraceElements.forType(type),
0927: ErrorMessages.RECURSIVE_PROVIDER_TYPE, type);
0928: return invalidFactory();
0929: }
0930:
0931: // TODO: Make sure the provided type extends type. We at least check
0932: // the type at runtime below.
0933:
0934: InternalFactory<? extends Provider<?>> providerFactory = getInternalFactory(
0935: member, Key.get(providerType));
0936: Key<? extends Provider<?>> providerKey = Key
0937: .get(providerType);
0938: return (InternalFactory<T>) new BoundProviderFactory(
0939: providerKey, providerFactory, StackTraceElements
0940: .forType(type)) {
0941: public Object get(InternalContext context) {
0942: Object o = super .get(context);
0943: try {
0944: return type.cast(o);
0945: } catch (ClassCastException e) {
0946: errorHandler.handle(StackTraceElements
0947: .forType(type),
0948: ErrorMessages.SUBTYPE_NOT_PROVIDED,
0949: providerType, type);
0950: throw new AssertionError();
0951: }
0952: }
0953: };
0954: }
0955:
0956: // TODO: Method interceptors could actually enable us to implement
0957: // abstract types. Should we remove this restriction?
0958: if (Modifier.isAbstract(type.getModifiers())) {
0959: return null;
0960: }
0961:
0962: // Inject the class itself.
0963: synchronized (implicitBindings) {
0964: @SuppressWarnings("unchecked")
0965: InternalFactory<T> factory = (InternalFactory<T>) implicitBindings
0966: .get(type);
0967: if (factory != null) {
0968: return factory;
0969: }
0970:
0971: // Create the factory.
0972: ImplicitBinding<T> implicitBinding = new ImplicitBinding<T>(
0973: type);
0974:
0975: // Scope the factory if necessary.
0976:
0977: // If we don't have a scope from the configuration, look for one on
0978: // the type.
0979: if (scope == null) {
0980: scope = Scopes.getScopeForType(type, scopes,
0981: errorHandler);
0982: }
0983:
0984: InternalFactory<? extends T> scoped;
0985: if (scope != null) {
0986: scoped = Scopes.scope(Key.get(type), this ,
0987: implicitBinding, scope);
0988: } else {
0989: scoped = implicitBinding;
0990: }
0991:
0992: implicitBindings.put(type, scoped);
0993:
0994: try {
0995: // Look up the constructor. We do this separately from constructions to
0996: // support circular dependencies.
0997: ConstructorInjector<T> constructor = getConstructor(type);
0998: implicitBinding.setConstructorInjector(constructor);
0999: } catch (RuntimeException e) {
1000: // Clean up state.
1001: implicitBindings.remove(type);
1002: throw e;
1003: } catch (Throwable t) {
1004: // Clean up state.
1005: implicitBindings.remove(type);
1006: throw new AssertionError(t);
1007: }
1008:
1009: return scoped;
1010: }
1011: }
1012:
1013: static class ImplicitBinding<T> implements InternalFactory<T> {
1014:
1015: final Class<T> implementation;
1016: ConstructorInjector<T> constructorInjector;
1017:
1018: ImplicitBinding(Class<T> implementation) {
1019: this .implementation = implementation;
1020: }
1021:
1022: void setConstructorInjector(
1023: ConstructorInjector<T> constructorInjector) {
1024: this .constructorInjector = constructorInjector;
1025: }
1026:
1027: public T get(InternalContext context) {
1028: return (T) constructorInjector.construct(context, context
1029: .getExpectedType());
1030: }
1031: }
1032:
1033: private static final InternalFactory<?> INVALID_FACTORY = new InternalFactory<Object>() {
1034: public Object get(InternalContext context) {
1035: throw new AssertionError();
1036: }
1037: };
1038:
1039: @SuppressWarnings("unchecked")
1040: static <T> InternalFactory<T> invalidFactory() {
1041: return (InternalFactory<T>) INVALID_FACTORY;
1042: }
1043:
1044: public String toString() {
1045: return new ToStringBuilder(Injector.class).add("bindings",
1046: bindings).toString();
1047: }
1048: }
|