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