1 package org.robolectric.internal; 2 3 import java.net.URL; 4 import java.util.LinkedHashMap; 5 import java.util.Map; 6 import javax.annotation.Nonnull; 7 import org.robolectric.internal.bytecode.InstrumentationConfiguration; 8 import org.robolectric.internal.bytecode.SandboxClassLoader; 9 import org.robolectric.internal.dependency.DependencyResolver; 10 import org.robolectric.util.Pair; 11 12 public class SandboxFactory { 13 public static final SandboxFactory INSTANCE = new SandboxFactory(); 14 15 /** The factor for cache size. See {@link #CACHE_SIZE} for details. */ 16 private static final int CACHE_SIZE_FACTOR = 3; 17 18 /** We need to set the cache size of class loaders more than the number of supported APIs as different tests may have different configurations. */ 19 private static final int CACHE_SIZE = SdkConfig.getSupportedApis().size() * CACHE_SIZE_FACTOR; 20 21 // Simple LRU Cache. SdkEnvironments are unique across InstrumentationConfiguration and SdkConfig 22 private final LinkedHashMap<Pair<InstrumentationConfiguration, SdkConfig>, SdkEnvironment> sdkToEnvironment = new LinkedHashMap<Pair<InstrumentationConfiguration, SdkConfig>, SdkEnvironment>() { 23 @Override 24 protected boolean removeEldestEntry(Map.Entry<Pair<InstrumentationConfiguration, SdkConfig>, SdkEnvironment> eldest) { 25 return size() > CACHE_SIZE; 26 } 27 }; 28 29 public synchronized SdkEnvironment getSdkEnvironment(InstrumentationConfiguration instrumentationConfig, DependencyResolver dependencyResolver, SdkConfig sdkConfig) { 30 Pair<InstrumentationConfiguration, SdkConfig> key = Pair.create(instrumentationConfig, sdkConfig); 31 32 SdkEnvironment sdkEnvironment = sdkToEnvironment.get(key); 33 if (sdkEnvironment == null) { 34 URL url = dependencyResolver.getLocalArtifactUrl(sdkConfig.getAndroidSdkDependency()); 35 36 ClassLoader robolectricClassLoader = createClassLoader(instrumentationConfig, url); 37 sdkEnvironment = new SdkEnvironment(sdkConfig, robolectricClassLoader); 38 39 sdkToEnvironment.put(key, sdkEnvironment); 40 } 41 return sdkEnvironment; 42 } 43 44 @Nonnull 45 public ClassLoader createClassLoader(InstrumentationConfiguration instrumentationConfig, URL... urls) { 46 return new SandboxClassLoader(ClassLoader.getSystemClassLoader(), instrumentationConfig, urls); 47 } 48 49 } 50