• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.robolectric.internal.bytecode;
2 
3 import java.lang.reflect.InvocationTargetException;
4 import org.robolectric.internal.IShadow;
5 import org.robolectric.util.ReflectionHelpers;
6 
7 public class ShadowImpl implements IShadow {
8 
9   private final ProxyMaker proxyMaker = new ProxyMaker(this::directMethodName);
10 
11   @Override
12   @SuppressWarnings("TypeParameterUnusedInFormals")
extract(Object instance)13   public <T> T extract(Object instance) {
14     return (T) ((ShadowedObject) instance).$$robo$getData();
15   }
16 
newInstanceOf(Class<T> clazz)17   @Override public <T> T newInstanceOf(Class<T> clazz) {
18     return ReflectionHelpers.callConstructor(clazz);
19   }
20 
21   @Override
newInstance(Class<T> clazz, Class<?>[] parameterTypes, Object[] params)22   public <T> T newInstance(Class<T> clazz, Class<?>[] parameterTypes, Object[] params) {
23     return ReflectionHelpers.callConstructor(clazz, ReflectionHelpers.ClassParameter.fromComponentLists(parameterTypes, params));
24   }
25 
26   /**
27    * Returns a proxy object that invokes the original $$robo$$-prefixed methods for {@code
28    * shadowedObject}.
29    *
30    * @deprecated This is incompatible with JDK17+. Use a {@link
31    *     org.robolectric.util.reflector.Reflector} interface with {@link
32    *     org.robolectric.util.reflector.Direct}.
33    */
34   @Deprecated
35   @Override
directlyOn(T shadowedObject, Class<T> clazz)36   public <T> T directlyOn(T shadowedObject, Class<T> clazz) {
37     return createProxy(shadowedObject, clazz);
38   }
39 
40   @Override
41   @SuppressWarnings(value = {"unchecked", "TypeParameterUnusedInFormals"})
directlyOn( Object shadowedObject, String clazzName, String methodName, ReflectionHelpers.ClassParameter<?>... paramValues)42   public <R> R directlyOn(
43       Object shadowedObject,
44       String clazzName,
45       String methodName,
46       ReflectionHelpers.ClassParameter<?>... paramValues) {
47     try {
48       Class<Object> aClass =
49           (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
57   @SuppressWarnings(value = {"unchecked", "TypeParameterUnusedInFormals"})
directlyOn( T shadowedObject, Class<T> clazz, String methodName, ReflectionHelpers.ClassParameter<?>... paramValues)58   public <R, T> R directlyOn(
59       T shadowedObject,
60       Class<T> clazz,
61       String methodName,
62       ReflectionHelpers.ClassParameter<?>... paramValues) {
63     String directMethodName = directMethodName(clazz.getName(), methodName);
64     return (R)
65         ReflectionHelpers.callInstanceMethod(clazz, shadowedObject, directMethodName, paramValues);
66   }
67 
68   @Override
69   @SuppressWarnings(value = {"unchecked", "TypeParameterUnusedInFormals"})
directlyOn( Class<T> clazz, String methodName, ReflectionHelpers.ClassParameter<?>... paramValues)70   public <R, T> R directlyOn(
71       Class<T> clazz, String methodName, ReflectionHelpers.ClassParameter<?>... paramValues) {
72     String directMethodName = directMethodName(clazz.getName(), methodName);
73     return (R) ReflectionHelpers.callStaticMethod(clazz, directMethodName, paramValues);
74   }
75 
createProxy(T shadowedObject, Class<T> clazz)76   private <T> T createProxy(T shadowedObject, Class<T> clazz) {
77     return proxyMaker.createProxy(clazz, shadowedObject);
78   }
79 
80   @Override
81   @SuppressWarnings(value = {"unchecked", "TypeParameterUnusedInFormals"})
invokeConstructor( Class<? extends R> clazz, R instance, ReflectionHelpers.ClassParameter<?>... paramValues)82   public <R> R invokeConstructor(
83       Class<? extends R> clazz, R instance, ReflectionHelpers.ClassParameter<?>... paramValues) {
84     String directMethodName =
85         directMethodName(clazz.getName(), ShadowConstants.CONSTRUCTOR_METHOD_NAME);
86     return (R) ReflectionHelpers.callInstanceMethod(clazz, instance, directMethodName, paramValues);
87   }
88 
89   @Override
directMethodName(String className, String methodName)90   public String directMethodName(String className, String methodName) {
91      return ShadowConstants.ROBO_PREFIX
92       + className.replace('.', '_').replace('$', '_')
93       + "$" + methodName;
94   }
95 
96   @Override
directNativeMethodName(String className, String methodName)97   public String directNativeMethodName(String className, String methodName) {
98     return ShadowConstants.ROBO_PREFIX + methodName + "$nativeBinding";
99   }
100 
101   @Override
directInitialize(Class<?> clazz)102   public void directInitialize(Class<?> clazz) {
103     try {
104       RobolectricInternals.performStaticInitialization(clazz);
105     } catch (InvocationTargetException | IllegalAccessException e) {
106       throw new RuntimeException("failed to initialize " + clazz, e);
107     }
108   }
109 
110 }
111