14e11457f34addf5d10fe0c31cefd54c75c37b540sberlin/** 24e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * Copyright (C) 2011 Google Inc. 34e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * 44e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * Licensed under the Apache License, Version 2.0 (the "License"); 54e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * you may not use this file except in compliance with the License. 64e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * You may obtain a copy of the License at 74e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * 84e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * http://www.apache.org/licenses/LICENSE-2.0 94e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * 104e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * Unless required by applicable law or agreed to in writing, software 114e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * distributed under the License is distributed on an "AS IS" BASIS, 124e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * See the License for the specific language governing permissions and 144e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * limitations under the License. 154e11457f34addf5d10fe0c31cefd54c75c37b540sberlin */ 164e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 174e11457f34addf5d10fe0c31cefd54c75c37b540sberlinpackage com.google.inject.internal; 184e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 19b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport com.google.common.collect.ImmutableSet; 204e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.AbstractModule; 214e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.Binder; 224e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.Binding; 234e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.Injector; 244e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.Key; 254e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.MembersInjector; 264e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.Module; 274e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.Provider; 284e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.Scope; 29bf2b16c06a5ff7c099fe60f9a46cfb130ce45962Christian Edward Gruberimport com.google.inject.Stage; 304e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.TypeLiteral; 314e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.spi.DefaultBindingTargetVisitor; 324e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 33b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport java.util.Set; 34b7a02b02d81c830d148355c90bc309bcd66fb592sberlin 354e11457f34addf5d10fe0c31cefd54c75c37b540sberlin/** 364e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * Guarantees that processing of Binding elements happens in a sane way. 37ec76179f50f9d8c340b311c6b019c00526566b66sberlin * 384e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * @author sameb@google.com (Sam Berlin) 394e11457f34addf5d10fe0c31cefd54c75c37b540sberlin */ 404e11457f34addf5d10fe0c31cefd54c75c37b540sberlinabstract class AbstractBindingProcessor extends AbstractProcessor { 414e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 424e11457f34addf5d10fe0c31cefd54c75c37b540sberlin // It's unfortunate that we have to maintain a blacklist of specific 434e11457f34addf5d10fe0c31cefd54c75c37b540sberlin // classes, but we can't easily block the whole package because of 444e11457f34addf5d10fe0c31cefd54c75c37b540sberlin // all our unit tests. 454e11457f34addf5d10fe0c31cefd54c75c37b540sberlin private static final Set<Class<?>> FORBIDDEN_TYPES = ImmutableSet.<Class<?>>of( 464e11457f34addf5d10fe0c31cefd54c75c37b540sberlin AbstractModule.class, 474e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Binder.class, 484e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Binding.class, 494e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Injector.class, 504e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Key.class, 514e11457f34addf5d10fe0c31cefd54c75c37b540sberlin MembersInjector.class, 524e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Module.class, 534e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Provider.class, 544e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Scope.class, 55bf2b16c06a5ff7c099fe60f9a46cfb130ce45962Christian Edward Gruber Stage.class, 564e11457f34addf5d10fe0c31cefd54c75c37b540sberlin TypeLiteral.class); 57ec76179f50f9d8c340b311c6b019c00526566b66sberlin 584e11457f34addf5d10fe0c31cefd54c75c37b540sberlin protected final ProcessedBindingData bindingData; 59ec76179f50f9d8c340b311c6b019c00526566b66sberlin 604e11457f34addf5d10fe0c31cefd54c75c37b540sberlin AbstractBindingProcessor(Errors errors, ProcessedBindingData bindingData) { 614e11457f34addf5d10fe0c31cefd54c75c37b540sberlin super(errors); 624e11457f34addf5d10fe0c31cefd54c75c37b540sberlin this.bindingData = bindingData; 634e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 644e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 654e11457f34addf5d10fe0c31cefd54c75c37b540sberlin protected <T> UntargettedBindingImpl<T> invalidBinding( 664e11457f34addf5d10fe0c31cefd54c75c37b540sberlin InjectorImpl injector, Key<T> key, Object source) { 674e11457f34addf5d10fe0c31cefd54c75c37b540sberlin return new UntargettedBindingImpl<T>(injector, key, source); 684e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 69ec76179f50f9d8c340b311c6b019c00526566b66sberlin 704e11457f34addf5d10fe0c31cefd54c75c37b540sberlin protected void putBinding(BindingImpl<?> binding) { 714e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Key<?> key = binding.getKey(); 724e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 734e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Class<?> rawType = key.getTypeLiteral().getRawType(); 744e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if (FORBIDDEN_TYPES.contains(rawType)) { 754e11457f34addf5d10fe0c31cefd54c75c37b540sberlin errors.cannotBindToGuiceType(rawType.getSimpleName()); 764e11457f34addf5d10fe0c31cefd54c75c37b540sberlin return; 774e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 784e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 794e11457f34addf5d10fe0c31cefd54c75c37b540sberlin BindingImpl<?> original = injector.getExistingBinding(key); 804e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if (original != null) { 814e11457f34addf5d10fe0c31cefd54c75c37b540sberlin // If it failed because of an explicit duplicate binding... 824e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if (injector.state.getExplicitBinding(key) != null) { 834e11457f34addf5d10fe0c31cefd54c75c37b540sberlin try { 844e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(!isOkayDuplicate(original, binding, injector.state)) { 854e11457f34addf5d10fe0c31cefd54c75c37b540sberlin errors.bindingAlreadySet(key, original.getSource()); 864e11457f34addf5d10fe0c31cefd54c75c37b540sberlin return; 874e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 884e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } catch(Throwable t) { 894e11457f34addf5d10fe0c31cefd54c75c37b540sberlin errors.errorCheckingDuplicateBinding(key, original.getSource(), t); 904e11457f34addf5d10fe0c31cefd54c75c37b540sberlin return; 914e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 924e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } else { 934e11457f34addf5d10fe0c31cefd54c75c37b540sberlin // Otherwise, it failed because of a duplicate JIT binding 944e11457f34addf5d10fe0c31cefd54c75c37b540sberlin // in the parent 954e11457f34addf5d10fe0c31cefd54c75c37b540sberlin errors.jitBindingAlreadySet(key); 964e11457f34addf5d10fe0c31cefd54c75c37b540sberlin return; 974e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 984e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 994e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 1004e11457f34addf5d10fe0c31cefd54c75c37b540sberlin // prevent the parent from creating a JIT binding for this key 101d57f8ece5508afc66c4768396c54b412dc9f2cc2Sam Berlin injector.state.parent().blacklist(key, injector.state, binding.getSource()); 1024e11457f34addf5d10fe0c31cefd54c75c37b540sberlin injector.state.putBinding(key, binding); 1034e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 1044e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 1054e11457f34addf5d10fe0c31cefd54c75c37b540sberlin /** 1064e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * We tolerate duplicate bindings if one exposes the other or if the two bindings 1074e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * are considered duplicates (see {@link Bindings#areDuplicates(BindingImpl, BindingImpl)}. 1084e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * 1094e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * @param original the binding in the parent injector (candidate for an exposing binding) 1104e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * @param binding the binding to check (candidate for the exposed binding) 1114e11457f34addf5d10fe0c31cefd54c75c37b540sberlin */ 1124e11457f34addf5d10fe0c31cefd54c75c37b540sberlin private boolean isOkayDuplicate(BindingImpl<?> original, BindingImpl<?> binding, State state) { 1134e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if (original instanceof ExposedBindingImpl) { 1144e11457f34addf5d10fe0c31cefd54c75c37b540sberlin ExposedBindingImpl exposed = (ExposedBindingImpl) original; 1154e11457f34addf5d10fe0c31cefd54c75c37b540sberlin InjectorImpl exposedFrom = (InjectorImpl) exposed.getPrivateElements().getInjector(); 1164e11457f34addf5d10fe0c31cefd54c75c37b540sberlin return (exposedFrom == binding.getInjector()); 1174e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } else { 1184e11457f34addf5d10fe0c31cefd54c75c37b540sberlin original = (BindingImpl<?>)state.getExplicitBindingsThisLevel().get(binding.getKey()); 1194e11457f34addf5d10fe0c31cefd54c75c37b540sberlin // If no original at this level, the original was on a parent, and we don't 1204e11457f34addf5d10fe0c31cefd54c75c37b540sberlin // allow deduplication between parents & children. 1214e11457f34addf5d10fe0c31cefd54c75c37b540sberlin if(original == null) { 1224e11457f34addf5d10fe0c31cefd54c75c37b540sberlin return false; 1234e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } else { 1244e11457f34addf5d10fe0c31cefd54c75c37b540sberlin return original.equals(binding); 1254e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 1264e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 1274e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 128ec76179f50f9d8c340b311c6b019c00526566b66sberlin 1294e11457f34addf5d10fe0c31cefd54c75c37b540sberlin private <T> void validateKey(Object source, Key<T> key) { 1304e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Annotations.checkForMisplacedScopeAnnotations( 1314e11457f34addf5d10fe0c31cefd54c75c37b540sberlin key.getTypeLiteral().getRawType(), source, errors); 1324e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 133ec76179f50f9d8c340b311c6b019c00526566b66sberlin 134ec76179f50f9d8c340b311c6b019c00526566b66sberlin /** 1354e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * Processor for visiting bindings. Each overriden method that wants to 1364e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * actually process the binding should call prepareBinding first. 1374e11457f34addf5d10fe0c31cefd54c75c37b540sberlin */ 1384e11457f34addf5d10fe0c31cefd54c75c37b540sberlin abstract class Processor<T, V> extends DefaultBindingTargetVisitor<T, V> { 1394e11457f34addf5d10fe0c31cefd54c75c37b540sberlin final Object source; 1404e11457f34addf5d10fe0c31cefd54c75c37b540sberlin final Key<T> key; 1414e11457f34addf5d10fe0c31cefd54c75c37b540sberlin final Class<? super T> rawType; 1424e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Scoping scoping; 143ec76179f50f9d8c340b311c6b019c00526566b66sberlin 1444e11457f34addf5d10fe0c31cefd54c75c37b540sberlin Processor(BindingImpl<T> binding) { 1454e11457f34addf5d10fe0c31cefd54c75c37b540sberlin source = binding.getSource(); 1464e11457f34addf5d10fe0c31cefd54c75c37b540sberlin key = binding.getKey(); 1474e11457f34addf5d10fe0c31cefd54c75c37b540sberlin rawType = key.getTypeLiteral().getRawType(); 1484e11457f34addf5d10fe0c31cefd54c75c37b540sberlin scoping = binding.getScoping(); 1494e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 150ec76179f50f9d8c340b311c6b019c00526566b66sberlin 151ec76179f50f9d8c340b311c6b019c00526566b66sberlin protected void prepareBinding() { 1524e11457f34addf5d10fe0c31cefd54c75c37b540sberlin validateKey(source, key); 1534e11457f34addf5d10fe0c31cefd54c75c37b540sberlin scoping = Scoping.makeInjectable(scoping, injector, errors); 1544e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 1554e11457f34addf5d10fe0c31cefd54c75c37b540sberlin 1564e11457f34addf5d10fe0c31cefd54c75c37b540sberlin protected void scheduleInitialization(final BindingImpl<?> binding) { 1574e11457f34addf5d10fe0c31cefd54c75c37b540sberlin bindingData.addUninitializedBinding(new Runnable() { 1584e11457f34addf5d10fe0c31cefd54c75c37b540sberlin public void run() { 1594e11457f34addf5d10fe0c31cefd54c75c37b540sberlin try { 1604e11457f34addf5d10fe0c31cefd54c75c37b540sberlin binding.getInjector().initializeBinding(binding, errors.withSource(source)); 1614e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } catch (ErrorsException e) { 1624e11457f34addf5d10fe0c31cefd54c75c37b540sberlin errors.merge(e.getErrors()); 1634e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 1644e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 1654e11457f34addf5d10fe0c31cefd54c75c37b540sberlin }); 1664e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 1674e11457f34addf5d10fe0c31cefd54c75c37b540sberlin } 1684e11457f34addf5d10fe0c31cefd54c75c37b540sberlin} 169