1 /** 2 * Copyright (C) 2011 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 com.google.common.collect.ImmutableSet; 20 import com.google.inject.AbstractModule; 21 import com.google.inject.Binder; 22 import com.google.inject.Binding; 23 import com.google.inject.Injector; 24 import com.google.inject.Key; 25 import com.google.inject.MembersInjector; 26 import com.google.inject.Module; 27 import com.google.inject.Provider; 28 import com.google.inject.Scope; 29 import com.google.inject.Stage; 30 import com.google.inject.TypeLiteral; 31 import com.google.inject.spi.DefaultBindingTargetVisitor; 32 33 import java.util.Set; 34 35 /** 36 * Guarantees that processing of Binding elements happens in a sane way. 37 * 38 * @author sameb (at) google.com (Sam Berlin) 39 */ 40 abstract class AbstractBindingProcessor extends AbstractProcessor { 41 42 // It's unfortunate that we have to maintain a blacklist of specific 43 // classes, but we can't easily block the whole package because of 44 // all our unit tests. 45 private static final Set<Class<?>> FORBIDDEN_TYPES = ImmutableSet.<Class<?>>of( 46 AbstractModule.class, 47 Binder.class, 48 Binding.class, 49 Injector.class, 50 Key.class, 51 MembersInjector.class, 52 Module.class, 53 Provider.class, 54 Scope.class, 55 Stage.class, 56 TypeLiteral.class); 57 58 protected final ProcessedBindingData bindingData; 59 60 AbstractBindingProcessor(Errors errors, ProcessedBindingData bindingData) { 61 super(errors); 62 this.bindingData = bindingData; 63 } 64 65 protected <T> UntargettedBindingImpl<T> invalidBinding( 66 InjectorImpl injector, Key<T> key, Object source) { 67 return new UntargettedBindingImpl<T>(injector, key, source); 68 } 69 70 protected void putBinding(BindingImpl<?> binding) { 71 Key<?> key = binding.getKey(); 72 73 Class<?> rawType = key.getTypeLiteral().getRawType(); 74 if (FORBIDDEN_TYPES.contains(rawType)) { 75 errors.cannotBindToGuiceType(rawType.getSimpleName()); 76 return; 77 } 78 79 BindingImpl<?> original = injector.getExistingBinding(key); 80 if (original != null) { 81 // If it failed because of an explicit duplicate binding... 82 if (injector.state.getExplicitBinding(key) != null) { 83 try { 84 if(!isOkayDuplicate(original, binding, injector.state)) { 85 errors.bindingAlreadySet(key, original.getSource()); 86 return; 87 } 88 } catch(Throwable t) { 89 errors.errorCheckingDuplicateBinding(key, original.getSource(), t); 90 return; 91 } 92 } else { 93 // Otherwise, it failed because of a duplicate JIT binding 94 // in the parent 95 errors.jitBindingAlreadySet(key); 96 return; 97 } 98 } 99 100 // prevent the parent from creating a JIT binding for this key 101 injector.state.parent().blacklist(key, injector.state, binding.getSource()); 102 injector.state.putBinding(key, binding); 103 } 104 105 /** 106 * We tolerate duplicate bindings if one exposes the other or if the two bindings 107 * are considered duplicates (see {@link Bindings#areDuplicates(BindingImpl, BindingImpl)}. 108 * 109 * @param original the binding in the parent injector (candidate for an exposing binding) 110 * @param binding the binding to check (candidate for the exposed binding) 111 */ 112 private boolean isOkayDuplicate(BindingImpl<?> original, BindingImpl<?> binding, State state) { 113 if (original instanceof ExposedBindingImpl) { 114 ExposedBindingImpl exposed = (ExposedBindingImpl) original; 115 InjectorImpl exposedFrom = (InjectorImpl) exposed.getPrivateElements().getInjector(); 116 return (exposedFrom == binding.getInjector()); 117 } else { 118 original = (BindingImpl<?>)state.getExplicitBindingsThisLevel().get(binding.getKey()); 119 // If no original at this level, the original was on a parent, and we don't 120 // allow deduplication between parents & children. 121 if(original == null) { 122 return false; 123 } else { 124 return original.equals(binding); 125 } 126 } 127 } 128 129 private <T> void validateKey(Object source, Key<T> key) { 130 Annotations.checkForMisplacedScopeAnnotations( 131 key.getTypeLiteral().getRawType(), source, errors); 132 } 133 134 /** 135 * Processor for visiting bindings. Each overriden method that wants to 136 * actually process the binding should call prepareBinding first. 137 */ 138 abstract class Processor<T, V> extends DefaultBindingTargetVisitor<T, V> { 139 final Object source; 140 final Key<T> key; 141 final Class<? super T> rawType; 142 Scoping scoping; 143 144 Processor(BindingImpl<T> binding) { 145 source = binding.getSource(); 146 key = binding.getKey(); 147 rawType = key.getTypeLiteral().getRawType(); 148 scoping = binding.getScoping(); 149 } 150 151 protected void prepareBinding() { 152 validateKey(source, key); 153 scoping = Scoping.makeInjectable(scoping, injector, errors); 154 } 155 156 protected void scheduleInitialization(final BindingImpl<?> binding) { 157 bindingData.addUninitializedBinding(new Runnable() { 158 public void run() { 159 try { 160 binding.getInjector().initializeBinding(binding, errors.withSource(source)); 161 } catch (ErrorsException e) { 162 errors.merge(e.getErrors()); 163 } 164 } 165 }); 166 } 167 } 168 } 169