package com.google.inject.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.inject.internal.ProvisionListenerStackCallback.ProvisionCallback;
import com.google.inject.spi.Dependency;
import javax.inject.Provider;
abstract class ProviderInternalFactory<T> implements InternalFactory<T> {
protected final Object source;
ProviderInternalFactory(Object source) {
this.source = checkNotNull(source, "source");
}
protected T circularGet(
final Provider<? extends T> provider,
InternalContext context,
final Dependency<?> dependency,
ProvisionListenerStackCallback<T> provisionCallback)
throws InternalProvisionException {
final ConstructionContext<T> constructionContext = context.getConstructionContext(this);
if (constructionContext.isConstructing()) {
Class<?> expectedType = dependency.getKey().getTypeLiteral().getRawType();
@SuppressWarnings("unchecked")
T proxyType = (T) constructionContext.createProxy(context.getInjectorOptions(), expectedType);
return proxyType;
}
constructionContext.startConstruction();
try {
if (provisionCallback == null) {
return provision(provider, dependency, constructionContext);
} else {
return provisionCallback.provision(
context,
new ProvisionCallback<T>() {
@Override
public T call() throws InternalProvisionException {
return provision(provider, dependency, constructionContext);
}
});
}
} finally {
constructionContext.removeCurrentReference();
constructionContext.finishConstruction();
}
}
protected T provision(
Provider<? extends T> provider,
Dependency<?> dependency,
ConstructionContext<T> constructionContext)
throws InternalProvisionException {
T t = provider.get();
if (t == null && !dependency.isNullable()) {
InternalProvisionException.onNullInjectedIntoNonNullableDependency(source, dependency);
}
constructionContext.setProxyDelegates(t);
return t;
}
}