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