package org.robolectric.internal.bytecode; import org.robolectric.shadow.api.Shadow; import java.util.Set; import static org.robolectric.util.ReflectionHelpers.newInstance; import static org.robolectric.util.ReflectionHelpers.setStaticField; public class Sandbox { private final ClassLoader robolectricClassLoader; private final ShadowInvalidator shadowInvalidator; public ClassHandler classHandler; // todo not public private ShadowMap shadowMap = ShadowMap.EMPTY; public Sandbox(ClassLoader robolectricClassLoader) { this.robolectricClassLoader = robolectricClassLoader; this.shadowInvalidator = new ShadowInvalidator(); } public <T> Class<T> bootstrappedClass(Class<?> clazz) { try { return (Class<T>) robolectricClassLoader.loadClass(clazz.getName()); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } public ClassLoader getRobolectricClassLoader() { return robolectricClassLoader; } public ShadowInvalidator getShadowInvalidator() { return shadowInvalidator; } public void replaceShadowMap(ShadowMap shadowMap) { if (InvokeDynamic.ENABLED) { ShadowMap oldShadowMap = this.shadowMap; this.shadowMap = shadowMap; Set<String> invalidatedClasses = shadowMap.getInvalidatedClasses(oldShadowMap); getShadowInvalidator().invalidateClasses(invalidatedClasses); } } public void configure(ClassHandler classHandler, Interceptors interceptors) { this.classHandler = classHandler; ClassLoader robolectricClassLoader = getRobolectricClassLoader(); ShadowInvalidator invalidator = getShadowInvalidator(); Class<?> robolectricInternalsClass = bootstrappedClass(RobolectricInternals.class); setStaticField(robolectricInternalsClass, "classHandler", classHandler); setStaticField(robolectricInternalsClass, "shadowInvalidator", invalidator); setStaticField(robolectricInternalsClass, "classLoader", robolectricClassLoader); Class<?> invokeDynamicSupportClass = bootstrappedClass(InvokeDynamicSupport.class); setStaticField(invokeDynamicSupportClass, "INTERCEPTORS", interceptors); Class<?> shadowClass = bootstrappedClass(Shadow.class); setStaticField(shadowClass, "SHADOW_IMPL", newInstance(bootstrappedClass(ShadowImpl.class))); } }