package org.robolectric.internal.bytecode;
import org.robolectric.internal.IShadow;
import org.robolectric.util.ReflectionHelpers;
public class ShadowImpl implements IShadow {
private final ProxyMaker PROXY_MAKER = new ProxyMaker(new ProxyMaker.MethodMapper() {
@Override public String getName(String className, String methodName) {
return directMethodName(methodName);
}
});
@Override
public <T> T extract(Object instance) {
return (T) ((ShadowedObject) instance).$$robo$getData();
}
public <T> T newInstanceOf(Class<T> clazz) {
return ReflectionHelpers.callConstructor(clazz);
}
public <T> T newInstance(Class<T> clazz, Class[] parameterTypes, Object[] params) {
return ReflectionHelpers.callConstructor(clazz, ReflectionHelpers.ClassParameter.fromComponentLists(parameterTypes, params));
}
public <T> T directlyOn(T shadowedObject, Class<T> clazz) {
return createProxy(shadowedObject, clazz);
}
private <T> T createProxy(T shadowedObject, Class<T> clazz) {
try {
if (InvokeDynamic.ENABLED) {
return PROXY_MAKER.createProxy(clazz, shadowedObject);
} else {
return ReflectionHelpers.callConstructor(clazz,
ReflectionHelpers.ClassParameter.fromComponentLists(new Class[] { DirectObjectMarker.class, clazz },
new Object[] { DirectObjectMarker.INSTANCE, shadowedObject }));
}
} catch (Exception e) {
throw new RuntimeException("error creating direct call proxy for " + clazz, e);
}
}
@SuppressWarnings("unchecked")
public <R> R directlyOn(Object shadowedObject, String clazzName, String methodName, ReflectionHelpers.ClassParameter... paramValues) {
try {
Class<Object> aClass = (Class<Object>) shadowedObject.getClass().getClassLoader().loadClass(clazzName);
return directlyOn(shadowedObject, aClass, methodName, paramValues);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
public <R, T> R directlyOn(T shadowedObject, Class<T> clazz, String methodName, ReflectionHelpers.ClassParameter... paramValues) {
String directMethodName = directMethodName(methodName);
return (R) ReflectionHelpers.callInstanceMethod(clazz, shadowedObject, directMethodName, paramValues);
}
public <R, T> R directlyOn(Class<T> clazz, String methodName, ReflectionHelpers.ClassParameter... paramValues) {
String directMethodName = directMethodName(methodName);
return (R) ReflectionHelpers.callStaticMethod(clazz, directMethodName, paramValues);
}
public <R> R invokeConstructor(Class<? extends R> clazz, R instance, ReflectionHelpers.ClassParameter... paramValues) {
String directMethodName = directMethodName(ShadowConstants.CONSTRUCTOR_METHOD_NAME);
return (R) ReflectionHelpers.callInstanceMethod(clazz, instance, directMethodName, paramValues);
}
public String directMethodName(String methodName) {
return ShadowConstants.ROBO_PREFIX + methodName;
}
}