package com.google.inject.internal;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.inject.spi.InjectionPoint;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
final class DefaultConstructionProxyFactory<T> implements ConstructionProxyFactory<T> {
private final InjectionPoint injectionPoint;
DefaultConstructionProxyFactory(InjectionPoint injectionPoint) {
this.injectionPoint = injectionPoint;
}
@Override
public ConstructionProxy<T> create() {
@SuppressWarnings("unchecked")
final Constructor<T> constructor = (Constructor<T>) injectionPoint.getMember();
try {
net.sf.cglib.reflect.FastClass fc = BytecodeGen.newFastClassForMember(constructor);
if (fc != null) {
int index = fc.getIndex(constructor.getParameterTypes());
Preconditions.checkArgument(
index >= 0, "Could not find constructor %s in fast class", constructor);
return new FastClassProxy<T>(injectionPoint, constructor, fc, index);
}
} catch (net.sf.cglib.core.CodeGenerationException e) {
}
return new ReflectiveProxy<T>(injectionPoint, constructor);
}
private static final class FastClassProxy<T> implements ConstructionProxy<T> {
final InjectionPoint injectionPoint;
final Constructor<T> constructor;
final net.sf.cglib.reflect.FastClass fc;
final int index;
private FastClassProxy(
InjectionPoint injectionPoint,
Constructor<T> constructor,
net.sf.cglib.reflect.FastClass fc,
int index) {
this.injectionPoint = injectionPoint;
this.constructor = constructor;
this.fc = fc;
this.index = index;
}
@Override
@SuppressWarnings("unchecked")
public T newInstance(Object... arguments) throws InvocationTargetException {
return (T) fc.newInstance(index, arguments);
}
@Override
public InjectionPoint getInjectionPoint() {
return injectionPoint;
}
@Override
public Constructor<T> getConstructor() {
return constructor;
}
@Override
public ImmutableMap<Method, List<org.aopalliance.intercept.MethodInterceptor>>
getMethodInterceptors() {
return ImmutableMap.of();
}
}
private static final class ReflectiveProxy<T> implements ConstructionProxy<T> {
final Constructor<T> constructor;
final InjectionPoint injectionPoint;
ReflectiveProxy(InjectionPoint injectionPoint, Constructor<T> constructor) {
if (!Modifier.isPublic(constructor.getDeclaringClass().getModifiers())
|| !Modifier.isPublic(constructor.getModifiers())) {
constructor.setAccessible(true);
}
this.injectionPoint = injectionPoint;
this.constructor = constructor;
}
@Override
public T newInstance(Object... arguments) throws InvocationTargetException {
try {
return constructor.newInstance(arguments);
} catch (InstantiationException e) {
throw new AssertionError(e);
} catch (IllegalAccessException e) {
throw new AssertionError(e);
}
}
@Override
public InjectionPoint getInjectionPoint() {
return injectionPoint;
}
@Override
public Constructor<T> getConstructor() {
return constructor;
}
@Override
public ImmutableMap<Method, List<org.aopalliance.intercept.MethodInterceptor>>
getMethodInterceptors() {
return ImmutableMap.of();
}
}
}