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