1 16 17 package com.google.inject; 18 19 import com.google.inject.BinderImpl.CreationListener; 20 import com.google.inject.binder.ScopedBindingBuilder; 21 import com.google.inject.binder.AnnotatedBindingBuilder; 22 import com.google.inject.util.Annotations; 23 import com.google.inject.util.Objects; 24 import com.google.inject.util.StackTraceElements; 25 import com.google.inject.util.ToStringBuilder; 26 import java.lang.annotation.Annotation ; 27 import java.util.logging.Level ; 28 import java.util.logging.Logger ; 29 30 33 class BindingBuilderImpl<T> implements AnnotatedBindingBuilder<T> { 34 35 private static final Logger logger 36 = Logger.getLogger(BindingBuilderImpl.class.getName()); 37 38 final Object source; 39 Key<T> key; 40 InternalFactory<? extends T> factory; 41 T instance; 42 Scope scope; 43 boolean preload = false; 44 private BinderImpl binder; 45 46 BindingBuilderImpl(BinderImpl binder, Key<T> key, Object source) { 47 this.binder = binder; 48 this.key = Objects.nonNull(key, "key"); 49 this.source = source; 50 } 51 52 Object getSource() { 53 return source; 54 } 55 56 Key<T> getKey() { 57 return key; 58 } 59 60 public BindingBuilderImpl<T> annotatedWith( 61 Class <? extends Annotation > annotationType) { 62 if (this.key.hasAnnotationType()) { 63 binder.addError(source, ErrorMessages.ANNOTATION_ALREADY_SPECIFIED); 64 } else { 65 boolean retainedAtRuntime = 66 Annotations.isRetainedAtRuntime(annotationType); 67 boolean bindingAnnotation = Key.isBindingAnnotation(annotationType); 68 69 if (!retainedAtRuntime) { 70 binder.addError(StackTraceElements.forType(annotationType), 71 ErrorMessages.MISSING_RUNTIME_RETENTION, binder.source()); 72 } 73 74 if (!bindingAnnotation) { 75 binder.addError(StackTraceElements.forType(annotationType), 76 ErrorMessages.MISSING_BINDING_ANNOTATION, binder.source()); 77 } 78 79 if (retainedAtRuntime && bindingAnnotation) { 80 this.key = Key.get(this.key.getTypeLiteral(), annotationType); 81 } 82 } 83 return this; 84 } 85 86 public BindingBuilderImpl<T> annotatedWith(Annotation annotation) { 87 if (this.key.hasAnnotationType()) { 88 binder.addError(source, ErrorMessages.ANNOTATION_ALREADY_SPECIFIED); 89 } else { 90 Class <? extends Annotation > annotationType = annotation.annotationType(); 91 92 boolean retainedAtRuntime = 93 Annotations.isRetainedAtRuntime(annotationType); 94 boolean bindingAnnotation = Key.isBindingAnnotation(annotationType); 95 96 if (!retainedAtRuntime) { 97 binder.addError(StackTraceElements.forType(annotationType), 98 ErrorMessages.MISSING_RUNTIME_RETENTION, binder.source()); 99 } 100 101 if (!bindingAnnotation) { 102 binder.addError(StackTraceElements.forType(annotationType), 103 ErrorMessages.MISSING_BINDING_ANNOTATION, binder.source()); 104 } 105 106 if (retainedAtRuntime && bindingAnnotation) { 107 this.key = Key.get(this.key.getTypeLiteral(), annotation); 108 } 109 } 110 return this; 111 } 112 113 public ScopedBindingBuilder to(Class <? extends T> implementation) { 114 return to(TypeLiteral.get(implementation)); 115 } 116 117 public ScopedBindingBuilder to(TypeLiteral<? extends T> implementation) { 118 return to(Key.get(implementation)); 119 } 120 121 public ScopedBindingBuilder to(Key<? extends T> targetKey) { 122 ensureImplementationIsNotSet(); 123 124 if (key.equals(targetKey)) { 125 binder.addError(source, ErrorMessages.RECURSIVE_BINDING); 126 } 127 128 final FactoryProxy<? extends T> factoryProxy = 129 new FactoryProxy<T>(key, targetKey, source); 130 this.factory = factoryProxy; 131 binder.creationListeners.add(factoryProxy); 132 return this; 133 } 134 135 public void toInstance(T instance) { 136 ensureImplementationIsNotSet(); 137 this.instance = Objects.nonNull(instance, "instance"); 138 this.factory = new ConstantFactory<T>(instance); 139 registerInstanceForInjection(instance); 140 if (this.scope != null) { 141 binder.addError(source, ErrorMessages.SINGLE_INSTANCE_AND_SCOPE); 142 } 143 } 144 145 148 BindingBuilderImpl<T> to(InternalFactory<? extends T> factory) { 149 ensureImplementationIsNotSet(); 150 this.factory = factory; 151 return this; 152 } 153 154 public ScopedBindingBuilder toProvider(Provider<? extends T> provider) { 155 ensureImplementationIsNotSet(); 156 this.factory = new InternalFactoryToProviderAdapter<T>(provider, source); 157 registerInstanceForInjection(provider); 158 return this; 159 } 160 161 public BindingBuilderImpl<T> toProvider( 162 Class <? extends Provider<? extends T>> providerType) { 163 return toProvider(Key.get(providerType)); 164 } 165 166 public BindingBuilderImpl<T> toProvider( 167 Key<? extends Provider<? extends T>> providerKey) { 168 ensureImplementationIsNotSet(); 169 170 final BoundProviderFactory<T> boundProviderFactory = 171 new BoundProviderFactory<T>(providerKey, source); 172 binder.creationListeners.add(boundProviderFactory); 173 this.factory = boundProviderFactory; 174 175 return this; 176 } 177 178 181 private void ensureImplementationIsNotSet() { 182 if (factory != null) { 183 binder.addError(source, ErrorMessages.IMPLEMENTATION_ALREADY_SET); 184 } 185 } 186 187 public void in(Class <? extends Annotation > scopeAnnotation) { 188 ensureScopeNotSet(); 190 191 this.scope = binder.scopes.get( 194 Objects.nonNull(scopeAnnotation, "scope annotation")); 195 if (this.scope == null) { 196 binder.addError(source, ErrorMessages.SCOPE_NOT_FOUND, 197 "@" + scopeAnnotation.getSimpleName()); 198 } 199 } 200 201 public void in(Scope scope) { 202 ensureScopeNotSet(); 203 this.scope = Objects.nonNull(scope, "scope"); 204 } 205 206 private void ensureScopeNotSet() { 207 if (this.instance != null) { 209 binder.addError(source, ErrorMessages.SINGLE_INSTANCE_AND_SCOPE); 210 return; 211 } 212 213 if (this.scope != null) { 214 binder.addError(source, ErrorMessages.SCOPE_ALREADY_SET); 215 } 216 } 217 218 public void asEagerSingleton() { 219 in(Scopes.SINGLETON); 220 this.preload = true; 221 } 222 223 boolean shouldPreload() { 224 return preload; 225 } 226 227 InternalFactory<? extends T> getInternalFactory(InjectorImpl injector) { 228 if (this.factory == null && !key.hasAnnotationType()) { 229 final ImplicitImplementation<T> implicitImplementation = 231 new ImplicitImplementation<T>(key, scope, source); 232 binder.creationListeners.add(implicitImplementation); 233 234 if (this.scope == null) { 236 this.scope = Scopes.getScopeForType( 239 key.getTypeLiteral().getRawType(), binder.scopes, IGNORE_ERRORS); 240 } 241 242 return implicitImplementation; 243 } 244 245 return Scopes.scope(this.key, injector, this.factory, scope); 246 } 247 248 boolean isSingletonScoped() { 249 return this.scope == Scopes.SINGLETON; 250 } 251 252 void registerInstanceForInjection(final Object o) { 253 binder.instanceInjectors.add(new CreationListener() { 254 public void notify(InjectorImpl injector) { 255 try { 256 injector.injectMembers(o); 257 } 258 catch (Exception e) { 259 String className = e.getClass().getSimpleName(); 260 String message = ErrorMessages.getRootMessage(e); 261 String logMessage = String.format( 262 ErrorMessages.ERROR_INJECTING_MEMBERS, o, message); 263 logger.log(Level.INFO, logMessage, e); 264 binder.addError(source, ErrorMessages.ERROR_INJECTING_MEMBERS_SEE_LOG, 265 className, o, message); 266 } 267 } 268 }); 269 } 270 271 275 private static class FactoryProxy<T> implements InternalFactory<T>, 276 CreationListener { 277 278 private final Key<T> key; 279 private final Key<? extends T> targetKey; 280 private final Object source; 281 282 InternalFactory<? extends T> targetFactory; 283 284 FactoryProxy(Key<T> key, Key<? extends T> targetKey, Object source) { 285 this.key = key; 286 this.targetKey = targetKey; 287 this.source = source; 288 } 289 290 public void notify(final InjectorImpl injector) { 291 injector.withDefaultSource(source, new Runnable () { 292 public void run() { 293 targetFactory = injector.getInternalFactory(null, targetKey); 294 } 295 }); 296 } 297 298 public T get(InternalContext context) { 299 return targetFactory.get(context); 300 } 301 302 public String toString() { 303 return new ToStringBuilder(FactoryProxy.class) 304 .add("key", key) 305 .add("provider", targetFactory) 306 .toString(); 307 } 308 } 309 310 private static class ImplicitImplementation<T> implements InternalFactory<T>, 311 CreationListener { 312 313 private final Key<T> key; 314 private final Object source; 315 private final Scope scope; 316 InternalFactory<? extends T> implicitFactory; 317 318 ImplicitImplementation(Key<T> key, Scope scope, Object source) { 319 this.key = key; 320 this.scope = scope; 321 this.source = source; 322 } 323 324 public void notify(final InjectorImpl injector) { 325 injector.withDefaultSource(source, new Runnable () { 326 public void run() { 327 implicitFactory = injector.getImplicitBinding(null, 328 (Class ) key.getTypeLiteral().getRawType(), scope); 329 } 330 }); 331 } 332 333 public T get(InternalContext context) { 334 return implicitFactory.get(context); 335 } 336 337 public String toString() { 338 return new ToStringBuilder(FactoryProxy.class) 339 .add("key", key) 340 .add("provider", implicitFactory) 341 .toString(); 342 } 343 } 344 345 static ErrorHandler IGNORE_ERRORS = new ErrorHandler() { 346 public void handle(Object source, String message) {} 347 public void handle(Object source, String message, Object ... arguments) {} 348 }; 349 } 350 | Popular Tags |