• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 import static com.google.common.base.Preconditions.checkState;
21 import static com.google.inject.internal.Errors.checkConfiguration;
22 import static com.google.inject.util.Types.newParameterizedType;
23 import static java.lang.annotation.RetentionPolicy.RUNTIME;
24 
25 import com.google.common.base.Optional;
26 import com.google.common.base.Throwables;
27 import com.google.common.collect.ImmutableSet;
28 import com.google.common.collect.Iterables;
29 import com.google.inject.Binder;
30 import com.google.inject.Binding;
31 import com.google.inject.Injector;
32 import com.google.inject.Key;
33 import com.google.inject.Module;
34 import com.google.inject.Provider;
35 import com.google.inject.TypeLiteral;
36 import com.google.inject.binder.LinkedBindingBuilder;
37 import com.google.inject.internal.InternalProviderInstanceBindingImpl.InitializationTiming;
38 import com.google.inject.multibindings.MultibindingsTargetVisitor;
39 import com.google.inject.multibindings.OptionalBinderBinding;
40 import com.google.inject.spi.BindingTargetVisitor;
41 import com.google.inject.spi.Dependency;
42 import com.google.inject.spi.Element;
43 import com.google.inject.spi.ProviderInstanceBinding;
44 import com.google.inject.spi.ProviderWithExtensionVisitor;
45 import com.google.inject.util.Types;
46 import java.io.Serializable;
47 import java.lang.annotation.Annotation;
48 import java.lang.annotation.Retention;
49 import java.lang.reflect.InvocationTargetException;
50 import java.lang.reflect.Method;
51 import java.lang.reflect.Type;
52 import java.util.Set;
53 import javax.inject.Qualifier;
54 
55 /**
56  * The actual OptionalBinder plays several roles. It implements Module to hide that fact from the
57  * public API, and installs the various bindings that are exposed to the user.
58  */
59 public final class RealOptionalBinder<T> implements Module {
newRealOptionalBinder(Binder binder, Key<T> type)60   public static <T> RealOptionalBinder<T> newRealOptionalBinder(Binder binder, Key<T> type) {
61     binder = binder.skipSources(RealOptionalBinder.class);
62     RealOptionalBinder<T> optionalBinder = new RealOptionalBinder<>(binder, type);
63     binder.install(optionalBinder);
64     return optionalBinder;
65   }
66 
67   /* Reflectively capture java 8's Optional types so we can bind them if we're running in java8. */
68   private static final Class<?> JAVA_OPTIONAL_CLASS;
69   private static final Object JAVA_OPTIONAL_EMPTY;
70   private static final Method JAVA_OPTIONAL_OF_METHOD;
71 
72   static {
73     Class<?> optional = null;
74     Object emptyObject = null;
75     Method of = null;
76     boolean useJavaOptional = false;
77     try {
78       optional = Class.forName("java.util.Optional");
79       emptyObject = optional.getDeclaredMethod("empty").invoke(null);
80       of = optional.getDeclaredMethod("of", Object.class);
81       // only use optional support if all our reflection succeeded
82       useJavaOptional = true;
83     } catch (ClassNotFoundException ignored) {
84     } catch (NoSuchMethodException ignored) {
85     } catch (SecurityException ignored) {
86     } catch (IllegalAccessException ignored) {
87     } catch (InvocationTargetException ignored) {
88     }
89     JAVA_OPTIONAL_CLASS = useJavaOptional ? optional : null;
90     JAVA_OPTIONAL_EMPTY = useJavaOptional ? emptyObject : null;
91     JAVA_OPTIONAL_OF_METHOD = useJavaOptional ? of : null;
92   }
93 
94   /**
95    * Returns java.util.Optional.empty() if the parameter is null, calls {@link
96    * #invokeJavaOptionalOf} otherwise.
97    */
invokeJavaOptionalOfNullable(Object o)98   private static Object invokeJavaOptionalOfNullable(Object o) {
99     if (o == null) {
100       return JAVA_OPTIONAL_EMPTY;
101     }
102     return invokeJavaOptionalOf(o);
103   }
104 
105   /** Invokes java.util.Optional.of. */
invokeJavaOptionalOf(Object o)106   private static Object invokeJavaOptionalOf(Object o) {
107     try {
108       return JAVA_OPTIONAL_OF_METHOD.invoke(null, o);
109     } catch (IllegalAccessException e) {
110       throw new SecurityException(e);
111     } catch (IllegalArgumentException e) {
112       throw new IllegalStateException(e);
113     } catch (InvocationTargetException e) {
114       throw Throwables.propagate(e.getCause());
115     }
116   }
117 
118   @SuppressWarnings("unchecked")
optionalOf(TypeLiteral<T> type)119   static <T> TypeLiteral<Optional<T>> optionalOf(TypeLiteral<T> type) {
120     return (TypeLiteral<Optional<T>>)
121         TypeLiteral.get(Types.newParameterizedType(Optional.class, type.getType()));
122   }
123 
javaOptionalOf(TypeLiteral<T> type)124   static <T> TypeLiteral<?> javaOptionalOf(TypeLiteral<T> type) {
125     checkState(JAVA_OPTIONAL_CLASS != null, "java.util.Optional not found");
126     return TypeLiteral.get(Types.newParameterizedType(JAVA_OPTIONAL_CLASS, type.getType()));
127   }
128 
129   @SuppressWarnings("unchecked")
optionalOfJavaxProvider( TypeLiteral<T> type)130   static <T> TypeLiteral<Optional<javax.inject.Provider<T>>> optionalOfJavaxProvider(
131       TypeLiteral<T> type) {
132     return (TypeLiteral<Optional<javax.inject.Provider<T>>>)
133         TypeLiteral.get(
134             Types.newParameterizedType(
135                 Optional.class, newParameterizedType(javax.inject.Provider.class, type.getType())));
136   }
137 
javaOptionalOfJavaxProvider(TypeLiteral<T> type)138   static <T> TypeLiteral<?> javaOptionalOfJavaxProvider(TypeLiteral<T> type) {
139     checkState(JAVA_OPTIONAL_CLASS != null, "java.util.Optional not found");
140     return TypeLiteral.get(
141         Types.newParameterizedType(
142             JAVA_OPTIONAL_CLASS,
143             newParameterizedType(javax.inject.Provider.class, type.getType())));
144   }
145 
146   @SuppressWarnings("unchecked")
optionalOfProvider(TypeLiteral<T> type)147   static <T> TypeLiteral<Optional<Provider<T>>> optionalOfProvider(TypeLiteral<T> type) {
148     return (TypeLiteral<Optional<Provider<T>>>)
149         TypeLiteral.get(
150             Types.newParameterizedType(
151                 Optional.class, newParameterizedType(Provider.class, type.getType())));
152   }
153 
javaOptionalOfProvider(TypeLiteral<T> type)154   static <T> TypeLiteral<?> javaOptionalOfProvider(TypeLiteral<T> type) {
155     checkState(JAVA_OPTIONAL_CLASS != null, "java.util.Optional not found");
156     return TypeLiteral.get(
157         Types.newParameterizedType(
158             JAVA_OPTIONAL_CLASS, newParameterizedType(Provider.class, type.getType())));
159   }
160 
161   @SuppressWarnings("unchecked")
providerOf(Key<T> key)162   static <T> Key<Provider<T>> providerOf(Key<T> key) {
163     Type providerT = Types.providerOf(key.getTypeLiteral().getType());
164     return (Key<Provider<T>>) key.ofType(providerT);
165   }
166 
167   enum Source {
168     DEFAULT,
169     ACTUAL
170   }
171 
172   @Retention(RUNTIME)
173   @Qualifier
174   @interface Default {
value()175     String value();
176   }
177 
178   @Retention(RUNTIME)
179   @Qualifier
180   @interface Actual {
value()181     String value();
182   }
183 
184   private final BindingSelection<T> bindingSelection;
185   private final Binder binder;
186 
RealOptionalBinder(Binder binder, Key<T> typeKey)187   private RealOptionalBinder(Binder binder, Key<T> typeKey) {
188     this.bindingSelection = new BindingSelection<>(typeKey);
189     this.binder = binder;
190   }
191 
192   /**
193    * Adds a binding for T. Multiple calls to this are safe, and will be collapsed as duplicate
194    * bindings.
195    */
addDirectTypeBinding(Binder binder)196   private void addDirectTypeBinding(Binder binder) {
197     binder
198         .bind(bindingSelection.getDirectKey())
199         .toProvider(new RealDirectTypeProvider<T>(bindingSelection));
200   }
201 
202   /**
203    * Returns the key to use for the default binding.
204    *
205    * <p>As a side effect this installs support for the 'direct type', so a binding for {@code T}
206    * will be made available.
207    */
getKeyForDefaultBinding()208   Key<T> getKeyForDefaultBinding() {
209     bindingSelection.checkNotInitialized();
210     addDirectTypeBinding(binder);
211     return bindingSelection.getKeyForDefaultBinding();
212   }
213 
setDefault()214   public LinkedBindingBuilder<T> setDefault() {
215     return binder.bind(getKeyForDefaultBinding());
216   }
217 
218   /**
219    * Returns the key to use for the actual binding, overrides the default if set.
220    *
221    * <p>As a side effect this installs support for the 'direct type', so a binding for {@code T}
222    * will be made available.
223    */
getKeyForActualBinding()224   Key<T> getKeyForActualBinding() {
225     bindingSelection.checkNotInitialized();
226     addDirectTypeBinding(binder);
227     return bindingSelection.getKeyForActualBinding();
228   }
229 
setBinding()230   public LinkedBindingBuilder<T> setBinding() {
231     return binder.bind(getKeyForActualBinding());
232   }
233 
234   @Override
configure(Binder binder)235   public void configure(Binder binder) {
236     bindingSelection.checkNotInitialized();
237     Key<T> key = bindingSelection.getDirectKey();
238     // Every OptionalBinder get's the following types bound
239     // * Optional<Provider<T>>
240     // * Optional<javax.inject.Provider<T>>
241     // * Optional<T>
242     // If setDefault() or setBinding() is called then also
243     // * T is bound
244     // If java.util.Optional is on the classpath (because this is a jdk8+ vm), then you also get
245     // * java.util.Optional<Provider<T>>
246     // * java.util.Optional<javax.inject.Provider<T>>
247     // * java.util.Optional<T>
248     InternalProviderInstanceBindingImpl.Factory<Optional<Provider<T>>> optionalProviderFactory =
249         new RealOptionalProviderProvider<T>(bindingSelection);
250     binder
251         .bind(key.ofType(optionalOfProvider(key.getTypeLiteral())))
252         .toProvider(optionalProviderFactory);
253 
254     // Provider is assignable to javax.inject.Provider and the provider that the factory contains
255     // cannot be modified so we can use some rawtypes hackery to share the same implementation.
256     @SuppressWarnings("unchecked")
257     InternalProviderInstanceBindingImpl.Factory<Optional<javax.inject.Provider<T>>>
258         optionalJavaxProviderFactory =
259             (InternalProviderInstanceBindingImpl.Factory) optionalProviderFactory;
260     binder
261         .bind(key.ofType(optionalOfJavaxProvider(key.getTypeLiteral())))
262         .toProvider(optionalJavaxProviderFactory);
263 
264     Key<Optional<T>> optionalKey = key.ofType(optionalOf(key.getTypeLiteral()));
265     binder
266         .bind(optionalKey)
267         .toProvider(new RealOptionalKeyProvider<T>(bindingSelection, optionalKey));
268 
269     // Bind the java-8 types if we know them.
270     bindJava8Optional(binder);
271   }
272 
273   @SuppressWarnings("unchecked")
bindJava8Optional(Binder binder)274   private void bindJava8Optional(Binder binder) {
275     if (JAVA_OPTIONAL_CLASS != null) {
276       Key<?> key = bindingSelection.getDirectKey();
277       TypeLiteral<?> typeLiteral = key.getTypeLiteral();
278       InternalProviderInstanceBindingImpl.Factory<Object> javaOptionalProviderFactory =
279           new JavaOptionalProviderProvider(bindingSelection);
280       binder
281           .bind(key.ofType(javaOptionalOfProvider(typeLiteral)))
282           .toProvider((Provider) javaOptionalProviderFactory);
283       // Provider is assignable to javax.inject.Provider and the provider that the factory contains
284       // cannot be modified so we can use some rawtypes hackery to share the same implementation.
285       binder
286           .bind(key.ofType(javaOptionalOfJavaxProvider(typeLiteral)))
287           .toProvider((Provider) javaOptionalProviderFactory);
288       Key<?> javaOptionalKey = key.ofType(javaOptionalOf(typeLiteral));
289       binder
290           .bind(javaOptionalKey)
291           .toProvider(new JavaOptionalProvider(bindingSelection, javaOptionalKey));
292     }
293   }
294 
295   /** Provides the binding for java.util.Optional<T>. */
296   @SuppressWarnings({"rawtypes", "unchecked"})
297   private static final class JavaOptionalProvider extends RealOptionalBinderProviderWithDependencies
298       implements ProviderWithExtensionVisitor, OptionalBinderBinding {
299 
300     private final Key<?> optionalKey;
301 
302     private Dependency<?> targetDependency;
303     private InternalFactory<?> target;
304 
JavaOptionalProvider(BindingSelection<?> bindingSelection, Key<?> optionalKey)305     JavaOptionalProvider(BindingSelection<?> bindingSelection, Key<?> optionalKey) {
306       super(bindingSelection);
307       this.optionalKey = optionalKey;
308     }
309 
310     @Override
doInitialize()311     void doInitialize() {
312       if (bindingSelection.getBinding() != null) {
313         target = bindingSelection.getBinding().getInternalFactory();
314         targetDependency = bindingSelection.getDependency();
315       }
316     }
317 
318     @Override
doProvision(InternalContext context, Dependency dependency)319     protected Object doProvision(InternalContext context, Dependency dependency)
320         throws InternalProvisionException {
321       InternalFactory<?> local = target;
322       if (local == null) {
323         return JAVA_OPTIONAL_EMPTY;
324       }
325       Dependency<?> localDependency = targetDependency;
326       Object result;
327       Dependency previous = context.pushDependency(localDependency, getSource());
328 
329       try {
330         // See comments in RealOptionalKeyProvider, about how localDependency may be more specific
331         // than what we actually need.
332         result = local.get(context, localDependency, false);
333       } catch (InternalProvisionException ipe) {
334         throw ipe.addSource(localDependency);
335         } finally {
336           context.popStateAndSetDependency(previous);
337 
338       }
339       return invokeJavaOptionalOfNullable(result);
340     }
341 
342     @Override
getDependencies()343     public Set<Dependency<?>> getDependencies() {
344       return bindingSelection.dependencies;
345     }
346 
347     @SuppressWarnings("unchecked")
348     @Override
acceptExtensionVisitor( BindingTargetVisitor visitor, ProviderInstanceBinding binding)349     public Object acceptExtensionVisitor(
350         BindingTargetVisitor visitor, ProviderInstanceBinding binding) {
351       if (visitor instanceof MultibindingsTargetVisitor) {
352         return ((MultibindingsTargetVisitor) visitor).visit(this);
353       } else {
354         return visitor.visit(binding);
355       }
356     }
357 
358     @Override
containsElement(Element element)359     public boolean containsElement(Element element) {
360       return bindingSelection.containsElement(element);
361     }
362 
363     @Override
getActualBinding()364     public Binding<?> getActualBinding() {
365       return bindingSelection.getActualBinding();
366     }
367 
368     @Override
getDefaultBinding()369     public Binding<?> getDefaultBinding() {
370       return bindingSelection.getDefaultBinding();
371     }
372 
373     @Override
getKey()374     public Key getKey() {
375       return optionalKey;
376     }
377   }
378 
379   /** Provides the binding for java.util.Optional<Provider<T>>. */
380   @SuppressWarnings({"rawtypes", "unchecked"})
381   private static final class JavaOptionalProviderProvider
382       extends RealOptionalBinderProviderWithDependencies {
383     private Object value;
384 
JavaOptionalProviderProvider(BindingSelection<?> bindingSelection)385     JavaOptionalProviderProvider(BindingSelection<?> bindingSelection) {
386       super(bindingSelection);
387     }
388 
389     @Override
doInitialize()390     void doInitialize() {
391       if (bindingSelection.getBinding() == null) {
392         value = JAVA_OPTIONAL_EMPTY;
393       } else {
394         value = invokeJavaOptionalOf(bindingSelection.getBinding().getProvider());
395       }
396     }
397 
398     @Override
doProvision(InternalContext context, Dependency dependency)399     protected Object doProvision(InternalContext context, Dependency dependency) {
400       return value;
401     }
402 
403     @Override
getDependencies()404     public Set<Dependency<?>> getDependencies() {
405       return bindingSelection.providerDependencies();
406     }
407   }
408 
409   /** Provides the binding for T, conditionally installed by calling setBinding/setDefault. */
410   private static final class RealDirectTypeProvider<T>
411       extends RealOptionalBinderProviderWithDependencies<T, T> {
412     private Key<? extends T> targetKey;
413 
414     private Object targetSource;
415 
416     private InternalFactory<? extends T> targetFactory;
417 
RealDirectTypeProvider(BindingSelection<T> bindingSelection)418     RealDirectTypeProvider(BindingSelection<T> bindingSelection) {
419       super(bindingSelection);
420     }
421 
422     @Override
doInitialize()423     void doInitialize() {
424       BindingImpl<T> targetBinding = bindingSelection.getBinding();
425       // we only install this factory if they call setBinding()/setDefault() so we know that
426       // targetBinding will be non-null.
427       this.targetKey = targetBinding.getKey();
428       this.targetSource = targetBinding.getSource();
429       this.targetFactory = targetBinding.getInternalFactory();
430     }
431 
432     @Override
doProvision(InternalContext context, Dependency<?> dependency)433     protected T doProvision(InternalContext context, Dependency<?> dependency)
434         throws InternalProvisionException {
435       // This is what linked bindings do (see FactoryProxy), and we are pretty similar.
436       context.pushState(targetKey, targetSource);
437 
438       try {
439         return targetFactory.get(context, dependency, true);
440       } catch (InternalProvisionException ipe) {
441         throw ipe.addSource(targetKey);
442         } finally {
443           context.popState();
444 
445       }
446     }
447 
448     @Override
getDependencies()449     public Set<Dependency<?>> getDependencies() {
450       return bindingSelection.dependencies;
451     }
452   }
453 
454   /** Provides the binding for Optional<Provider<T>>. */
455   private static final class RealOptionalProviderProvider<T>
456       extends RealOptionalBinderProviderWithDependencies<T, Optional<Provider<T>>> {
457     private Optional<Provider<T>> value;
458 
RealOptionalProviderProvider(BindingSelection<T> bindingSelection)459     RealOptionalProviderProvider(BindingSelection<T> bindingSelection) {
460       super(bindingSelection);
461     }
462 
463     @Override
doInitialize()464     void doInitialize() {
465       if (bindingSelection.getBinding() == null) {
466         value = Optional.absent();
467       } else {
468         value = Optional.of(bindingSelection.getBinding().getProvider());
469       }
470     }
471 
472     @Override
doProvision(InternalContext context, Dependency<?> dependency)473     protected Optional<Provider<T>> doProvision(InternalContext context, Dependency<?> dependency) {
474       return value;
475     }
476 
477     @Override
getDependencies()478     public Set<Dependency<?>> getDependencies() {
479       return bindingSelection.providerDependencies();
480     }
481   }
482 
483   /** Provides the binding for Optional<T>. */
484   private static final class RealOptionalKeyProvider<T>
485       extends RealOptionalBinderProviderWithDependencies<T, Optional<T>>
486       implements ProviderWithExtensionVisitor<Optional<T>>, OptionalBinderBinding<Optional<T>> {
487 
488     private final Key<Optional<T>> optionalKey;
489 
490     // These are assigned to non-null values during initialization if and only if we have a binding
491     // to delegate to.
492     private Dependency<?> targetDependency;
493     private InternalFactory<? extends T> delegate;
494 
RealOptionalKeyProvider(BindingSelection<T> bindingSelection, Key<Optional<T>> optionalKey)495     RealOptionalKeyProvider(BindingSelection<T> bindingSelection, Key<Optional<T>> optionalKey) {
496       super(bindingSelection);
497       this.optionalKey = optionalKey;
498     }
499 
500     @Override
doInitialize()501     void doInitialize() {
502       if (bindingSelection.getBinding() != null) {
503         delegate = bindingSelection.getBinding().getInternalFactory();
504         targetDependency = bindingSelection.getDependency();
505       }
506     }
507 
508     @Override
doProvision(InternalContext context, Dependency<?> currentDependency)509     protected Optional<T> doProvision(InternalContext context, Dependency<?> currentDependency)
510         throws InternalProvisionException {
511       InternalFactory<? extends T> local = delegate;
512       if (local == null) {
513         return Optional.absent();
514       }
515       Dependency<?> localDependency = targetDependency;
516       T result;
517       Dependency previous = context.pushDependency(localDependency, getSource());
518 
519       try {
520         // currentDependency is Optional<? super T>, so we really just need to set the target
521         // dependency to ? super T, but we are currently setting it to T.  We could hypothetically
522         // make it easier for our delegate to generate proxies by modifying the dependency, but that
523         // would also require us to rewrite the key on each call.  So for now we don't do it.
524         result = local.get(context, localDependency, false);
525       } catch (InternalProvisionException ipe) {
526         throw ipe.addSource(localDependency);
527         } finally {
528           context.popStateAndSetDependency(previous);
529 
530       }
531       return Optional.fromNullable(result);
532     }
533 
534     @Override
getDependencies()535     public Set<Dependency<?>> getDependencies() {
536       return bindingSelection.dependencies();
537     }
538 
539     @SuppressWarnings("unchecked")
540     @Override
acceptExtensionVisitor( BindingTargetVisitor<B, R> visitor, ProviderInstanceBinding<? extends B> binding)541     public <B, R> R acceptExtensionVisitor(
542         BindingTargetVisitor<B, R> visitor, ProviderInstanceBinding<? extends B> binding) {
543       if (visitor instanceof MultibindingsTargetVisitor) {
544         return ((MultibindingsTargetVisitor<Optional<T>, R>) visitor).visit(this);
545       } else {
546         return visitor.visit(binding);
547       }
548     }
549 
550     @Override
getKey()551     public Key<Optional<T>> getKey() {
552       return optionalKey;
553     }
554 
555     @Override
getActualBinding()556     public Binding<?> getActualBinding() {
557       return bindingSelection.getActualBinding();
558     }
559 
560     @Override
getDefaultBinding()561     public Binding<?> getDefaultBinding() {
562       return bindingSelection.getDefaultBinding();
563     }
564 
565     @Override
containsElement(Element element)566     public boolean containsElement(Element element) {
567       return bindingSelection.containsElement(element);
568     }
569   }
570 
571   /**
572    * A helper object that implements the core logic for deciding what the implementation of the
573    * binding will be.
574    *
575    * <p>This also implements the main OptionalBinderBinding logic.
576    */
577   private static final class BindingSelection<T> {
578     private static final ImmutableSet<Dependency<?>> MODULE_DEPENDENCIES =
579         ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(Injector.class)));
580 
581     /*@Nullable */ BindingImpl<T> actualBinding;
582     /*@Nullable */ BindingImpl<T> defaultBinding;
583     /*@Nullable */ BindingImpl<T> binding;
584     private boolean initialized;
585     private final Key<T> key;
586 
587     // Until the injector initializes us, we don't know what our dependencies are,
588     // so initialize to the whole Injector (like Multibinder, and MapBinder indirectly).
589     private ImmutableSet<Dependency<?>> dependencies = MODULE_DEPENDENCIES;
590     private ImmutableSet<Dependency<?>> providerDependencies = MODULE_DEPENDENCIES;
591 
592     /** lazily allocated, by {@link #getBindingName}. */
593     private String bindingName;
594 
595     /** lazily allocated, by {@link #getKeyForDefaultBinding}. */
596     private Key<T> defaultBindingKey;
597 
598     /** lazily allocated, by {@link #getKeyForActualBinding}. */
599     private Key<T> actualBindingKey;
600 
BindingSelection(Key<T> key)601     BindingSelection(Key<T> key) {
602       this.key = key;
603     }
604 
checkNotInitialized()605     void checkNotInitialized() {
606       checkConfiguration(!initialized, "already initialized");
607     }
608 
initialize(InjectorImpl injector)609     void initialize(InjectorImpl injector) {
610       // Every one of our providers will call this method, so only execute the logic once.
611       if (initialized) {
612         return;
613       }
614 
615       actualBinding = injector.getExistingBinding(getKeyForActualBinding());
616       defaultBinding = injector.getExistingBinding(getKeyForDefaultBinding());
617       // We should never create Jit bindings, but we can use them if some other binding created it.
618       BindingImpl<T> userBinding = injector.getExistingBinding(key);
619       if (actualBinding != null) {
620         // TODO(sameb): Consider exposing an option that will allow
621         // ACTUAL to fallback to DEFAULT if ACTUAL's provider returns null.
622         // Right now, an ACTUAL binding can convert from present -> absent
623         // if it's bound to a provider that returns null.
624         binding = actualBinding;
625       } else if (defaultBinding != null) {
626         binding = defaultBinding;
627       } else if (userBinding != null) {
628         // If neither the actual or default is set, then we fallback
629         // to the value bound to the type itself and consider that the
630         // "actual binding" for the SPI.
631         binding = userBinding;
632         actualBinding = userBinding;
633       }
634       if (binding != null) {
635         dependencies = ImmutableSet.<Dependency<?>>of(Dependency.get(binding.getKey()));
636         providerDependencies =
637             ImmutableSet.<Dependency<?>>of(Dependency.get(providerOf(binding.getKey())));
638       } else {
639         dependencies = ImmutableSet.of();
640         providerDependencies = ImmutableSet.of();
641       }
642       initialized = true;
643     }
644 
getKeyForDefaultBinding()645     Key<T> getKeyForDefaultBinding() {
646       if (defaultBindingKey == null) {
647         defaultBindingKey = Key.get(key.getTypeLiteral(), new DefaultImpl(getBindingName()));
648       }
649       return defaultBindingKey;
650     }
651 
getKeyForActualBinding()652     Key<T> getKeyForActualBinding() {
653       if (actualBindingKey == null) {
654         actualBindingKey = Key.get(key.getTypeLiteral(), new ActualImpl(getBindingName()));
655       }
656       return actualBindingKey;
657     }
658 
getDirectKey()659     Key<T> getDirectKey() {
660       return key;
661     }
662 
getBindingName()663     private String getBindingName() {
664       // Lazily allocated, most instantiations will never need this because they are deduped during
665       // module installation.
666       if (bindingName == null) {
667         bindingName = Annotations.nameOf(key);
668       }
669       return bindingName;
670     }
671 
getBinding()672     BindingImpl<T> getBinding() {
673       return binding;
674     }
675 
676     // Provide default implementations for most of the OptionalBinderBinding interface
getDefaultBinding()677     BindingImpl<T> getDefaultBinding() {
678       return defaultBinding;
679     }
680 
getActualBinding()681     BindingImpl<T> getActualBinding() {
682       return actualBinding;
683     }
684 
providerDependencies()685     ImmutableSet<Dependency<?>> providerDependencies() {
686       return providerDependencies;
687     }
688 
dependencies()689     ImmutableSet<Dependency<?>> dependencies() {
690       return dependencies;
691     }
692 
693     /**
694      * Returns the Dependency for the target binding, throws NoSuchElementException if no target
695      * exists.
696      *
697      * <p>Calls to this method should typically be guarded by checking if {@link #getBinding()}
698      * returns {@code null}.
699      */
getDependency()700     Dependency<?> getDependency() {
701       return Iterables.getOnlyElement(dependencies);
702     }
703 
704     /** Implementation of {@link OptionalBinderBinding#containsElement}. */
containsElement(Element element)705     boolean containsElement(Element element) {
706       // All of our bindings are ProviderInstanceBindings whose providers extend
707       // RealOptionalBinderProviderWithDependencies and have 'this' as its binding selection.
708       if (element instanceof ProviderInstanceBinding) {
709         javax.inject.Provider<?> providerInstance =
710             ((ProviderInstanceBinding<?>) element).getUserSuppliedProvider();
711         if (providerInstance instanceof RealOptionalBinderProviderWithDependencies) {
712           return ((RealOptionalBinderProviderWithDependencies<?, ?>) providerInstance)
713               .bindingSelection.equals(this);
714         }
715       }
716       if (element instanceof Binding) {
717         Key<?> elementKey = ((Binding) element).getKey();
718         // if it isn't one of the things we bound directly it might be an actual or default key
719         return elementKey.equals(getKeyForActualBinding())
720             || elementKey.equals(getKeyForDefaultBinding());
721       }
722       return false; // cannot match;
723     }
724 
725     @Override
equals(Object o)726     public boolean equals(Object o) {
727       return o instanceof BindingSelection && ((BindingSelection) o).key.equals(key);
728     }
729 
730     @Override
hashCode()731     public int hashCode() {
732       return key.hashCode();
733     }
734   }
735 
736   @Override
equals(Object o)737   public boolean equals(Object o) {
738     return o instanceof RealOptionalBinder
739         && ((RealOptionalBinder<?>) o).bindingSelection.equals(bindingSelection);
740   }
741 
742   @Override
hashCode()743   public int hashCode() {
744     return bindingSelection.hashCode();
745   }
746 
747   /** A base class for ProviderWithDependencies that need equality based on a specific object. */
748   private abstract static class RealOptionalBinderProviderWithDependencies<T, P>
749       extends InternalProviderInstanceBindingImpl.Factory<P> {
750     protected final BindingSelection<T> bindingSelection;
751 
RealOptionalBinderProviderWithDependencies(BindingSelection<T> bindingSelection)752     RealOptionalBinderProviderWithDependencies(BindingSelection<T> bindingSelection) {
753       // We need delayed initialization so we can detect jit bindings created by other bindings
754       // while not also creating jit bindings ourselves.  This ensures we only pick up user bindings
755       // if the binding would have existed in the injector statically.
756       super(InitializationTiming.DELAYED);
757       this.bindingSelection = bindingSelection;
758     }
759 
760     @Override
initialize(InjectorImpl injector, Errors errors)761     final void initialize(InjectorImpl injector, Errors errors) throws ErrorsException {
762       bindingSelection.initialize(injector);
763       doInitialize();
764     }
765 
766     /**
767      * Initialize the factory. BindingSelection is guaranteed to be initialized at this point and
768      * this will be called prior to any provisioning.
769      */
doInitialize()770     abstract void doInitialize();
771 
772     @Override
equals(Object obj)773     public boolean equals(Object obj) {
774       return obj != null
775           && this.getClass() == obj.getClass()
776           && bindingSelection.equals(
777               ((RealOptionalBinderProviderWithDependencies<?, ?>) obj).bindingSelection);
778     }
779 
780     @Override
hashCode()781     public int hashCode() {
782       return bindingSelection.hashCode();
783     }
784   }
785 
786   static class DefaultImpl extends BaseAnnotation implements Default {
DefaultImpl(String value)787     public DefaultImpl(String value) {
788       super(Default.class, value);
789     }
790   }
791 
792   static class ActualImpl extends BaseAnnotation implements Actual {
ActualImpl(String value)793     public ActualImpl(String value) {
794       super(Actual.class, value);
795     }
796   }
797 
798   abstract static class BaseAnnotation implements Serializable, Annotation {
799 
800     private final String value;
801     private final Class<? extends Annotation> clazz;
802 
BaseAnnotation(Class<? extends Annotation> clazz, String value)803     BaseAnnotation(Class<? extends Annotation> clazz, String value) {
804       this.clazz = checkNotNull(clazz, "clazz");
805       this.value = checkNotNull(value, "value");
806     }
807 
value()808     public String value() {
809       return this.value;
810     }
811 
812     @Override
hashCode()813     public int hashCode() {
814       // This is specified in java.lang.Annotation.
815       return (127 * "value".hashCode()) ^ value.hashCode();
816     }
817 
818     @Override
equals(Object o)819     public boolean equals(Object o) {
820       // We check against each annotation type instead of BaseAnnotation
821       // so that we can compare against generated annotation implementations.
822       if (o instanceof Actual && clazz == Actual.class) {
823         Actual other = (Actual) o;
824         return value.equals(other.value());
825       } else if (o instanceof Default && clazz == Default.class) {
826         Default other = (Default) o;
827         return value.equals(other.value());
828       }
829       return false;
830     }
831 
832     @Override
toString()833     public String toString() {
834       return "@" + clazz.getName() + (value.isEmpty() ? "" : "(value=" + value + ")");
835     }
836 
837     @Override
annotationType()838     public Class<? extends Annotation> annotationType() {
839       return clazz;
840     }
841 
842     private static final long serialVersionUID = 0;
843   }
844 }
845