• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 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 
17 package com.google.inject.internal;
18 
19 import static com.google.common.base.Preconditions.checkNotNull;
20 
21 import com.google.common.collect.ImmutableList;
22 import com.google.common.collect.ImmutableMap;
23 import com.google.common.collect.Lists;
24 import com.google.common.collect.Maps;
25 import com.google.inject.Binding;
26 import com.google.inject.Key;
27 import com.google.inject.Scope;
28 import com.google.inject.TypeLiteral;
29 import com.google.inject.spi.ModuleAnnotatedMethodScannerBinding;
30 import com.google.inject.spi.ProvisionListenerBinding;
31 import com.google.inject.spi.ScopeBinding;
32 import com.google.inject.spi.TypeConverterBinding;
33 import com.google.inject.spi.TypeListenerBinding;
34 import java.lang.annotation.Annotation;
35 import java.util.Collections;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.Set;
39 
40 /** @author jessewilson@google.com (Jesse Wilson) */
41 final class InheritingState implements State {
42 
43   private final State parent;
44 
45   // Must be a linked hashmap in order to preserve order of bindings in Modules.
46   private final Map<Key<?>, Binding<?>> explicitBindingsMutable = Maps.newLinkedHashMap();
47   private final Map<Key<?>, Binding<?>> explicitBindings =
48       Collections.unmodifiableMap(explicitBindingsMutable);
49   private final Map<Class<? extends Annotation>, ScopeBinding> scopes = Maps.newHashMap();
50   private final List<TypeConverterBinding> converters = Lists.newArrayList();
51   /*if[AOP]*/
52   private final List<MethodAspect> methodAspects = Lists.newArrayList();
53   /*end[AOP]*/
54   private final List<TypeListenerBinding> typeListenerBindings = Lists.newArrayList();
55   private final List<ProvisionListenerBinding> provisionListenerBindings = Lists.newArrayList();
56   private final List<ModuleAnnotatedMethodScannerBinding> scannerBindings = Lists.newArrayList();
57   private final WeakKeySet blacklistedKeys;
58   private final Object lock;
59 
InheritingState(State parent)60   InheritingState(State parent) {
61     this.parent = checkNotNull(parent, "parent");
62     this.lock = (parent == State.NONE) ? this : parent.lock();
63     this.blacklistedKeys = new WeakKeySet(lock);
64   }
65 
66   @Override
parent()67   public State parent() {
68     return parent;
69   }
70 
71   @Override
72   @SuppressWarnings("unchecked") // we only put in BindingImpls that match their key types
getExplicitBinding(Key<T> key)73   public <T> BindingImpl<T> getExplicitBinding(Key<T> key) {
74     Binding<?> binding = explicitBindings.get(key);
75     return binding != null ? (BindingImpl<T>) binding : parent.getExplicitBinding(key);
76   }
77 
78   @Override
getExplicitBindingsThisLevel()79   public Map<Key<?>, Binding<?>> getExplicitBindingsThisLevel() {
80     return explicitBindings;
81   }
82 
83   @Override
putBinding(Key<?> key, BindingImpl<?> binding)84   public void putBinding(Key<?> key, BindingImpl<?> binding) {
85     explicitBindingsMutable.put(key, binding);
86   }
87 
88   @Override
getScopeBinding(Class<? extends Annotation> annotationType)89   public ScopeBinding getScopeBinding(Class<? extends Annotation> annotationType) {
90     ScopeBinding scopeBinding = scopes.get(annotationType);
91     return scopeBinding != null ? scopeBinding : parent.getScopeBinding(annotationType);
92   }
93 
94   @Override
putScopeBinding(Class<? extends Annotation> annotationType, ScopeBinding scope)95   public void putScopeBinding(Class<? extends Annotation> annotationType, ScopeBinding scope) {
96     scopes.put(annotationType, scope);
97   }
98 
99   @Override
getConvertersThisLevel()100   public Iterable<TypeConverterBinding> getConvertersThisLevel() {
101     return converters;
102   }
103 
104   @Override
addConverter(TypeConverterBinding typeConverterBinding)105   public void addConverter(TypeConverterBinding typeConverterBinding) {
106     converters.add(typeConverterBinding);
107   }
108 
109   @Override
getConverter( String stringValue, TypeLiteral<?> type, Errors errors, Object source)110   public TypeConverterBinding getConverter(
111       String stringValue, TypeLiteral<?> type, Errors errors, Object source) {
112     TypeConverterBinding matchingConverter = null;
113     for (State s = this; s != State.NONE; s = s.parent()) {
114       for (TypeConverterBinding converter : s.getConvertersThisLevel()) {
115         if (converter.getTypeMatcher().matches(type)) {
116           if (matchingConverter != null) {
117             errors.ambiguousTypeConversion(stringValue, source, type, matchingConverter, converter);
118           }
119           matchingConverter = converter;
120         }
121       }
122     }
123     return matchingConverter;
124   }
125 
126   /*if[AOP]*/
127   @Override
addMethodAspect(MethodAspect methodAspect)128   public void addMethodAspect(MethodAspect methodAspect) {
129     methodAspects.add(methodAspect);
130   }
131 
132   @Override
getMethodAspects()133   public ImmutableList<MethodAspect> getMethodAspects() {
134     return new ImmutableList.Builder<MethodAspect>()
135         .addAll(parent.getMethodAspects())
136         .addAll(methodAspects)
137         .build();
138   }
139   /*end[AOP]*/
140 
141   @Override
addTypeListener(TypeListenerBinding listenerBinding)142   public void addTypeListener(TypeListenerBinding listenerBinding) {
143     typeListenerBindings.add(listenerBinding);
144   }
145 
146   @Override
getTypeListenerBindings()147   public List<TypeListenerBinding> getTypeListenerBindings() {
148     List<TypeListenerBinding> parentBindings = parent.getTypeListenerBindings();
149     List<TypeListenerBinding> result =
150         Lists.newArrayListWithCapacity(parentBindings.size() + typeListenerBindings.size());
151     result.addAll(parentBindings);
152     result.addAll(typeListenerBindings);
153     return result;
154   }
155 
156   @Override
addProvisionListener(ProvisionListenerBinding listenerBinding)157   public void addProvisionListener(ProvisionListenerBinding listenerBinding) {
158     provisionListenerBindings.add(listenerBinding);
159   }
160 
161   @Override
getProvisionListenerBindings()162   public List<ProvisionListenerBinding> getProvisionListenerBindings() {
163     List<ProvisionListenerBinding> parentBindings = parent.getProvisionListenerBindings();
164     List<ProvisionListenerBinding> result =
165         Lists.newArrayListWithCapacity(parentBindings.size() + provisionListenerBindings.size());
166     result.addAll(parentBindings);
167     result.addAll(provisionListenerBindings);
168     return result;
169   }
170 
171   @Override
addScanner(ModuleAnnotatedMethodScannerBinding scanner)172   public void addScanner(ModuleAnnotatedMethodScannerBinding scanner) {
173     scannerBindings.add(scanner);
174   }
175 
176   @Override
getScannerBindings()177   public List<ModuleAnnotatedMethodScannerBinding> getScannerBindings() {
178     List<ModuleAnnotatedMethodScannerBinding> parentBindings = parent.getScannerBindings();
179     List<ModuleAnnotatedMethodScannerBinding> result =
180         Lists.newArrayListWithCapacity(parentBindings.size() + scannerBindings.size());
181     result.addAll(parentBindings);
182     result.addAll(scannerBindings);
183     return result;
184   }
185 
186   @Override
blacklist(Key<?> key, State state, Object source)187   public void blacklist(Key<?> key, State state, Object source) {
188     parent.blacklist(key, state, source);
189     blacklistedKeys.add(key, state, source);
190   }
191 
192   @Override
isBlacklisted(Key<?> key)193   public boolean isBlacklisted(Key<?> key) {
194     return blacklistedKeys.contains(key);
195   }
196 
197   @Override
getSourcesForBlacklistedKey(Key<?> key)198   public Set<Object> getSourcesForBlacklistedKey(Key<?> key) {
199     return blacklistedKeys.getSources(key);
200   }
201 
202   @Override
lock()203   public Object lock() {
204     return lock;
205   }
206 
207   @Override
getScopes()208   public Map<Class<? extends Annotation>, Scope> getScopes() {
209     ImmutableMap.Builder<Class<? extends Annotation>, Scope> builder = ImmutableMap.builder();
210     for (Map.Entry<Class<? extends Annotation>, ScopeBinding> entry : scopes.entrySet()) {
211       builder.put(entry.getKey(), entry.getValue().getScope());
212     }
213     return builder.build();
214   }
215 }
216