Settings implements Serializable { void substituteVariables(Properties p) { Preconditions.checkNotNull(p); for (Map.Entry<Object, Object> entry : p.entrySet()) { String key = entry.getKey().toString(); String value = entry.getValue().toString(); StringBuilder b = new StringBuilder(); int pos, prev = 0, end = 0; if (value.matches(".*(\\$\\{(\\s*\\w.+\\s*)\\}).*")) { while ((pos = value.indexOf('$', prev)) >= 0) { if (value.charAt(pos + 1) != '{') { prev = pos + 1; } else { if (pos > prev) { prev = value.charAt(prev) == '}' ? prev + 1 : prev; b.append(value.substring(prev, pos)); } end = value.indexOf('}', pos); if (end == -1) { throw new IllegalStateException( "can't substitute value in " + value + " (there is no ending '}')" ); } String variable = value.substring(pos + 2, end); String substitutedValue = p.getProperty(variable); if (!Strings.isNullOrEmpty(substitutedValue)) { log.debug(String.format( "resolved variable %s to value %s from same settings", variable, substitutedValue)); } else { substitutedValue = properties.getProperty(variable); if (!Strings.isNullOrEmpty(substitutedValue)) { log.debug(String.format( "resolved variable %s to value %s from previously loaded settings", variable, substitutedValue)); } else { substitutedValue = System.getProperty(variable); if (!Strings.isNullOrEmpty(substitutedValue)) { log.debug(String.format( "resolved variable %s to value %s from system properties", variable, substitutedValue)); } else { String msg = String.format( "unable to substitute variable %s for property %s (value = %s)", variable, key, value); log.warn(msg); substitutedValue = "${" + variable + "}"; } } } b.append(substitutedValue); prev = end; } } } if (b.length() != 0) { if (value.length() > end + 1) { b.append(value.substring(end + 1)); } p.setProperty(key, b.toString()); } } } Settings(); synchronized void loadFromClassPath(String location); synchronized void loadFromProperties(Properties p); synchronized void loadFromFile(String location); Object set(String source, String setting, @Nullable String value); Object set(String setting, @Nullable String value); static KeyIteratorFilter startsWith(String prefix); static KeyIteratorFilter endsWith(String prefix); static KeyIteratorFilter contains(String string); static KeyIteratorFilter notContains(String string); static KeyIteratorFilter matches(String regex); static KeyIteratorFilter[] join(KeyIteratorFilter filter,
                                           KeyIteratorFilter... filters); Keys keys(); Keys keys(@Nullable KeyIteratorFilter... filter); MappedSettings<T> map(@Nullable String prefix, Class<T> type); MappedSettings<T> map(@Nullable String prefix,
                                     Class<T> type,
                                     KeyIteratorFilter... filters); boolean isDefined(String key); @Nullable String getString(String key); @Nullable Integer getInteger(String key); @Nullable Long getLong(String key); @Nullable Double getDouble(String key); Boolean getBoolean(String key); @Nullable BigDecimal getBigDecimal(String key); String getString(String key, String defaultValue); Long getLong(String key, @Nullable Long defaultValue); Integer getInteger(String key, @Nullable Integer defaultValue); Double getDouble(String key, @Nullable Double defaultValue); @Nullable BigDecimal getBigDecimal(String key, @Nullable BigDecimal defaultValue); Boolean getBoolean(String key, @Nullable Boolean defaultValue); Properties asProperties(); Properties asProperties(@Nullable String prefixForCutoff); Map<String, String> asMap(); Map<String, String> asMap(@Nullable String prefixForCutoff); synchronized List<String> getLocationsLoaded(); void addListener(SettingsListener l); void removeListener(SettingsListener l); @Override String toString(); static SettingsBuilder builder(); static final String OVERRIDES_FILE_SYSTEM_PROPERTY; }
@Test public void testSubstitutions() { Properties p = new Properties(); p.setProperty("test.name", "Ben"); p.setProperty("test.message1", "Hello ${test.name}"); p.setProperty("test.message2", "${test.name} says hello"); p.setProperty("test.message3", "Teh ${test.name} iz ${test.name} here"); p.setProperty("test.message4", "${test.name} has a ${test.name} in his ${test.name}, ${test.name}"); p.setProperty("test.nosub", "$Rev: 1234$"); p.setProperty("test.message5", "this var is ${irreplaceable}!"); Settings settings = new Settings(); settings.substituteVariables(p); Assert.assertEquals("Hello Ben", p.getProperty("test.message1")); Assert.assertEquals("Ben says hello", p.getProperty("test.message2")); Assert.assertEquals("Teh Ben iz Ben here", p.getProperty("test.message3")); Assert.assertEquals("Ben has a Ben in his Ben, Ben", p.getProperty("test.message4")); Assert.assertEquals("this var is ${irreplaceable}!", p.getProperty("test.message5")); }