1 package org.robolectric.plugins; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.util.LinkedHashMap; 6 import java.util.Map; 7 import java.util.Properties; 8 import javax.annotation.Nonnull; 9 import org.robolectric.pluginapi.config.Configurer; 10 11 /** 12 * Provides cached access to {@code robolectric-properties} files, for all your configuration needs! 13 * 14 * <p>Used by {@link ConfigConfigurer} to support package configuration (see [Configuring 15 * Robolectric](http://robolectric.org/configuring/) but it may be useful for other {@link 16 * Configurer}s as well. 17 */ 18 @SuppressWarnings({"AndroidJdkLibsChecker", "NewApi"}) 19 public class PackagePropertiesLoader { 20 21 /** 22 * We should get very high cache hit rates even with a tiny cache if we're called sequentially by 23 * multiple {@link Configurer}s for the same package. 24 */ 25 private final Map<String, Properties> cache = 26 new LinkedHashMap<String, Properties>() { 27 @Override 28 protected boolean removeEldestEntry(Map.Entry<String, Properties> eldest) { 29 return size() > 3; 30 } 31 }; 32 getConfig(@onnull String packageName, String propFileName)33 private Properties getConfig(@Nonnull String packageName, String propFileName) { 34 StringBuilder buf = new StringBuilder(); 35 if (!packageName.isEmpty()) { 36 buf.append(packageName.replace('.', '/')); 37 buf.append('/'); 38 } 39 String propsFile = buf.toString() + propFileName + ".properties"; 40 return cache.computeIfAbsent( 41 propsFile, 42 s -> { 43 final String resourceName = propsFile; 44 try (InputStream resourceAsStream = getResourceAsStream(resourceName)) { 45 if (resourceAsStream == null) { 46 return null; 47 } 48 Properties properties = new Properties(); 49 properties.load(resourceAsStream); 50 return properties; 51 } catch (IOException e) { 52 throw new RuntimeException(e); 53 } 54 }); 55 } 56 57 /** 58 * Return a {@link Properties} file for the given package name, or {@code null} if none is 59 * available. 60 * 61 * @since 3.2 62 */ getConfigProperties(@onnull String packageName)63 public Properties getConfigProperties(@Nonnull String packageName) { 64 return getConfig(packageName, "robolectric"); 65 } 66 67 // visible for testing getResourceAsStream(String resourceName)68 InputStream getResourceAsStream(String resourceName) { 69 return getClass().getClassLoader().getResourceAsStream(resourceName); 70 } 71 } 72