diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/info/EnvironmentInfoContributor.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/info/EnvironmentInfoContributor.java index adefd96fe4..d0ffb41168 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/info/EnvironmentInfoContributor.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/info/EnvironmentInfoContributor.java @@ -16,6 +16,7 @@ package org.springframework.boot.actuate.info; +import org.springframework.boot.bind.PropertySourcesBinder; import org.springframework.core.env.ConfigurableEnvironment; /** diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/info/InfoPropertiesInfoContributor.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/info/InfoPropertiesInfoContributor.java index b9d73313e7..2dd58a9ba7 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/info/InfoPropertiesInfoContributor.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/info/InfoPropertiesInfoContributor.java @@ -20,8 +20,8 @@ import java.util.Collections; import java.util.Map; import java.util.Properties; +import org.springframework.boot.bind.PropertySourcesBinder; import org.springframework.boot.info.InfoProperties; -import org.springframework.core.env.MutablePropertySources; import org.springframework.core.env.PropertySource; import org.springframework.util.StringUtils; @@ -84,9 +84,7 @@ public abstract class InfoPropertiesInfoContributor im * @return the raw content */ protected Map extractContent(PropertySource propertySource) { - MutablePropertySources propertySources = new MutablePropertySources(); - propertySources.addFirst(propertySource); - return new PropertySourcesBinder(propertySources).extractAll(""); + return new PropertySourcesBinder(propertySource).extractAll(""); } /** diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointAutoConfigurationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointAutoConfigurationTests.java index e1cc0814d1..73d303505f 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointAutoConfigurationTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointAutoConfigurationTests.java @@ -49,12 +49,13 @@ import org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration; import org.springframework.boot.autoconfigure.info.ProjectInfoProperties; import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration; import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration; -import org.springframework.boot.bind.PropertiesConfigurationFactory; +import org.springframework.boot.bind.PropertySourcesBinder; import org.springframework.boot.test.EnvironmentTestUtils; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; +import org.springframework.core.env.PropertiesPropertySource; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PropertiesLoaderUtils; import org.springframework.validation.BindException; @@ -262,18 +263,15 @@ public class EndpointAutoConfigurationTests { private static class GitFullInfoContributor implements InfoContributor { - private final Map content; + private Map content = new LinkedHashMap(); GitFullInfoContributor(Resource location) throws BindException, IOException { - this.content = new LinkedHashMap(); if (location.exists()) { - PropertiesConfigurationFactory> factory = new PropertiesConfigurationFactory>( - this.content); - factory.setTargetName("git"); Properties gitInfoProperties = PropertiesLoaderUtils .loadProperties(location); - factory.setProperties(gitInfoProperties); - factory.bindPropertiesToTarget(); + PropertiesPropertySource gitPropertySource = + new PropertiesPropertySource("git", gitInfoProperties); + this.content = new PropertySourcesBinder(gitPropertySource).extractAll("git"); } } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/info/PropertySourcesBinder.java b/spring-boot/src/main/java/org/springframework/boot/bind/PropertySourcesBinder.java similarity index 61% rename from spring-boot-actuator/src/main/java/org/springframework/boot/actuate/info/PropertySourcesBinder.java rename to spring-boot/src/main/java/org/springframework/boot/bind/PropertySourcesBinder.java index 76db2cf9ba..212d7e8a28 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/info/PropertySourcesBinder.java +++ b/spring-boot/src/main/java/org/springframework/boot/bind/PropertySourcesBinder.java @@ -14,13 +14,16 @@ * limitations under the License. */ -package org.springframework.boot.actuate.info; +package org.springframework.boot.bind; import java.util.LinkedHashMap; import java.util.Map; -import org.springframework.boot.bind.PropertiesConfigurationFactory; +import org.springframework.core.convert.ConversionService; import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.Environment; +import org.springframework.core.env.MutablePropertySources; +import org.springframework.core.env.PropertySource; import org.springframework.core.env.PropertySources; import org.springframework.util.StringUtils; import org.springframework.validation.BindException; @@ -33,20 +36,50 @@ import org.springframework.validation.BindException; */ public class PropertySourcesBinder { - private final PropertySources propertySources; + private PropertySources propertySources; + private ConversionService conversionService; + + /** + * Create a new instance. + * @param propertySources the {@link PropertySources} to use + */ public PropertySourcesBinder(PropertySources propertySources) { this.propertySources = propertySources; } + /** + * Create a new instance from a single {@link PropertySource}. + * @param propertySource the {@link PropertySource} to use + */ + public PropertySourcesBinder(PropertySource propertySource) { + this(createPropertySources(propertySource)); + } + + /** + * Create a new instance using the {@link Environment} as the property sources. + * @param environment the environment + */ public PropertySourcesBinder(ConfigurableEnvironment environment) { this(environment.getPropertySources()); } - public final PropertySources getPropertySources() { + public void setPropertySources(PropertySources propertySources) { + this.propertySources = propertySources; + } + + public PropertySources getPropertySources() { return this.propertySources; } + public void setConversionService(ConversionService conversionService) { + this.conversionService = conversionService; + } + + public ConversionService getConversionService() { + return this.conversionService; + } + /** * Extract the keys using the specified {@code prefix}. The * prefix won't be included. @@ -74,6 +107,9 @@ public class PropertySourcesBinder { if (StringUtils.hasText(prefix)) { factory.setTargetName(prefix); } + if (this.conversionService != null) { + factory.setConversionService(this.conversionService); + } factory.setPropertySources(this.propertySources); try { factory.bindPropertiesToTarget(); @@ -83,4 +119,10 @@ public class PropertySourcesBinder { } } + private static PropertySources createPropertySources(PropertySource propertySource) { + MutablePropertySources propertySources = new MutablePropertySources(); + propertySources.addLast(propertySource); + return propertySources; + } + } diff --git a/spring-boot/src/test/java/org/springframework/boot/bind/PropertySourcesBinderTests.java b/spring-boot/src/test/java/org/springframework/boot/bind/PropertySourcesBinderTests.java new file mode 100644 index 0000000000..5e50215fc7 --- /dev/null +++ b/spring-boot/src/test/java/org/springframework/boot/bind/PropertySourcesBinderTests.java @@ -0,0 +1,94 @@ +/* + * Copyright 2012-2016 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.bind; + +import java.util.Map; + +import org.junit.Test; + +import org.springframework.boot.testutil.EnvironmentTestUtils; +import org.springframework.core.env.StandardEnvironment; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link PropertySourcesBinder}. + * + * @author Stephane Nicoll + */ +public class PropertySourcesBinderTests { + + private StandardEnvironment env = new StandardEnvironment(); + + @Test + public void extractAllWithPrefix() { + EnvironmentTestUtils.addEnvironment(this.env, "foo.first=1", "foo.second=2"); + Map content = new PropertySourcesBinder(this.env).extractAll("foo"); + assertThat(content.get("first")).isEqualTo("1"); + assertThat(content.get("second")).isEqualTo("2"); + assertThat(content).hasSize(2); + } + + @Test + @SuppressWarnings("unchecked") + public void extractNoPrefix() { + EnvironmentTestUtils.addEnvironment(this.env, "foo.ctx.first=1", "foo.ctx.second=2"); + Map content = new PropertySourcesBinder(this.env).extractAll(""); + assertThat(content.get("foo")).isInstanceOf(Map.class); + Map foo = (Map) content.get("foo"); + assertThat(content.get("foo")).isInstanceOf(Map.class); + Map ctx = (Map) foo.get("ctx"); + assertThat(ctx.get("first")).isEqualTo("1"); + assertThat(ctx.get("second")).isEqualTo("2"); + assertThat(ctx).hasSize(2); + assertThat(foo).hasSize(1); + } + + @Test + public void bindToSimplePojo() { + EnvironmentTestUtils.addEnvironment(this.env, "test.name=foo", "test.counter=42"); + TestBean bean = new TestBean(); + new PropertySourcesBinder(this.env).bindTo("test", bean); + assertThat(bean.getName()).isEqualTo("foo"); + assertThat(bean.getCounter()).isEqualTo(42); + } + + + private static class TestBean { + private String name; + + private Integer counter; + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getCounter() { + return this.counter; + } + + public void setCounter(Integer counter) { + this.counter = counter; + } + + } + +}