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