package org.robolectric.internal; import javax.annotation.Nonnull; import org.robolectric.internal.bytecode.InstrumentationConfiguration; import org.robolectric.internal.bytecode.SandboxClassLoader; import org.robolectric.internal.dependency.DependencyResolver; import org.robolectric.util.Pair; import java.net.URL; import java.net.URLClassLoader; import java.util.LinkedHashMap; import java.util.Map; public class SandboxFactory { public static final SandboxFactory INSTANCE = new SandboxFactory(); /** The factor for cache size. See {@link #CACHE_SIZE} for details. */ private static final int CACHE_SIZE_FACTOR = 3; /** We need to set the cache size of class loaders more than the number of supported APIs as different tests may have different configurations. */ private static final int CACHE_SIZE = SdkConfig.getSupportedApis().size() * CACHE_SIZE_FACTOR; // Simple LRU Cache. SdkEnvironments are unique across InstrumentationConfiguration and SdkConfig private final LinkedHashMap<Pair<InstrumentationConfiguration, SdkConfig>, SdkEnvironment> sdkToEnvironment = new LinkedHashMap<Pair<InstrumentationConfiguration, SdkConfig>, SdkEnvironment>() { @Override protected boolean removeEldestEntry(Map.Entry<Pair<InstrumentationConfiguration, SdkConfig>, SdkEnvironment> eldest) { return size() > CACHE_SIZE; } }; public synchronized SdkEnvironment getSdkEnvironment(InstrumentationConfiguration instrumentationConfig, DependencyResolver dependencyResolver, SdkConfig sdkConfig) { Pair<InstrumentationConfiguration, SdkConfig> key = Pair.create(instrumentationConfig, sdkConfig); SdkEnvironment sdkEnvironment = sdkToEnvironment.get(key); if (sdkEnvironment == null) { URL url = dependencyResolver.getLocalArtifactUrl(sdkConfig.getAndroidSdkDependency()); ClassLoader robolectricClassLoader = createClassLoader(instrumentationConfig, url); sdkEnvironment = new SdkEnvironment(sdkConfig, robolectricClassLoader); sdkToEnvironment.put(key, sdkEnvironment); } return sdkEnvironment; } @Nonnull public ClassLoader createClassLoader(InstrumentationConfiguration instrumentationConfig, URL... urls) { URLClassLoader systemClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader(); return new SandboxClassLoader(systemClassLoader, instrumentationConfig, urls); } }