diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/DevToolHomePropertiesPostProcessor.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/DevToolHomePropertiesPostProcessor.java new file mode 100644 index 00000000000..445d743d552 --- /dev/null +++ b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/DevToolHomePropertiesPostProcessor.java @@ -0,0 +1,85 @@ +/* + * Copyright 2012-2015 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.devtools.autoconfigure; + +import java.io.File; +import java.io.IOException; +import java.util.Properties; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.context.EnvironmentAware; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.Environment; +import org.springframework.core.env.PropertiesPropertySource; +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.support.PropertiesLoaderUtils; +import org.springframework.util.StringUtils; + +/** + * {@link BeanFactoryPostProcessor} to add devtools properties from the users home folder. + * + * @author Phillip Webb + * @since 1.3.0 + */ +public class DevToolHomePropertiesPostProcessor implements BeanFactoryPostProcessor, + EnvironmentAware { + + private static final String FILE_NAME = ".spring-boot-devtools.properties"; + + private Environment environment; + + @Override + public void setEnvironment(Environment environment) { + this.environment = environment; + } + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) + throws BeansException { + if (this.environment instanceof ConfigurableEnvironment) { + try { + postProcessEnvironment((ConfigurableEnvironment) this.environment); + } + catch (IOException ex) { + throw new IllegalStateException("Unable to load " + FILE_NAME, ex); + } + } + } + + private void postProcessEnvironment(ConfigurableEnvironment environment) + throws IOException { + File home = getHomeFolder(); + File propertyFile = (home == null ? null : new File(home, FILE_NAME)); + if (propertyFile != null && propertyFile.exists() && propertyFile.isFile()) { + FileSystemResource resource = new FileSystemResource(propertyFile); + Properties properties = PropertiesLoaderUtils.loadProperties(resource); + environment.getPropertySources().addFirst( + new PropertiesPropertySource("devtools-local", properties)); + } + } + + protected File getHomeFolder() { + String home = System.getProperty("user.home"); + if (StringUtils.hasLength(home)) { + return new File(home); + } + return null; + } + +} diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/LocalDevToolsAutoConfiguration.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/LocalDevToolsAutoConfiguration.java index add8581c9ce..2b17b542aa1 100644 --- a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/LocalDevToolsAutoConfiguration.java +++ b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/LocalDevToolsAutoConfiguration.java @@ -58,6 +58,11 @@ public class LocalDevToolsAutoConfiguration { return new DevToolsPropertyDefaultsPostProcessor(); } + @Bean + public static DevToolHomePropertiesPostProcessor devToolHomePropertiesPostProcessor() { + return new DevToolHomePropertiesPostProcessor(); + } + /** * Local LiveReload configuration. */ diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/remote/client/RemoteClientConfiguration.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/remote/client/RemoteClientConfiguration.java index 2a44f46eb2f..fe2a7523e01 100644 --- a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/remote/client/RemoteClientConfiguration.java +++ b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/remote/client/RemoteClientConfiguration.java @@ -33,6 +33,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.devtools.autoconfigure.DevToolHomePropertiesPostProcessor; import org.springframework.boot.devtools.autoconfigure.DevToolsProperties; import org.springframework.boot.devtools.autoconfigure.DevToolsProperties.Restart; import org.springframework.boot.devtools.autoconfigure.OptionalLiveReloadServer; @@ -86,6 +87,11 @@ public class RemoteClientConfiguration { return new PropertySourcesPlaceholderConfigurer(); } + @Bean + public static DevToolHomePropertiesPostProcessor devToolHomePropertiesPostProcessor() { + return new DevToolHomePropertiesPostProcessor(); + } + @Bean public ClientHttpRequestFactory clientHttpRequestFactory() { List interceptors = Arrays diff --git a/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/DevToolHomePropertiesPostProcessorTests.java b/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/DevToolHomePropertiesPostProcessorTests.java new file mode 100644 index 00000000000..330997bf963 --- /dev/null +++ b/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/DevToolHomePropertiesPostProcessorTests.java @@ -0,0 +1,88 @@ +/* + * Copyright 2012-2015 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.devtools.autoconfigure; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Properties; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.core.env.Environment; +import org.springframework.mock.env.MockEnvironment; + +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; + +/** + * Tests for {@link DevToolHomePropertiesPostProcessor}. + * + * @author Phillip Webb + */ +public class DevToolHomePropertiesPostProcessorTests { + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + private File home; + + @Before + public void setup() throws IOException { + this.home = this.temp.newFolder(); + } + + @Test + public void loadsHomeProperties() throws Exception { + Properties properties = new Properties(); + properties.put("abc", "def"); + OutputStream out = new FileOutputStream(new File(this.home, + ".spring-boot-devtools.properties")); + properties.store(out, null); + out.close(); + Environment environment = new MockEnvironment(); + MockDevToolHomePropertiesPostProcessor postProcessor = new MockDevToolHomePropertiesPostProcessor(); + postProcessor.setEnvironment(environment); + postProcessor.postProcessBeanFactory(mock(ConfigurableListableBeanFactory.class)); + assertThat(environment.getProperty("abc"), equalTo("def")); + } + + @Test + public void ignoresMissingHomeProperties() throws Exception { + Environment environment = new MockEnvironment(); + MockDevToolHomePropertiesPostProcessor postProcessor = new MockDevToolHomePropertiesPostProcessor(); + postProcessor.setEnvironment(environment); + postProcessor.postProcessBeanFactory(mock(ConfigurableListableBeanFactory.class)); + assertThat(environment.getProperty("abc"), nullValue()); + } + + private class MockDevToolHomePropertiesPostProcessor extends + DevToolHomePropertiesPostProcessor { + + @Override + protected File getHomeFolder() { + return DevToolHomePropertiesPostProcessorTests.this.home; + } + } + +} diff --git a/spring-boot-samples/spring-boot-sample-devtools/src/main/java/demo/SampleDevToolsApplication.java b/spring-boot-samples/spring-boot-sample-devtools/src/main/java/demo/SampleDevToolsApplication.java index 61d0bd9a620..9a9cca90d6f 100644 --- a/spring-boot-samples/spring-boot-sample-devtools/src/main/java/demo/SampleDevToolsApplication.java +++ b/spring-boot-samples/spring-boot-sample-devtools/src/main/java/demo/SampleDevToolsApplication.java @@ -26,4 +26,5 @@ public class SampleDevToolsApplication extends WebMvcAutoConfigurationAdapter { public static void main(String[] args) { SpringApplication.run(SampleDevToolsApplication.class, args); } + }