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 17package com.google.inject.internal; 18 19import com.google.inject.Binder; 20import com.google.inject.Binding; 21import com.google.inject.Key; 22import com.google.inject.Provider; 23import com.google.inject.spi.ConstructorBinding; 24import com.google.inject.spi.ConvertedConstantBinding; 25import com.google.inject.spi.ExposedBinding; 26import com.google.inject.spi.InjectionPoint; 27import com.google.inject.spi.InstanceBinding; 28import com.google.inject.spi.LinkedKeyBinding; 29import com.google.inject.spi.PrivateElements; 30import com.google.inject.spi.ProviderBinding; 31import com.google.inject.spi.ProviderInstanceBinding; 32import com.google.inject.spi.ProviderKeyBinding; 33import com.google.inject.spi.UntargettedBinding; 34 35import java.util.Set; 36 37/** 38 * Handles {@link Binder#bind} and {@link Binder#bindConstant} elements. 39 * 40 * @author crazybob@google.com (Bob Lee) 41 * @author jessewilson@google.com (Jesse Wilson) 42 */ 43final class BindingProcessor extends AbstractBindingProcessor { 44 45 private final Initializer initializer; 46 47 BindingProcessor(Errors errors, Initializer initializer, ProcessedBindingData bindingData) { 48 super(errors, bindingData); 49 this.initializer = initializer; 50 } 51 52 @Override public <T> Boolean visit(Binding<T> command) { 53 Class<?> rawType = command.getKey().getTypeLiteral().getRawType(); 54 if (Void.class.equals(rawType)) { 55 if (command instanceof ProviderInstanceBinding 56 && ((ProviderInstanceBinding) command).getUserSuppliedProvider() 57 instanceof ProviderMethod) { 58 errors.voidProviderMethod(); 59 } else { 60 errors.missingConstantValues(); 61 } 62 return true; 63 } 64 65 if (rawType == Provider.class) { 66 errors.bindingToProvider(); 67 return true; 68 } 69 70 return command.acceptTargetVisitor(new Processor<T, Boolean>((BindingImpl<T>)command) { 71 @Override 72 public Boolean visit(ConstructorBinding<? extends T> binding) { 73 prepareBinding(); 74 try { 75 ConstructorBindingImpl<T> onInjector = ConstructorBindingImpl.create(injector, key, 76 binding.getConstructor(), source, scoping, errors, false, false); 77 scheduleInitialization(onInjector); 78 putBinding(onInjector); 79 } catch (ErrorsException e) { 80 errors.merge(e.getErrors()); 81 putBinding(invalidBinding(injector, key, source)); 82 } 83 return true; 84 } 85 86 @Override 87 public Boolean visit(InstanceBinding<? extends T> binding) { 88 prepareBinding(); 89 Set<InjectionPoint> injectionPoints = binding.getInjectionPoints(); 90 T instance = binding.getInstance(); 91 @SuppressWarnings("unchecked") // safe to cast to binding<T> because 92 // the processor was constructed w/ it 93 Initializable<T> ref = initializer.requestInjection( 94 injector, instance, (Binding<T>) binding, source, injectionPoints); 95 ConstantFactory<? extends T> factory = new ConstantFactory<T>(ref); 96 InternalFactory<? extends T> scopedFactory 97 = Scoping.scope(key, injector, factory, source, scoping); 98 putBinding(new InstanceBindingImpl<T>(injector, key, source, scopedFactory, injectionPoints, 99 instance)); 100 return true; 101 } 102 103 @Override 104 public Boolean visit(ProviderInstanceBinding<? extends T> binding) { 105 prepareBinding(); 106 javax.inject.Provider<? extends T> provider = binding.getUserSuppliedProvider(); 107 Set<InjectionPoint> injectionPoints = binding.getInjectionPoints(); 108 Initializable<? extends javax.inject.Provider<? extends T>> initializable = 109 initializer.<javax.inject.Provider<? extends T>>requestInjection( 110 injector, provider, null, source, injectionPoints); 111 // always visited with Binding<T> 112 @SuppressWarnings("unchecked") 113 InternalFactory<T> factory = new InternalFactoryToInitializableAdapter<T>( 114 initializable, source, 115 injector.provisionListenerStore.get((ProviderInstanceBinding<T>)binding)); 116 InternalFactory<? extends T> scopedFactory 117 = Scoping.scope(key, injector, factory, source, scoping); 118 putBinding(new ProviderInstanceBindingImpl<T>(injector, key, source, scopedFactory, scoping, 119 provider, injectionPoints)); 120 return true; 121 } 122 123 @Override 124 public Boolean visit(ProviderKeyBinding<? extends T> binding) { 125 prepareBinding(); 126 Key<? extends javax.inject.Provider<? extends T>> providerKey = binding.getProviderKey(); 127 // always visited with Binding<T> 128 @SuppressWarnings("unchecked") 129 BoundProviderFactory<T> boundProviderFactory = new BoundProviderFactory<T>( 130 injector, providerKey, source, 131 injector.provisionListenerStore.get((ProviderKeyBinding<T>) binding)); 132 bindingData.addCreationListener(boundProviderFactory); 133 InternalFactory<? extends T> scopedFactory = Scoping.scope( 134 key, injector, (InternalFactory<? extends T>) boundProviderFactory, source, scoping); 135 putBinding(new LinkedProviderBindingImpl<T>( 136 injector, key, source, scopedFactory, scoping, providerKey)); 137 return true; 138 } 139 140 @Override 141 public Boolean visit(LinkedKeyBinding<? extends T> binding) { 142 prepareBinding(); 143 Key<? extends T> linkedKey = binding.getLinkedKey(); 144 if (key.equals(linkedKey)) { 145 errors.recursiveBinding(); 146 } 147 148 FactoryProxy<T> factory = new FactoryProxy<T>(injector, key, linkedKey, source); 149 bindingData.addCreationListener(factory); 150 InternalFactory<? extends T> scopedFactory 151 = Scoping.scope(key, injector, factory, source, scoping); 152 putBinding( 153 new LinkedBindingImpl<T>(injector, key, source, scopedFactory, scoping, linkedKey)); 154 return true; 155 } 156 157 @Override 158 public Boolean visit(UntargettedBinding<? extends T> untargetted) { 159 return false; 160 } 161 162 @Override 163 public Boolean visit(ExposedBinding<? extends T> binding) { 164 throw new IllegalArgumentException("Cannot apply a non-module element"); 165 } 166 167 @Override 168 public Boolean visit(ConvertedConstantBinding<? extends T> binding) { 169 throw new IllegalArgumentException("Cannot apply a non-module element"); 170 } 171 172 @Override 173 public Boolean visit(ProviderBinding<? extends T> binding) { 174 throw new IllegalArgumentException("Cannot apply a non-module element"); 175 } 176 177 @Override 178 protected Boolean visitOther(Binding<? extends T> binding) { 179 throw new IllegalStateException("BindingProcessor should override all visitations"); 180 } 181 }); 182 } 183 184 @Override public Boolean visit(PrivateElements privateElements) { 185 for (Key<?> key : privateElements.getExposedKeys()) { 186 bindExposed(privateElements, key); 187 } 188 return false; // leave the private elements for the PrivateElementsProcessor to handle 189 } 190 191 private <T> void bindExposed(PrivateElements privateElements, Key<T> key) { 192 ExposedKeyFactory<T> exposedKeyFactory = new ExposedKeyFactory<T>(key, privateElements); 193 bindingData.addCreationListener(exposedKeyFactory); 194 putBinding(new ExposedBindingImpl<T>( 195 injector, privateElements.getExposedSource(key), key, exposedKeyFactory, privateElements)); 196 } 197} 198