blob: 082191fb4900a07a2881036d810d6035ebbdfcd0 [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
17package com.google.inject;
18
19import com.google.inject.internal.Errors;
20import com.google.inject.internal.ErrorsException;
21import com.google.inject.internal.ImmutableList;
22import com.google.inject.internal.ImmutableSet;
23import com.google.inject.internal.InternalContext;
limpbizkit7cef5b02009-03-29 21:16:51 +000024import com.google.inject.spi.InjectionListener;
limpbizkita843a952009-04-08 22:24:55 +000025import com.google.inject.spi.InjectionPoint;
limpbizkit7cef5b02009-03-29 21:16:51 +000026
27/**
28 * Injects members of instances of a given type.
29 *
30 * @author jessewilson@google.com (Jesse Wilson)
31 */
32class MembersInjectorImpl<T> implements MembersInjector<T> {
33 private final TypeLiteral<T> typeLiteral;
34 private final InjectorImpl injector;
35 private final ImmutableList<SingleMemberInjector> memberInjectors;
limpbizkitee792462009-04-08 23:48:49 +000036 private final ImmutableList<MembersInjector<? super T>> userMembersInjectors;
limpbizkit7cef5b02009-03-29 21:16:51 +000037 private final ImmutableList<InjectionListener<? super T>> injectionListeners;
limpbizkiteb405132009-04-14 00:50:25 +000038 /*if[AOP]*/
limpbizkita843a952009-04-08 22:24:55 +000039 private final ImmutableList<MethodAspect> addedAspects;
limpbizkiteb405132009-04-14 00:50:25 +000040 /*end[AOP]*/
limpbizkit7cef5b02009-03-29 21:16:51 +000041
42 MembersInjectorImpl(InjectorImpl injector, TypeLiteral<T> typeLiteral,
limpbizkiteb405132009-04-14 00:50:25 +000043 EncounterImpl<T> encounter, ImmutableList<SingleMemberInjector> memberInjectors) {
limpbizkit7cef5b02009-03-29 21:16:51 +000044 this.injector = injector;
45 this.typeLiteral = typeLiteral;
46 this.memberInjectors = memberInjectors;
limpbizkiteb405132009-04-14 00:50:25 +000047 this.userMembersInjectors = encounter.getMembersInjectors();
48 this.injectionListeners = encounter.getInjectionListeners();
49 /*if[AOP]*/
50 this.addedAspects = encounter.getAspects();
51 /*end[AOP]*/
limpbizkit7cef5b02009-03-29 21:16:51 +000052 }
53
54 public ImmutableList<SingleMemberInjector> getMemberInjectors() {
55 return memberInjectors;
56 }
57
58 public void injectMembers(T instance) {
59 Errors errors = new Errors(typeLiteral);
60 try {
limpbizkita843a952009-04-08 22:24:55 +000061 injectAndNotify(instance, errors);
limpbizkit7cef5b02009-03-29 21:16:51 +000062 } catch (ErrorsException e) {
63 errors.merge(e.getErrors());
64 }
65
66 errors.throwProvisionExceptionIfErrorsExist();
67 }
68
limpbizkita843a952009-04-08 22:24:55 +000069 void injectAndNotify(final T instance, final Errors errors) throws ErrorsException {
limpbizkit7cef5b02009-03-29 21:16:51 +000070 if (instance == null) {
71 return;
72 }
73
74 injector.callInContext(new ContextualCallable<Void>() {
75 public Void call(InternalContext context) throws ErrorsException {
76 injectMembers(instance, errors, context);
77 return null;
78 }
79 });
80
limpbizkita843a952009-04-08 22:24:55 +000081 notifyListeners(instance, errors);
82 }
83
84 void notifyListeners(T instance, Errors errors) throws ErrorsException {
85 int numErrorsBefore = errors.size();
limpbizkit7cef5b02009-03-29 21:16:51 +000086 for (InjectionListener<? super T> injectionListener : injectionListeners) {
87 try {
88 injectionListener.afterInjection(instance);
89 } catch (RuntimeException e) {
limpbizkita843a952009-04-08 22:24:55 +000090 errors.errorNotifyingInjectionListener(injectionListener, typeLiteral, e);
limpbizkit7cef5b02009-03-29 21:16:51 +000091 }
92 }
limpbizkita843a952009-04-08 22:24:55 +000093 errors.throwIfNewErrors(numErrorsBefore);
limpbizkit7cef5b02009-03-29 21:16:51 +000094 }
95
96 void injectMembers(T t, Errors errors, InternalContext context) {
limpbizkite89c49e2009-05-06 01:02:14 +000097 // optimization: use manual for/each to save allocating an iterator here
98 for (int i = 0, size = memberInjectors.size(); i < size; i++) {
99 memberInjectors.get(i).inject(errors, context, t);
limpbizkit7cef5b02009-03-29 21:16:51 +0000100 }
limpbizkitee792462009-04-08 23:48:49 +0000101
limpbizkite89c49e2009-05-06 01:02:14 +0000102 // optimization: use manual for/each to save allocating an iterator here
103 for (int i = 0, size = userMembersInjectors.size(); i < size; i++) {
104 MembersInjector<? super T> userMembersInjector = userMembersInjectors.get(i);
limpbizkitee792462009-04-08 23:48:49 +0000105 try {
106 userMembersInjector.injectMembers(t);
107 } catch (RuntimeException e) {
108 errors.errorInUserInjector(userMembersInjector, typeLiteral, e);
109 }
110 }
limpbizkit7cef5b02009-03-29 21:16:51 +0000111 }
112
113 @Override public String toString() {
114 return "MembersInjector<" + typeLiteral + ">";
115 }
116
117 public ImmutableSet<InjectionPoint> getInjectionPoints() {
118 ImmutableSet.Builder<InjectionPoint> builder = ImmutableSet.builder();
119 for (SingleMemberInjector memberInjector : memberInjectors) {
120 builder.add(memberInjector.getInjectionPoint());
121 }
122 return builder.build();
123 }
124
limpbizkiteb405132009-04-14 00:50:25 +0000125 /*if[AOP]*/
limpbizkita843a952009-04-08 22:24:55 +0000126 public ImmutableList<MethodAspect> getAddedAspects() {
127 return addedAspects;
limpbizkit7cef5b02009-03-29 21:16:51 +0000128 }
limpbizkiteb405132009-04-14 00:50:25 +0000129 /*end[AOP]*/
limpbizkit7cef5b02009-03-29 21:16:51 +0000130}