diff --git a/spring-boot-project/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/env/DevToolsHomePropertiesPostProcessor.java b/spring-boot-project/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/env/DevToolsHomePropertiesPostProcessor.java index aaa324f73a47..8400be2bdea5 100644 --- a/spring-boot-project/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/env/DevToolsHomePropertiesPostProcessor.java +++ b/spring-boot-project/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/env/DevToolsHomePropertiesPostProcessor.java @@ -19,6 +19,7 @@ import java.io.File; import java.io.IOException; import java.util.Properties; +import java.util.logging.Logger; import org.springframework.boot.SpringApplication; import org.springframework.boot.devtools.DevToolsEnablementDeducer; @@ -35,30 +36,48 @@ * * @author Phillip Webb * @author Andy Wilkinson + * @author HaiTao Zhang * @since 1.3.0 */ public class DevToolsHomePropertiesPostProcessor implements EnvironmentPostProcessor { - private static final String FILE_NAME = ".spring-boot-devtools.properties"; + private static final String[] FILE_NAMES = new String[] { ".spring-boot-devtools.yml", ".spring-boot-devtools.yaml", + ".spring-boot-devtools.properties" }; + + private Logger logger = Logger.getLogger(getClass().getName()); @Override public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { if (DevToolsEnablementDeducer.shouldEnable(Thread.currentThread())) { File home = getHomeFolder(); - File propertyFile = (home != null) ? new File(home, FILE_NAME) : null; + Properties properties = processDir(home, "/.config/spring-boot/", environment); + if (properties.isEmpty()) { + processDir(home, "", environment); + } + } + } + + private Properties processDir(File home, String configPath, ConfigurableEnvironment environment) { + Properties properties = new Properties(); + for (String fileName : FILE_NAMES) { + File propertyFile = (home != null) ? new File(home, configPath + fileName) : null; if (propertyFile != null && propertyFile.exists() && propertyFile.isFile()) { - FileSystemResource resource = new FileSystemResource(propertyFile); - Properties properties; - try { - properties = PropertiesLoaderUtils.loadProperties(resource); - environment.getPropertySources() - .addFirst(new PropertiesPropertySource("devtools-local", properties)); - } - catch (IOException ex) { - throw new IllegalStateException("Unable to load " + FILE_NAME, ex); - } + addProperty(propertyFile, environment, fileName, properties); } } + return properties; + } + + private void addProperty(File propertyFile, ConfigurableEnvironment environment, String fileName, + Properties properties) { + FileSystemResource resource = new FileSystemResource(propertyFile); + try { + PropertiesLoaderUtils.fillProperties(properties, resource); + environment.getPropertySources().addFirst(new PropertiesPropertySource("devtools-local", properties)); + } + catch (IOException ex) { + throw new IllegalStateException("Unable to load " + fileName, ex); + } } protected File getHomeFolder() { diff --git a/spring-boot-project/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/env/DevToolsHomePropertiesPostProcessorTests.java b/spring-boot-project/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/env/DevToolsHomePropertiesPostProcessorTests.java index d7f74ea938b8..0d87a3ac682b 100644 --- a/spring-boot-project/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/env/DevToolsHomePropertiesPostProcessorTests.java +++ b/spring-boot-project/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/env/DevToolsHomePropertiesPostProcessorTests.java @@ -36,6 +36,7 @@ * * @author Phillip Webb * @author Andy Wilkinson + * @author HaiTao Zhang */ class DevToolsHomePropertiesPostProcessorTests { @@ -47,7 +48,7 @@ void setup(@TempDir File tempDir) throws IOException { } @Test - void loadsHomeProperties() throws Exception { + void loadsPropertiesFromHomeFolderUsingProperties() throws Exception { Properties properties = new Properties(); properties.put("abc", "def"); OutputStream out = new FileOutputStream(new File(this.home, ".spring-boot-devtools.properties")); @@ -59,6 +60,137 @@ void loadsHomeProperties() throws Exception { assertThat(environment.getProperty("abc")).isEqualTo("def"); } + @Test + void loadsPropertiesFromHomeFolderUsingYml() throws Exception { + Properties properties = new Properties(); + properties.put("abc", "def"); + OutputStream out = new FileOutputStream(new File(this.home, ".spring-boot-devtools.yml")); + properties.store(out, null); + out.close(); + ConfigurableEnvironment environment = new MockEnvironment(); + MockDevToolHomePropertiesPostProcessor postProcessor = new MockDevToolHomePropertiesPostProcessor(); + runPostProcessor(() -> postProcessor.postProcessEnvironment(environment, null)); + assertThat(environment.getProperty("abc")).isEqualTo("def"); + } + + @Test + void loadsPropertiesFromHomeFolderUsingYaml() throws Exception { + Properties properties = new Properties(); + properties.put("abc", "def"); + OutputStream out = new FileOutputStream(new File(this.home, ".spring-boot-devtools.yaml")); + properties.store(out, null); + out.close(); + ConfigurableEnvironment environment = new MockEnvironment(); + MockDevToolHomePropertiesPostProcessor postProcessor = new MockDevToolHomePropertiesPostProcessor(); + runPostProcessor(() -> postProcessor.postProcessEnvironment(environment, null)); + assertThat(environment.getProperty("abc")).isEqualTo("def"); + } + + @Test + void loadsPropertiesFromConfigFolderUsingProperties() throws Exception { + Properties properties = new Properties(); + new File(this.home + "/.config/spring-boot").mkdirs(); + properties.put("abc", "def"); + OutputStream out = new FileOutputStream( + new File(this.home + "/.config/spring-boot", ".spring-boot-devtools.properties")); + properties.store(out, null); + out.close(); + ConfigurableEnvironment environment = new MockEnvironment(); + MockDevToolHomePropertiesPostProcessor postProcessor = new MockDevToolHomePropertiesPostProcessor(); + runPostProcessor(() -> postProcessor.postProcessEnvironment(environment, null)); + assertThat(environment.getProperty("abc")).isEqualTo("def"); + } + + @Test + void loadsPropertiesFromConfigFolderUsingYml() throws Exception { + Properties properties = new Properties(); + new File(this.home + "/.config/spring-boot").mkdirs(); + properties.put("abc", "def"); + OutputStream out = new FileOutputStream( + new File(this.home + "/.config/spring-boot", ".spring-boot-devtools.yml")); + properties.store(out, null); + out.close(); + ConfigurableEnvironment environment = new MockEnvironment(); + MockDevToolHomePropertiesPostProcessor postProcessor = new MockDevToolHomePropertiesPostProcessor(); + runPostProcessor(() -> postProcessor.postProcessEnvironment(environment, null)); + assertThat(environment.getProperty("abc")).isEqualTo("def"); + } + + @Test + void loadsPropertiesFromConfigFolderUsingYaml() throws Exception { + Properties properties = new Properties(); + new File(this.home + "/.config/spring-boot").mkdirs(); + properties.put("abc", "def"); + OutputStream out = new FileOutputStream( + new File(this.home + "/.config/spring-boot", ".spring-boot-devtools.yaml")); + properties.store(out, null); + out.close(); + ConfigurableEnvironment environment = new MockEnvironment(); + MockDevToolHomePropertiesPostProcessor postProcessor = new MockDevToolHomePropertiesPostProcessor(); + runPostProcessor(() -> postProcessor.postProcessEnvironment(environment, null)); + assertThat(environment.getProperty("abc")).isEqualTo("def"); + } + + @Test + void loadFromConfigFolderWithPropertiesTakingPrecedence() throws Exception { + Properties properties = new Properties(); + properties.put("abc", "def"); + new File(this.home + "/.config/spring-boot").mkdirs(); + OutputStream out = new FileOutputStream( + new File(this.home + "/.config/spring-boot/", ".spring-boot-devtools.yaml")); + properties.store(out, null); + out.close(); + Properties properties2 = new Properties(); + properties2.put("abc", "jkl"); + OutputStream out2 = new FileOutputStream( + new File(this.home + "/.config/spring-boot/", ".spring-boot-devtools.properties")); + properties2.store(out2, null); + out2.close(); + ConfigurableEnvironment environment = new MockEnvironment(); + MockDevToolHomePropertiesPostProcessor postProcessor = new MockDevToolHomePropertiesPostProcessor(); + runPostProcessor(() -> postProcessor.postProcessEnvironment(environment, null)); + assertThat(environment.getProperty("abc")).isEqualTo("jkl"); + } + + @Test + void loadFromHomeFolderWithPropertiesTakingPrecedence() throws Exception { + Properties properties = new Properties(); + properties.put("abc", "def"); + new File(this.home + "/.config/spring-boot").mkdirs(); + OutputStream out = new FileOutputStream(new File(this.home, ".spring-boot-devtools.yaml")); + properties.store(out, null); + out.close(); + Properties properties2 = new Properties(); + properties2.put("abc", "jkl"); + OutputStream out2 = new FileOutputStream(new File(this.home, ".spring-boot-devtools.properties")); + properties2.store(out2, null); + out2.close(); + ConfigurableEnvironment environment = new MockEnvironment(); + MockDevToolHomePropertiesPostProcessor postProcessor = new MockDevToolHomePropertiesPostProcessor(); + runPostProcessor(() -> postProcessor.postProcessEnvironment(environment, null)); + assertThat(environment.getProperty("abc")).isEqualTo("jkl"); + } + + @Test + void loadFromConfigFolderTakesPrecedenceOverHomeFolder() throws Exception { + Properties properties = new Properties(); + properties.put("abc", "def"); + new File(this.home + "/.config/spring-boot").mkdirs(); + OutputStream out = new FileOutputStream(new File(this.home, ".spring-boot-devtools.properties")); + properties.store(out, null); + out.close(); + Properties properties2 = new Properties(); + properties2.put("abc", "jkl"); + OutputStream out2 = new FileOutputStream( + new File(this.home + "/.config/spring-boot/", ".spring-boot-devtools.properties")); + properties2.store(out2, null); + out2.close(); + ConfigurableEnvironment environment = new MockEnvironment(); + MockDevToolHomePropertiesPostProcessor postProcessor = new MockDevToolHomePropertiesPostProcessor(); + runPostProcessor(() -> postProcessor.postProcessEnvironment(environment, null)); + assertThat(environment.getProperty("abc")).isEqualTo("jkl"); + } + @Test void ignoresMissingHomeProperties() throws Exception { ConfigurableEnvironment environment = new MockEnvironment();