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.ImmutableSet; 22 import com.google.inject.Binder; 23 import com.google.inject.ConfigurationException; 24 import com.google.inject.Key; 25 import com.google.inject.Provider; 26 import com.google.inject.TypeLiteral; 27 import com.google.inject.binder.AnnotatedBindingBuilder; 28 import com.google.inject.binder.ScopedBindingBuilder; 29 import com.google.inject.spi.Element; 30 import com.google.inject.spi.InjectionPoint; 31 import com.google.inject.spi.Message; 32 33 import java.lang.annotation.Annotation; 34 import java.lang.reflect.Constructor; 35 import java.util.List; 36 import java.util.Set; 37 38 /** 39 * Bind a non-constant key. 40 * 41 * @author jessewilson (at) google.com (Jesse Wilson) 42 */ 43 public class BindingBuilder<T> extends AbstractBindingBuilder<T> 44 implements AnnotatedBindingBuilder<T> { 45 46 public BindingBuilder(Binder binder, List<Element> elements, Object source, Key<T> key) { 47 super(binder, elements, source, key); 48 } 49 50 public BindingBuilder<T> annotatedWith(Class<? extends Annotation> annotationType) { 51 annotatedWithInternal(annotationType); 52 return this; 53 } 54 55 public BindingBuilder<T> annotatedWith(Annotation annotation) { 56 annotatedWithInternal(annotation); 57 return this; 58 } 59 60 public BindingBuilder<T> to(Class<? extends T> implementation) { 61 return to(Key.get(implementation)); 62 } 63 64 public BindingBuilder<T> to(TypeLiteral<? extends T> implementation) { 65 return to(Key.get(implementation)); 66 } 67 68 public BindingBuilder<T> to(Key<? extends T> linkedKey) { 69 checkNotNull(linkedKey, "linkedKey"); 70 checkNotTargetted(); 71 BindingImpl<T> base = getBinding(); 72 setBinding(new LinkedBindingImpl<T>( 73 base.getSource(), base.getKey(), base.getScoping(), linkedKey)); 74 return this; 75 } 76 77 public void toInstance(T instance) { 78 checkNotTargetted(); 79 80 // lookup the injection points, adding any errors to the binder's errors list 81 Set<InjectionPoint> injectionPoints; 82 if (instance != null) { 83 try { 84 injectionPoints = InjectionPoint.forInstanceMethodsAndFields(instance.getClass()); 85 } catch (ConfigurationException e) { 86 copyErrorsToBinder(e); 87 injectionPoints = e.getPartialValue(); 88 } 89 } else { 90 binder.addError(BINDING_TO_NULL); 91 injectionPoints = ImmutableSet.of(); 92 } 93 94 BindingImpl<T> base = getBinding(); 95 setBinding(new InstanceBindingImpl<T>( 96 base.getSource(), base.getKey(), Scoping.EAGER_SINGLETON, injectionPoints, instance)); 97 } 98 99 public BindingBuilder<T> toProvider(Provider<? extends T> provider) { 100 return toProvider((javax.inject.Provider<T>) provider); 101 } 102 103 public BindingBuilder<T> toProvider(javax.inject.Provider<? extends T> provider) { 104 checkNotNull(provider, "provider"); 105 checkNotTargetted(); 106 107 // lookup the injection points, adding any errors to the binder's errors list 108 Set<InjectionPoint> injectionPoints; 109 try { 110 injectionPoints = InjectionPoint.forInstanceMethodsAndFields(provider.getClass()); 111 } catch (ConfigurationException e) { 112 copyErrorsToBinder(e); 113 injectionPoints = e.getPartialValue(); 114 } 115 116 BindingImpl<T> base = getBinding(); 117 setBinding(new ProviderInstanceBindingImpl<T>( 118 base.getSource(), base.getKey(), base.getScoping(), injectionPoints, provider)); 119 return this; 120 } 121 122 public BindingBuilder<T> toProvider( 123 Class<? extends javax.inject.Provider<? extends T>> providerType) { 124 return toProvider(Key.get(providerType)); 125 } 126 127 public BindingBuilder<T> toProvider( 128 TypeLiteral<? extends javax.inject.Provider<? extends T>> providerType) { 129 return toProvider(Key.get(providerType)); 130 } 131 132 public BindingBuilder<T> toProvider( 133 Key<? extends javax.inject.Provider<? extends T>> providerKey) { 134 checkNotNull(providerKey, "providerKey"); 135 checkNotTargetted(); 136 137 BindingImpl<T> base = getBinding(); 138 setBinding(new LinkedProviderBindingImpl<T>( 139 base.getSource(), base.getKey(), base.getScoping(), providerKey)); 140 return this; 141 } 142 143 public <S extends T> ScopedBindingBuilder toConstructor(Constructor<S> constructor) { 144 return toConstructor(constructor, TypeLiteral.get(constructor.getDeclaringClass())); 145 } 146 147 public <S extends T> ScopedBindingBuilder toConstructor(Constructor<S> constructor, 148 TypeLiteral<? extends S> type) { 149 checkNotNull(constructor, "constructor"); 150 checkNotNull(type, "type"); 151 checkNotTargetted(); 152 153 BindingImpl<T> base = getBinding(); 154 155 Set<InjectionPoint> injectionPoints; 156 try { 157 injectionPoints = InjectionPoint.forInstanceMethodsAndFields(type); 158 } catch (ConfigurationException e) { 159 copyErrorsToBinder(e); 160 injectionPoints = e.getPartialValue(); 161 } 162 163 try { 164 InjectionPoint constructorPoint = InjectionPoint.forConstructor(constructor, type); 165 setBinding(new ConstructorBindingImpl<T>(base.getKey(), base.getSource(), base.getScoping(), 166 constructorPoint, injectionPoints)); 167 } catch (ConfigurationException e) { 168 copyErrorsToBinder(e); 169 } 170 171 return this; 172 } 173 174 @Override public String toString() { 175 return "BindingBuilder<" + getBinding().getKey().getTypeLiteral() + ">"; 176 } 177 178 private void copyErrorsToBinder(ConfigurationException e) { 179 for (Message message : e.getErrorMessages()) { 180 binder.addError(message); 181 } 182 } 183 } 184