package com.google.inject.internal;

import com.google.common.collect.ImmutableSet;
import com.google.inject.Key;
import com.google.inject.Provider;
import com.google.inject.internal.ProvisionListenerStackCallback.ProvisionCallback;
import com.google.inject.spi.Dependency;
import com.google.inject.spi.HasDependencies;
import com.google.inject.spi.InjectionPoint;
import com.google.inject.spi.ProviderWithExtensionVisitor;

A ProviderInstanceBindingImpl for implementing 'native' guice extensions.

Beyond the normal binding contract that is mostly handled by our baseclass, this also implements DelayedInitialize in order to initialize factory state.

/** * A {@link ProviderInstanceBindingImpl} for implementing 'native' guice extensions. * * <p>Beyond the normal binding contract that is mostly handled by our baseclass, this also * implements {@link DelayedInitialize} in order to initialize factory state. */
final class InternalProviderInstanceBindingImpl<T> extends ProviderInstanceBindingImpl<T> implements DelayedInitialize { enum InitializationTiming {
This factory can be initialized eagerly. This should be the case for most things.
/** This factory can be initialized eagerly. This should be the case for most things. */
EAGER,
Initialization of this factory should be delayed until after all other static initialization completes. This will be useful for factories that need to call InjectorImpl.getExistingBinding(Key<Object>) to not create jit bindings, but also want to be able to conditionally consume jit bindings created by other other bindings.
/** * Initialization of this factory should be delayed until after all other static initialization * completes. This will be useful for factories that need to call {@link * InjectorImpl#getExistingBinding(Key)} to not create jit bindings, but also want to be able to * conditionally consume jit bindings created by other other bindings. */
DELAYED; } private final Factory<T> originalFactory; InternalProviderInstanceBindingImpl( InjectorImpl injector, Key<T> key, Object source, Factory<T> originalFactory, InternalFactory<? extends T> scopedFactory, Scoping scoping) { super( injector, key, source, scopedFactory, scoping, originalFactory, ImmutableSet.<InjectionPoint>of()); this.originalFactory = originalFactory; } InitializationTiming getInitializationTiming() { return originalFactory.initializationTiming; } @Override public void initialize(final InjectorImpl injector, final Errors errors) throws ErrorsException { originalFactory.source = getSource(); originalFactory.provisionCallback = injector.provisionListenerStore.get(this); // For these kinds of providers, the 'user supplied provider' is really 'guice supplied' // So make our user supplied provider just delegate to the guice supplied one. originalFactory.delegateProvider = getProvider(); originalFactory.initialize(injector, errors); }
A base factory implementation. Any Factories that delegate to other bindings should use the CyclicFactory subclass, but trivial factories can use this one.
/** * A base factory implementation. Any Factories that delegate to other bindings should use the * {@code CyclicFactory} subclass, but trivial factories can use this one. */
abstract static class Factory<T> implements InternalFactory<T>, Provider<T>, HasDependencies { private final InitializationTiming initializationTiming; private Object source; private Provider<T> delegateProvider; ProvisionListenerStackCallback<T> provisionCallback; Factory(InitializationTiming initializationTiming) { this.initializationTiming = initializationTiming; }
The binding source.

May be useful for augmenting runtime error messages.

Note: this will return {#code null} until initialize(InjectorImpl, Errors) has already been called.

/** * The binding source. * * <p>May be useful for augmenting runtime error messages. * * <p>Note: this will return {#code null} until {@link #initialize(InjectorImpl, Errors)} has * already been called. */
final Object getSource() { return source; }
A callback that allows for implementations to fetch dependencies on other bindings.

Will be called exactly once, prior to any call to doProvision.

/** * A callback that allows for implementations to fetch dependencies on other bindings. * * <p>Will be called exactly once, prior to any call to {@link #doProvision}. */
abstract void initialize(InjectorImpl injector, Errors errors) throws ErrorsException; @Override public final T get() { Provider<T> local = delegateProvider; if (local == null) { throw new IllegalStateException( "This Provider cannot be used until the Injector has been created."); } return local.get(); } @Override public T get(final InternalContext context, final Dependency<?> dependency, boolean linked) throws InternalProvisionException { if (provisionCallback == null) { return doProvision(context, dependency); } else { return provisionCallback.provision( context, new ProvisionCallback<T>() { @Override public T call() throws InternalProvisionException { return doProvision(context, dependency); } }); } }
Creates an object to be injected.
Throws:
  • InternalProvisionException – if a value cannot be provided
Returns:instance to be injected
/** * Creates an object to be injected. * * @throws com.google.inject.internal.InternalProvisionException if a value cannot be provided * @return instance to be injected */
protected abstract T doProvision(InternalContext context, Dependency<?> dependency) throws InternalProvisionException; }
An base factory implementation that can be extended to provide a specialized implementation of a ProviderWithExtensionVisitor and also implements InternalFactory
/** * An base factory implementation that can be extended to provide a specialized implementation of * a {@link ProviderWithExtensionVisitor} and also implements {@link InternalFactory} */
abstract static class CyclicFactory<T> extends Factory<T> { CyclicFactory(InitializationTiming initializationTiming) { super(initializationTiming); } @Override public final T get( final InternalContext context, final Dependency<?> dependency, boolean linked) throws InternalProvisionException { final ConstructionContext<T> constructionContext = context.getConstructionContext(this); // We have a circular reference between bindings. Return a proxy. if (constructionContext.isConstructing()) { Class<?> expectedType = dependency.getKey().getTypeLiteral().getRawType(); @SuppressWarnings("unchecked") T proxyType = (T) constructionContext.createProxy(context.getInjectorOptions(), expectedType); return proxyType; } // Optimization: Don't go through the callback stack if no one's listening. constructionContext.startConstruction(); try { if (provisionCallback == null) { return provision(dependency, context, constructionContext); } else { return provisionCallback.provision( context, new ProvisionCallback<T>() { @Override public T call() throws InternalProvisionException { return provision(dependency, context, constructionContext); } }); } } finally { constructionContext.removeCurrentReference(); constructionContext.finishConstruction(); } } private T provision( Dependency<?> dependency, InternalContext context, ConstructionContext<T> constructionContext) throws InternalProvisionException { try { T t = doProvision(context, dependency); constructionContext.setProxyDelegates(t); return t; } catch (InternalProvisionException ipe) { throw ipe.addSource(getSource()); } catch (Throwable t) { throw InternalProvisionException.errorInProvider(t).addSource(getSource()); } } } }