blob: 417c437ea11c409b944bced9d74fcfabb5b527ab [file] [log] [blame]
limpbizkit7cef5b02009-03-29 21:16:51 +00001/**
2 * Copyright (C) 2009 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
limpbizkit5ae41eb2009-06-06 17:51:27 +000017package com.google.inject.internal;
limpbizkit7cef5b02009-03-29 21:16:51 +000018
limpbizkit5ae41eb2009-06-06 17:51:27 +000019import com.google.inject.ConfigurationException;
20import com.google.inject.TypeLiteral;
limpbizkit7cef5b02009-03-29 21:16:51 +000021import com.google.inject.spi.InjectionPoint;
limpbizkitee792462009-04-08 23:48:49 +000022import com.google.inject.spi.TypeListenerBinding;
limpbizkit7cef5b02009-03-29 21:16:51 +000023import java.lang.reflect.Field;
limpbizkit7cef5b02009-03-29 21:16:51 +000024import java.util.List;
25import java.util.Set;
limpbizkit7cef5b02009-03-29 21:16:51 +000026
27/**
28 * Members injectors by type.
29 *
30 * @author jessewilson@google.com (Jesse Wilson)
31 */
limpbizkit5ae41eb2009-06-06 17:51:27 +000032final class MembersInjectorStore {
limpbizkit7cef5b02009-03-29 21:16:51 +000033 private final InjectorImpl injector;
limpbizkitee792462009-04-08 23:48:49 +000034 private final ImmutableList<TypeListenerBinding> typeListenerBindings;
limpbizkit7cef5b02009-03-29 21:16:51 +000035
36 private final FailableCache<TypeLiteral<?>, MembersInjectorImpl<?>> cache
37 = new FailableCache<TypeLiteral<?>, MembersInjectorImpl<?>>() {
38 @Override protected MembersInjectorImpl<?> create(TypeLiteral<?> type, Errors errors)
39 throws ErrorsException {
40 return createWithListeners(type, errors);
41 }
42 };
43
44 MembersInjectorStore(InjectorImpl injector,
limpbizkitee792462009-04-08 23:48:49 +000045 List<TypeListenerBinding> typeListenerBindings) {
limpbizkit7cef5b02009-03-29 21:16:51 +000046 this.injector = injector;
limpbizkitee792462009-04-08 23:48:49 +000047 this.typeListenerBindings = ImmutableList.copyOf(typeListenerBindings);
limpbizkit7cef5b02009-03-29 21:16:51 +000048 }
49
50 /**
limpbizkita843a952009-04-08 22:24:55 +000051 * Returns true if any type listeners are installed. Other code may take shortcuts when there
52 * aren't any type listeners.
53 */
54 public boolean hasTypeListeners() {
limpbizkitee792462009-04-08 23:48:49 +000055 return !typeListenerBindings.isEmpty();
limpbizkita843a952009-04-08 22:24:55 +000056 }
57
58 /**
limpbizkit7cef5b02009-03-29 21:16:51 +000059 * Returns a new complete members injector with injection listeners registered.
60 */
61 @SuppressWarnings("unchecked") // the MembersInjector type always agrees with the passed type
62 public <T> MembersInjectorImpl<T> get(TypeLiteral<T> key, Errors errors) throws ErrorsException {
63 return (MembersInjectorImpl<T>) cache.get(key, errors);
64 }
65
66 /**
limpbizkita843a952009-04-08 22:24:55 +000067 * Creates a new members injector and attaches both injection listeners and method aspects.
limpbizkit7cef5b02009-03-29 21:16:51 +000068 */
limpbizkita843a952009-04-08 22:24:55 +000069 private <T> MembersInjectorImpl<T> createWithListeners(TypeLiteral<T> type, Errors errors)
limpbizkit7cef5b02009-03-29 21:16:51 +000070 throws ErrorsException {
71 int numErrorsBefore = errors.size();
limpbizkita843a952009-04-08 22:24:55 +000072
limpbizkit7cef5b02009-03-29 21:16:51 +000073 Set<InjectionPoint> injectionPoints;
74 try {
75 injectionPoints = InjectionPoint.forInstanceMethodsAndFields(type);
76 } catch (ConfigurationException e) {
77 errors.merge(e.getErrorMessages());
78 injectionPoints = e.getPartialValue();
79 }
80 ImmutableList<SingleMemberInjector> injectors = getInjectors(injectionPoints, errors);
81 errors.throwIfNewErrors(numErrorsBefore);
limpbizkit7cef5b02009-03-29 21:16:51 +000082
limpbizkit8d620752009-03-31 22:37:26 +000083 EncounterImpl<T> encounter = new EncounterImpl<T>(errors, injector.lookups);
limpbizkitee792462009-04-08 23:48:49 +000084 for (TypeListenerBinding typeListener : typeListenerBindings) {
limpbizkit7cef5b02009-03-29 21:16:51 +000085 if (typeListener.getTypeMatcher().matches(type)) {
86 try {
limpbizkita843a952009-04-08 22:24:55 +000087 typeListener.getListener().hear(type, encounter);
limpbizkit7cef5b02009-03-29 21:16:51 +000088 } catch (RuntimeException e) {
limpbizkita843a952009-04-08 22:24:55 +000089 errors.errorNotifyingTypeListener(typeListener, type, e);
limpbizkit7cef5b02009-03-29 21:16:51 +000090 }
91 }
92 }
limpbizkitccb15e42009-04-01 16:33:29 +000093 encounter.invalidate();
limpbizkit7cef5b02009-03-29 21:16:51 +000094 errors.throwIfNewErrors(numErrorsBefore);
limpbizkita843a952009-04-08 22:24:55 +000095
limpbizkiteb405132009-04-14 00:50:25 +000096 return new MembersInjectorImpl<T>(injector, type, encounter, injectors);
limpbizkit7cef5b02009-03-29 21:16:51 +000097 }
98
99 /**
100 * Returns the injectors for the specified injection points.
101 */
102 ImmutableList<SingleMemberInjector> getInjectors(
103 Set<InjectionPoint> injectionPoints, Errors errors) {
104 List<SingleMemberInjector> injectors = Lists.newArrayList();
105 for (InjectionPoint injectionPoint : injectionPoints) {
106 try {
107 Errors errorsForMember = injectionPoint.isOptional()
108 ? new Errors(injectionPoint)
109 : errors.withSource(injectionPoint);
110 SingleMemberInjector injector = injectionPoint.getMember() instanceof Field
111 ? new SingleFieldInjector(this.injector, injectionPoint, errorsForMember)
112 : new SingleMethodInjector(this.injector, injectionPoint, errorsForMember);
113 injectors.add(injector);
114 } catch (ErrorsException ignoredForNow) {
115 // ignored for now
116 }
117 }
118 return ImmutableList.copyOf(injectors);
119 }
120}