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