From 053c072155daa2c3422b7c9a459d26755b72ff63 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 19 Sep 2013 18:08:24 +0100 Subject: [PATCH] Add some tests for PropertiesLauncher --- spring-boot-tools/spring-boot-loader/pom.xml | 11 + .../boot/loader/PropertiesLauncher.java | 17 +- .../util/PropertyPlaceholderHelper.java | 253 ------------------ .../boot/loader/util/SystemPropertyUtils.java | 172 +++++++++--- .../boot/loader/PropertiesLauncherTests.java | 68 +++++ .../loader/util/SystemPropertyUtilsTests.java | 56 ++++ .../src/test/resources/application.properties | 2 + .../src/test/resources/foo.properties | 2 + 8 files changed, 284 insertions(+), 297 deletions(-) delete mode 100644 spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/util/PropertyPlaceholderHelper.java create mode 100644 spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/PropertiesLauncherTests.java create mode 100644 spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/util/SystemPropertyUtilsTests.java create mode 100644 spring-boot-tools/spring-boot-loader/src/test/resources/application.properties create mode 100644 spring-boot-tools/spring-boot-loader/src/test/resources/foo.properties diff --git a/spring-boot-tools/spring-boot-loader/pom.xml b/spring-boot-tools/spring-boot-loader/pom.xml index ba5a42a410..22ce873645 100644 --- a/spring-boot-tools/spring-boot-loader/pom.xml +++ b/spring-boot-tools/spring-boot-loader/pom.xml @@ -12,6 +12,17 @@ ${basedir}/../.. + + + + org.slf4j + jcl-over-slf4j + + + ch.qos.logback + logback-classic + + diff --git a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/PropertiesLauncher.java b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/PropertiesLauncher.java index b05f3b26cb..a68b11546b 100644 --- a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/PropertiesLauncher.java +++ b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/PropertiesLauncher.java @@ -149,6 +149,7 @@ public class PropertiesLauncher extends Launcher { } protected void initialize() throws Exception { + String config = SystemPropertyUtils.resolvePlaceholders(System.getProperty( CONFIG_NAME, "application")) + ".properties"; while (config.startsWith("/")) { @@ -219,7 +220,7 @@ public class PropertiesLauncher extends Launcher { path = this.properties.getProperty(PATH); } if (path != null) { - path = SystemPropertyUtils.resolvePlaceholders(path, true); + path = SystemPropertyUtils.resolvePlaceholders(path); this.paths = new ArrayList(Arrays.asList(path.split(","))); for (int i = 0; i < this.paths.size(); i++) { this.paths.set(i, this.paths.get(i).trim()); @@ -234,13 +235,20 @@ public class PropertiesLauncher extends Launcher { this.logger.info("Not found: " + config); } for (int i = 0; i < this.paths.size(); i++) { + if (!this.paths.get(i).endsWith("/")) { + // Always a directory + this.paths.set(i, this.paths.get(i) + "/"); + } if (this.paths.get(i).startsWith("./")) { + // No need for current dir path this.paths.set(i, this.paths.get(i).substring(2)); } } for (Iterator iter = this.paths.iterator(); iter.hasNext();) { String path = iter.next(); if (path.equals(".") || path.equals("")) { + // Empty path is always on the classpath so no need for it to be + // explicitly listed here iter.remove(); } } @@ -278,12 +286,11 @@ public class PropertiesLauncher extends Launcher { @Override protected String getMainClass(Archive archive) throws Exception { if (System.getProperty(MAIN) != null) { - return SystemPropertyUtils - .resolvePlaceholders(System.getProperty(MAIN), true); + return SystemPropertyUtils.resolvePlaceholders(System.getProperty(MAIN)); } if (this.properties.containsKey(MAIN)) { - return SystemPropertyUtils.resolvePlaceholders( - this.properties.getProperty(MAIN), true); + return SystemPropertyUtils.resolvePlaceholders(this.properties + .getProperty(MAIN)); } return super.getMainClass(archive); } diff --git a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/util/PropertyPlaceholderHelper.java b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/util/PropertyPlaceholderHelper.java deleted file mode 100644 index 61634d295b..0000000000 --- a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/util/PropertyPlaceholderHelper.java +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright 2012-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.loader.util; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Properties; -import java.util.Set; - -/** - * Utility class for working with Strings that have placeholder values in them. A - * placeholder takes the form {@code $ name} . Using {@code PropertyPlaceholderHelper} - * these placeholders can be substituted for user-supplied values. - *

- * Values for substitution can be supplied using a {@link Properties} instance or using a - * {@link PlaceholderResolver}. - * - * @author Juergen Hoeller - * @author Rob Harrop - * @since 3.0 - */ -public class PropertyPlaceholderHelper { - - private static final Map wellKnownSimplePrefixes = new HashMap( - 4); - - static { - wellKnownSimplePrefixes.put("}", "{"); - wellKnownSimplePrefixes.put("]", "["); - wellKnownSimplePrefixes.put(")", "("); - } - - private final String placeholderPrefix; - - private final String placeholderSuffix; - - private final String simplePrefix; - - private final String valueSeparator; - - private final boolean ignoreUnresolvablePlaceholders; - - /** - * Creates a new {@code PropertyPlaceholderHelper} that uses the supplied prefix and - * suffix. Unresolvable placeholders are ignored. - * @param placeholderPrefix the prefix that denotes the start of a placeholder. - * @param placeholderSuffix the suffix that denotes the end of a placeholder. - */ - public PropertyPlaceholderHelper(String placeholderPrefix, String placeholderSuffix) { - this(placeholderPrefix, placeholderSuffix, null, true); - } - - /** - * Creates a new {@code PropertyPlaceholderHelper} that uses the supplied prefix and - * suffix. - * @param placeholderPrefix the prefix that denotes the start of a placeholder - * @param placeholderSuffix the suffix that denotes the end of a placeholder - * @param valueSeparator the separating character between the placeholder variable and - * the associated default value, if any - * @param ignoreUnresolvablePlaceholders indicates whether unresolvable placeholders - * should be ignored ({@code true}) or cause an exception ({@code false}). - */ - public PropertyPlaceholderHelper(String placeholderPrefix, String placeholderSuffix, - String valueSeparator, boolean ignoreUnresolvablePlaceholders) { - - Assert.notNull(placeholderPrefix, "placeholderPrefix must not be null"); - Assert.notNull(placeholderSuffix, "placeholderSuffix must not be null"); - this.placeholderPrefix = placeholderPrefix; - this.placeholderSuffix = placeholderSuffix; - String simplePrefixForSuffix = wellKnownSimplePrefixes - .get(this.placeholderSuffix); - if (simplePrefixForSuffix != null - && this.placeholderPrefix.endsWith(simplePrefixForSuffix)) { - this.simplePrefix = simplePrefixForSuffix; - } - else { - this.simplePrefix = this.placeholderPrefix; - } - this.valueSeparator = valueSeparator; - this.ignoreUnresolvablePlaceholders = ignoreUnresolvablePlaceholders; - } - - /** - * Replaces all placeholders of format ${name} with the corresponding - * property from the supplied {@link Properties}. - * @param value the value containing the placeholders to be replaced. - * @param properties the {@code Properties} to use for replacement. - * @return the supplied value with placeholders replaced inline. - */ - public String replacePlaceholders(String value, final Properties properties) { - Assert.notNull(properties, "Argument 'properties' must not be null."); - return replacePlaceholders(value, new PlaceholderResolver() { - @Override - public String resolvePlaceholder(String placeholderName) { - return properties.getProperty(placeholderName); - } - }); - } - - /** - * Replaces all placeholders of format {@code $ name} with the value returned from the - * supplied {@link PlaceholderResolver}. - * @param value the value containing the placeholders to be replaced. - * @param placeholderResolver the {@code PlaceholderResolver} to use for replacement. - * @return the supplied value with placeholders replaced inline. - */ - public String replacePlaceholders(String value, - PlaceholderResolver placeholderResolver) { - Assert.notNull(value, "Argument 'value' must not be null."); - return parseStringValue(value, placeholderResolver, new HashSet()); - } - - protected String parseStringValue(String strVal, - PlaceholderResolver placeholderResolver, Set visitedPlaceholders) { - - StringBuilder buf = new StringBuilder(strVal); - - int startIndex = strVal.indexOf(this.placeholderPrefix); - while (startIndex != -1) { - int endIndex = findPlaceholderEndIndex(buf, startIndex); - if (endIndex != -1) { - String placeholder = buf.substring( - startIndex + this.placeholderPrefix.length(), endIndex); - String originalPlaceholder = placeholder; - if (!visitedPlaceholders.add(originalPlaceholder)) { - throw new IllegalArgumentException("Circular placeholder reference '" - + originalPlaceholder + "' in property definitions"); - } - // Recursive invocation, parsing placeholders contained in the placeholder - // key. - placeholder = parseStringValue(placeholder, placeholderResolver, - visitedPlaceholders); - // Now obtain the value for the fully resolved key... - String propVal = placeholderResolver.resolvePlaceholder(placeholder); - if (propVal == null && this.valueSeparator != null) { - int separatorIndex = placeholder.indexOf(this.valueSeparator); - if (separatorIndex != -1) { - String actualPlaceholder = placeholder.substring(0, - separatorIndex); - String defaultValue = placeholder.substring(separatorIndex - + this.valueSeparator.length()); - propVal = placeholderResolver - .resolvePlaceholder(actualPlaceholder); - if (propVal == null) { - propVal = defaultValue; - } - } - } - if (propVal != null) { - // Recursive invocation, parsing placeholders contained in the - // previously resolved placeholder value. - propVal = parseStringValue(propVal, placeholderResolver, - visitedPlaceholders); - buf.replace(startIndex, endIndex + this.placeholderSuffix.length(), - propVal); - startIndex = buf.indexOf(this.placeholderPrefix, - startIndex + propVal.length()); - } - else if (this.ignoreUnresolvablePlaceholders) { - // Proceed with unprocessed value. - startIndex = buf.indexOf(this.placeholderPrefix, endIndex - + this.placeholderSuffix.length()); - } - else { - throw new IllegalArgumentException("Could not resolve placeholder '" - + placeholder + "'" + " in string value \"" + strVal + "\""); - } - visitedPlaceholders.remove(originalPlaceholder); - } - else { - startIndex = -1; - } - } - - return buf.toString(); - } - - private int findPlaceholderEndIndex(CharSequence buf, int startIndex) { - int index = startIndex + this.placeholderPrefix.length(); - int withinNestedPlaceholder = 0; - while (index < buf.length()) { - if (substringMatch(buf, index, this.placeholderSuffix)) { - if (withinNestedPlaceholder > 0) { - withinNestedPlaceholder--; - index = index + this.placeholderSuffix.length(); - } - else { - return index; - } - } - else if (substringMatch(buf, index, this.simplePrefix)) { - withinNestedPlaceholder++; - index = index + this.simplePrefix.length(); - } - else { - index++; - } - } - return -1; - } - - /** - * Strategy interface used to resolve replacement values for placeholders contained in - * Strings. - * @see PropertyPlaceholderHelper - */ - public static interface PlaceholderResolver { - - /** - * Resolves the supplied placeholder name into the replacement value. - * @param placeholderName the name of the placeholder to resolve - * @return the replacement value or {@code null} if no replacement is to be made - */ - String resolvePlaceholder(String placeholderName); - } - - public static boolean substringMatch(CharSequence str, int index, - CharSequence substring) { - for (int j = 0; j < substring.length(); j++) { - int i = index + j; - if (i >= str.length() || str.charAt(i) != substring.charAt(j)) { - return false; - } - } - return true; - } - - public static class Assert { - - public static void notNull(Object target, String message) { - if (target == null) { - throw new IllegalStateException(message); - } - } - - } - -} \ No newline at end of file diff --git a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/util/SystemPropertyUtils.java b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/util/SystemPropertyUtils.java index c69a985fc6..9b8a58378a 100644 --- a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/util/SystemPropertyUtils.java +++ b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/util/SystemPropertyUtils.java @@ -16,22 +16,27 @@ package org.springframework.boot.loader.util; -import org.springframework.boot.loader.util.PropertyPlaceholderHelper.PlaceholderResolver; +import java.util.HashSet; +import java.util.Set; + +import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver; /** * Helper class for resolving placeholders in texts. Usually applied to file paths. * *

- * A text may contain {@code $ ...}} placeholders, to be resolved as system properties: - * e.g. {@code $ user.dir}}. Default values can be supplied using the ":" separator + * A text may contain {@code $ ...} placeholders, to be resolved as system properties: + * e.g. {@code $ user.dir} . Default values can be supplied using the ":" separator * between key and value. * + *

+ * + * Adapted from Spring. + * * @author Juergen Hoeller * @author Rob Harrop * @author Dave Syer - * @since 1.2.5 - * @see #PLACEHOLDER_PREFIX - * @see #PLACEHOLDER_SUFFIX + * * @see System#getProperty(String) */ public abstract class SystemPropertyUtils { @@ -45,11 +50,7 @@ public abstract class SystemPropertyUtils { /** Value separator for system property placeholders: ":" */ public static final String VALUE_SEPARATOR = ":"; - private static final PropertyPlaceholderHelper strictHelper = new PropertyPlaceholderHelper( - PLACEHOLDER_PREFIX, PLACEHOLDER_SUFFIX, VALUE_SEPARATOR, false); - - private static final PropertyPlaceholderHelper nonStrictHelper = new PropertyPlaceholderHelper( - PLACEHOLDER_PREFIX, PLACEHOLDER_SUFFIX, VALUE_SEPARATOR, true); + private static final PropertyPlaceholderHelper helper = new PropertyPlaceholderHelper(); /** * Resolve ${...} placeholders in the given text, replacing them with corresponding @@ -61,40 +62,86 @@ public abstract class SystemPropertyUtils { * @throws IllegalArgumentException if there is an unresolvable placeholder */ public static String resolvePlaceholders(String text) { - return resolvePlaceholders(text, false); + return helper.replacePlaceholders(text); } - /** - * Resolve ${...} placeholders in the given text, replacing them with corresponding - * system property values. Unresolvable placeholders with no default value are ignored - * and passed through unchanged if the flag is set to true. - * @param text the String to resolve - * @param ignoreUnresolvablePlaceholders flag to determine is unresolved placeholders - * are ignored - * @return the resolved String - * @see #PLACEHOLDER_PREFIX - * @see #PLACEHOLDER_SUFFIX - * @throws IllegalArgumentException if there is an unresolvable placeholder and the - * flag is false - */ - public static String resolvePlaceholders(String text, - boolean ignoreUnresolvablePlaceholders) { - PropertyPlaceholderHelper helper = (ignoreUnresolvablePlaceholders ? nonStrictHelper - : strictHelper); - return helper.replacePlaceholders(text, new SystemPropertyPlaceholderResolver( - text)); - } + static protected class PropertyPlaceholderHelper { - private static class SystemPropertyPlaceholderResolver implements PlaceholderResolver { + private static final String simplePrefix = PLACEHOLDER_PREFIX.substring(1); - private final String text; + /** + * Replaces all placeholders of format {@code $ name} with the value returned from + * the supplied {@link PlaceholderResolver}. + * @param value the value containing the placeholders to be replaced. + * @return the supplied value with placeholders replaced inline. + */ + public String replacePlaceholders(String value) { + Assert.notNull(value, "Argument 'value' must not be null."); + return parseStringValue(value, value, new HashSet()); + } + + private String parseStringValue(String value, String current, + Set visitedPlaceholders) { + + StringBuilder buf = new StringBuilder(current); + + int startIndex = current.indexOf(PLACEHOLDER_PREFIX); + while (startIndex != -1) { + int endIndex = findPlaceholderEndIndex(buf, startIndex); + if (endIndex != -1) { + String placeholder = buf.substring( + startIndex + PLACEHOLDER_PREFIX.length(), endIndex); + String originalPlaceholder = placeholder; + if (!visitedPlaceholders.add(originalPlaceholder)) { + throw new IllegalArgumentException( + "Circular placeholder reference '" + originalPlaceholder + + "' in property definitions"); + } + // Recursive invocation, parsing placeholders contained in the + // placeholder + // key. + placeholder = parseStringValue(value, placeholder, + visitedPlaceholders); + // Now obtain the value for the fully resolved key... + String propVal = resolvePlaceholder(value, placeholder); + if (propVal == null && VALUE_SEPARATOR != null) { + int separatorIndex = placeholder.indexOf(VALUE_SEPARATOR); + if (separatorIndex != -1) { + String actualPlaceholder = placeholder.substring(0, + separatorIndex); + String defaultValue = placeholder.substring(separatorIndex + + VALUE_SEPARATOR.length()); + propVal = resolvePlaceholder(value, actualPlaceholder); + if (propVal == null) { + propVal = defaultValue; + } + } + } + if (propVal != null) { + // Recursive invocation, parsing placeholders contained in the + // previously resolved placeholder value. + propVal = parseStringValue(value, propVal, visitedPlaceholders); + buf.replace(startIndex, endIndex + PLACEHOLDER_SUFFIX.length(), + propVal); + startIndex = buf.indexOf(PLACEHOLDER_PREFIX, + startIndex + propVal.length()); + } + else { + // Proceed with unprocessed value. + startIndex = buf.indexOf(PLACEHOLDER_PREFIX, endIndex + + PLACEHOLDER_SUFFIX.length()); + } + visitedPlaceholders.remove(originalPlaceholder); + } + else { + startIndex = -1; + } + } - public SystemPropertyPlaceholderResolver(String text) { - this.text = text; + return buf.toString(); } - @Override - public String resolvePlaceholder(String placeholderName) { + private String resolvePlaceholder(String text, String placeholderName) { try { String propVal = System.getProperty(placeholderName); if (propVal == null) { @@ -105,10 +152,57 @@ public abstract class SystemPropertyUtils { } catch (Throwable ex) { System.err.println("Could not resolve placeholder '" + placeholderName - + "' in [" + this.text + "] as system property: " + ex); + + "' in [" + text + "] as system property: " + ex); return null; } } + + private int findPlaceholderEndIndex(CharSequence buf, int startIndex) { + int index = startIndex + PLACEHOLDER_PREFIX.length(); + int withinNestedPlaceholder = 0; + while (index < buf.length()) { + if (substringMatch(buf, index, PLACEHOLDER_SUFFIX)) { + if (withinNestedPlaceholder > 0) { + withinNestedPlaceholder--; + index = index + PLACEHOLDER_SUFFIX.length(); + } + else { + return index; + } + } + else if (substringMatch(buf, index, + PropertyPlaceholderHelper.simplePrefix)) { + withinNestedPlaceholder++; + index = index + PropertyPlaceholderHelper.simplePrefix.length(); + } + else { + index++; + } + } + return -1; + } + + private static boolean substringMatch(CharSequence str, int index, + CharSequence substring) { + for (int j = 0; j < substring.length(); j++) { + int i = index + j; + if (i >= str.length() || str.charAt(i) != substring.charAt(j)) { + return false; + } + } + return true; + } + + private static class Assert { + + public static void notNull(Object target, String message) { + if (target == null) { + throw new IllegalStateException(message); + } + } + + } + } } diff --git a/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/PropertiesLauncherTests.java b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/PropertiesLauncherTests.java new file mode 100644 index 0000000000..aae8fee959 --- /dev/null +++ b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/PropertiesLauncherTests.java @@ -0,0 +1,68 @@ +/* + * Copyright 2012-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.loader; + +import org.junit.After; +import org.junit.Test; +import org.springframework.test.util.ReflectionTestUtils; + +import static org.junit.Assert.assertEquals; + +/** + * @author Dave Syer + */ +public class PropertiesLauncherTests { + + private PropertiesLauncher launcher = new PropertiesLauncher(); + + @After + public void close() { + System.clearProperty("loader.home"); + System.clearProperty("loader.path"); + System.clearProperty("loader.main"); + System.clearProperty("loader.config.name"); + System.clearProperty("loader.config.location"); + } + + @Test + public void testDefaultHome() { + assertEquals(System.getProperty("user.dir"), this.launcher.getHomeDirectory()); + } + + @Test + public void testUserSpecifiedMain() throws Exception { + this.launcher.initialize(); + assertEquals("demo.Application", this.launcher.getMainClass(null)); + } + + @Test + public void testUserSpecifiedConfigName() throws Exception { + System.setProperty("loader.config.name", "foo"); + this.launcher.initialize(); + assertEquals("my.Application", this.launcher.getMainClass(null)); + assertEquals("[etc/]", ReflectionTestUtils.getField(this.launcher, "paths") + .toString()); + } + + @Test + public void testSystemPropertySpecifiedMain() throws Exception { + System.setProperty("loader.main", "foo.Bar"); + this.launcher.initialize(); + assertEquals("foo.Bar", this.launcher.getMainClass(null)); + } + +} diff --git a/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/util/SystemPropertyUtilsTests.java b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/util/SystemPropertyUtilsTests.java new file mode 100644 index 0000000000..ce57cb4808 --- /dev/null +++ b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/util/SystemPropertyUtilsTests.java @@ -0,0 +1,56 @@ +/* + * Copyright 2012-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.loader.util; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.boot.loader.util.SystemPropertyUtils; + +import static org.junit.Assert.assertEquals; + +/** + * @author Dave Syer + */ +public class SystemPropertyUtilsTests { + + @BeforeClass + public static void init() { + System.setProperty("foo", "bar"); + } + + @AfterClass + public static void close() { + System.clearProperty("foo"); + } + + @Test + public void testVanillaPlaceholder() { + assertEquals("bar", SystemPropertyUtils.resolvePlaceholders("${foo}")); + } + + @Test + public void testDefaultValue() { + assertEquals("foo", SystemPropertyUtils.resolvePlaceholders("${bar:foo}")); + } + + @Test + public void testNestedPlaceholder() { + assertEquals("foo", SystemPropertyUtils.resolvePlaceholders("${bar:${spam:foo}}")); + } + +} diff --git a/spring-boot-tools/spring-boot-loader/src/test/resources/application.properties b/spring-boot-tools/spring-boot-loader/src/test/resources/application.properties new file mode 100644 index 0000000000..36edcf1c96 --- /dev/null +++ b/spring-boot-tools/spring-boot-loader/src/test/resources/application.properties @@ -0,0 +1,2 @@ +loader.main: demo.Application +loader.path: etc/,lib,. \ No newline at end of file diff --git a/spring-boot-tools/spring-boot-loader/src/test/resources/foo.properties b/spring-boot-tools/spring-boot-loader/src/test/resources/foo.properties new file mode 100644 index 0000000000..495dc6b44d --- /dev/null +++ b/spring-boot-tools/spring-boot-loader/src/test/resources/foo.properties @@ -0,0 +1,2 @@ +loader.main: my.Application +loader.path: etc \ No newline at end of file