1 package org.robolectric.internal.bytecode; 2 3 import org.robolectric.internal.IShadow; 4 import org.robolectric.util.ReflectionHelpers; 5 6 public class ShadowImpl implements IShadow { 7 8 private final ProxyMaker PROXY_MAKER = 9 new ProxyMaker( 10 new ProxyMaker.MethodMapper() { 11 @Override 12 public String getName(String className, String methodName) { 13 return directMethodName(className, methodName); 14 } 15 }); 16 17 @Override 18 @SuppressWarnings("TypeParameterUnusedInFormals") extract(Object instance)19 public <T> T extract(Object instance) { 20 return (T) ((ShadowedObject) instance).$$robo$getData(); 21 } 22 newInstanceOf(Class<T> clazz)23 @Override public <T> T newInstanceOf(Class<T> clazz) { 24 return ReflectionHelpers.callConstructor(clazz); 25 } 26 newInstance(Class<T> clazz, Class[] parameterTypes, Object[] params)27 @Override public <T> T newInstance(Class<T> clazz, Class[] parameterTypes, Object[] params) { 28 return ReflectionHelpers.callConstructor(clazz, ReflectionHelpers.ClassParameter.fromComponentLists(parameterTypes, params)); 29 } 30 directlyOn(T shadowedObject, Class<T> clazz)31 @Override public <T> T directlyOn(T shadowedObject, Class<T> clazz) { 32 return createProxy(shadowedObject, clazz); 33 } 34 createProxy(T shadowedObject, Class<T> clazz)35 private <T> T createProxy(T shadowedObject, Class<T> clazz) { 36 try { 37 return PROXY_MAKER.createProxy(clazz, shadowedObject); 38 } catch (Exception e) { 39 throw new RuntimeException("error creating direct call proxy for " + clazz, e); 40 } 41 } 42 43 @Override @SuppressWarnings(value = {"unchecked", "TypeParameterUnusedInFormals"}) directlyOn(Object shadowedObject, String clazzName, String methodName, ReflectionHelpers.ClassParameter... paramValues)44 public <R> R directlyOn(Object shadowedObject, String clazzName, String methodName, ReflectionHelpers.ClassParameter... paramValues) { 45 try { 46 Class<Object> aClass = (Class<Object>) shadowedObject.getClass().getClassLoader().loadClass(clazzName); 47 return directlyOn(shadowedObject, aClass, methodName, paramValues); 48 } catch (ClassNotFoundException e) { 49 throw new RuntimeException(e); 50 } 51 } 52 53 @Override @SuppressWarnings(value = {"unchecked", "TypeParameterUnusedInFormals"}) directlyOn(T shadowedObject, Class<T> clazz, String methodName, ReflectionHelpers.ClassParameter... paramValues)54 public <R, T> R directlyOn(T shadowedObject, Class<T> clazz, String methodName, ReflectionHelpers.ClassParameter... paramValues) { 55 String directMethodName = directMethodName(clazz.getName(), methodName); 56 return (R) ReflectionHelpers.callInstanceMethod(clazz, shadowedObject, directMethodName, paramValues); 57 } 58 59 @Override @SuppressWarnings(value = {"unchecked", "TypeParameterUnusedInFormals"}) directlyOn(Class<T> clazz, String methodName, ReflectionHelpers.ClassParameter... paramValues)60 public <R, T> R directlyOn(Class<T> clazz, String methodName, ReflectionHelpers.ClassParameter... paramValues) { 61 String directMethodName = directMethodName(clazz.getName(), methodName); 62 return (R) ReflectionHelpers.callStaticMethod(clazz, directMethodName, paramValues); 63 } 64 65 @Override @SuppressWarnings(value = {"unchecked", "TypeParameterUnusedInFormals"}) invokeConstructor(Class<? extends R> clazz, R instance, ReflectionHelpers.ClassParameter... paramValues)66 public <R> R invokeConstructor(Class<? extends R> clazz, R instance, ReflectionHelpers.ClassParameter... paramValues) { 67 String directMethodName = 68 directMethodName(clazz.getName(), ShadowConstants.CONSTRUCTOR_METHOD_NAME); 69 return (R) ReflectionHelpers.callInstanceMethod(clazz, instance, directMethodName, paramValues); 70 } 71 72 @Override directMethodName(String className, String methodName)73 public String directMethodName(String className, String methodName) { 74 return ShadowConstants.ROBO_PREFIX 75 + className.replace('.', '_').replace('$', '_') 76 + "$" + methodName; 77 } 78 79 } 80