Rework configuration properties support

Closes gh-9000
This commit is contained in:
Phillip Webb 2017-04-27 14:34:41 -07:00
commit 25f0b3482c
240 changed files with 13303 additions and 3669 deletions

View File

@ -35,7 +35,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ConditionContext;
@ -50,6 +49,7 @@ import org.springframework.util.StringUtils;
*
* @author Christian Dupuis
* @author Andy Wilkinson
* @author Madhura Bhave
*/
@Configuration
@Conditional(JmxEnabledCondition.class)
@ -103,8 +103,10 @@ public class EndpointMBeanExportAutoConfiguration {
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
boolean jmxEnabled = isEnabled(context, "spring.jmx.");
boolean jmxEndpointsEnabled = isEnabled(context, "endpoints.jmx.");
boolean jmxEnabled = context.getEnvironment()
.getProperty("spring.jmx.enabled", Boolean.class, true);
boolean jmxEndpointsEnabled = context.getEnvironment()
.getProperty("endpoints.jmx.enabled", Boolean.class, true);
if (jmxEnabled && jmxEndpointsEnabled) {
return ConditionOutcome.match(
ConditionMessage.forCondition("JMX Enabled").found("properties")
@ -114,12 +116,6 @@ public class EndpointMBeanExportAutoConfiguration {
.because("spring.jmx.enabled or endpoints.jmx.enabled is not set"));
}
private boolean isEnabled(ConditionContext context, String prefix) {
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
context.getEnvironment(), prefix);
return resolver.getProperty("enabled", Boolean.class, true);
}
}
}

View File

@ -49,7 +49,6 @@ import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.event.ApplicationFailedEvent;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
@ -89,6 +88,7 @@ import org.springframework.web.servlet.DispatcherServlet;
* @author Johannes Edmeier
* @author Eddú Meléndez
* @author Venil Noronha
* @author Madhura Bhave
*/
@Configuration
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class })
@ -133,9 +133,9 @@ public class EndpointWebMvcAutoConfiguration
@Override
public void afterSingletonsInstantiated() {
ManagementServerPort managementPort = ManagementServerPort.DIFFERENT;
Environment environment = this.applicationContext.getEnvironment();
if (this.applicationContext instanceof WebApplicationContext) {
managementPort = ManagementServerPort
.get(this.applicationContext.getEnvironment());
managementPort = ManagementServerPort.get(environment);
}
if (managementPort == ManagementServerPort.DIFFERENT) {
if (this.applicationContext instanceof ServletWebServerApplicationContext
@ -150,17 +150,14 @@ public class EndpointWebMvcAutoConfiguration
}
}
if (managementPort == ManagementServerPort.SAME) {
if (new RelaxedPropertyResolver(this.applicationContext.getEnvironment(),
"management.ssl.").getProperty("enabled") != null) {
if (environment.getProperty("management.ssl.enabled") != null) {
throw new IllegalStateException(
"Management-specific SSL cannot be configured as the management "
+ "server is not listening on a separate port");
}
if (this.applicationContext
.getEnvironment() instanceof ConfigurableEnvironment) {
if (environment instanceof ConfigurableEnvironment) {
addLocalManagementPortPropertyAlias(
(ConfigurableEnvironment) this.applicationContext
.getEnvironment());
(ConfigurableEnvironment) environment);
}
}
}
@ -356,9 +353,7 @@ public class EndpointWebMvcAutoConfiguration
}
private static Integer getPortProperty(Environment environment, String prefix) {
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(environment,
prefix);
return resolver.getProperty("port", Integer.class);
return environment.getProperty(prefix + "port", Integer.class);
}
}

View File

@ -47,7 +47,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ConditionContext;
@ -64,6 +63,7 @@ import org.springframework.web.cors.CorsConfiguration;
* @author Dave Syer
* @author Ben Hale
* @author Vedran Pavic
* @author Madhura Bhave
* @since 1.3.0
*/
@ManagementContextConfiguration
@ -225,8 +225,7 @@ public class EndpointWebMvcManagementContextConfiguration {
return ConditionOutcome
.match(message.found("logging.path").items(config));
}
config = new RelaxedPropertyResolver(environment, "endpoints.logfile.")
.getProperty("external-file");
config = environment.getProperty("endpoints.logfile.external-file");
if (StringUtils.hasText(config)) {
return ConditionOutcome.match(
message.found("endpoints.logfile.external-file").items(config));

View File

@ -33,7 +33,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplicat
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ConditionContext;
@ -60,6 +59,7 @@ import org.springframework.web.servlet.mvc.ServletWrappingController;
* @author Christian Dupuis
* @author Dave Syer
* @author Andy Wilkinson
* @author Madhura Bhave
*/
@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ -108,9 +108,8 @@ public class JolokiaAutoConfiguration {
private boolean isEnabled(ConditionContext context, String prefix,
boolean defaultValue) {
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
context.getEnvironment(), prefix);
return resolver.getProperty("enabled", Boolean.class, defaultValue);
return context.getEnvironment().getProperty(prefix + "enabled", Boolean.class,
defaultValue);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -21,9 +21,9 @@ import java.lang.annotation.Annotation;
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
/**
@ -31,6 +31,7 @@ import org.springframework.core.type.AnnotatedTypeMetadata;
* {@code defaults} name or individually via the name of the element.
*
* @author Stephane Nicoll
* @author Madhura Bhave
*/
abstract class OnEnabledEndpointElementCondition extends SpringBootCondition {
@ -59,10 +60,10 @@ abstract class OnEnabledEndpointElementCondition extends SpringBootCondition {
protected ConditionOutcome getEndpointOutcome(ConditionContext context,
String endpointName) {
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
context.getEnvironment(), this.prefix + endpointName + ".");
if (resolver.containsProperty("enabled")) {
boolean match = resolver.getProperty("enabled", Boolean.class, true);
Environment environment = context.getEnvironment();
String enabledProperty = this.prefix + endpointName + ".enabled";
if (environment.containsProperty(enabledProperty)) {
boolean match = environment.getProperty(enabledProperty, Boolean.class, true);
return new ConditionOutcome(match,
ConditionMessage.forCondition(this.annotationType).because(
this.prefix + endpointName + ".enabled is " + match));
@ -71,9 +72,8 @@ abstract class OnEnabledEndpointElementCondition extends SpringBootCondition {
}
protected ConditionOutcome getDefaultEndpointsOutcome(ConditionContext context) {
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
context.getEnvironment(), this.prefix + "defaults.");
boolean match = Boolean.valueOf(resolver.getProperty("enabled", "true"));
boolean match = Boolean.valueOf(context.getEnvironment()
.getProperty(this.prefix + "defaults.enabled", "true"));
return new ConditionOutcome(match,
ConditionMessage.forCondition(this.annotationType).because(
this.prefix + "defaults.enabled is considered " + match));

View File

@ -30,7 +30,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnCloudPlatform;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.security.IgnoredRequestCustomizer;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.cloud.CloudPlatform;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
@ -84,11 +83,9 @@ public class CloudFoundryActuatorAutoConfiguration {
private CloudFoundrySecurityService getCloudFoundrySecurityService(
RestTemplateBuilder restTemplateBuilder, Environment environment) {
RelaxedPropertyResolver cloudFoundryProperties = new RelaxedPropertyResolver(
environment, "management.cloudfoundry.");
String cloudControllerUrl = environment.getProperty("vcap.application.cf_api");
boolean skipSslValidation = cloudFoundryProperties
.getProperty("skip-ssl-validation", Boolean.class, false);
boolean skipSslValidation = environment.getProperty(
"management.cloudfoundry.skip-ssl-validation", Boolean.class, false);
return cloudControllerUrl == null ? null
: new CloudFoundrySecurityService(restTemplateBuilder, cloudControllerUrl,
skipSslValidation);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -19,16 +19,17 @@ package org.springframework.boot.actuate.condition;
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
/**
* {@link Condition} that checks whether or not an endpoint is enabled.
*
* @author Andy Wilkinson
* @author Madhura Bhave
*/
class OnEnabledEndpointCondition extends SpringBootCondition {
@ -49,10 +50,10 @@ class OnEnabledEndpointCondition extends SpringBootCondition {
private ConditionOutcome determineEndpointOutcome(String endpointName,
boolean enabledByDefault, ConditionContext context) {
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
context.getEnvironment(), "endpoints." + endpointName + ".");
if (resolver.containsProperty("enabled") || !enabledByDefault) {
boolean match = resolver.getProperty("enabled", Boolean.class,
Environment environment = context.getEnvironment();
String enabledProperty = "endpoints." + endpointName + ".enabled";
if (environment.containsProperty(enabledProperty) || !enabledByDefault) {
boolean match = environment.getProperty(enabledProperty, Boolean.class,
enabledByDefault);
ConditionMessage message = ConditionMessage
.forCondition(ConditionalOnEnabledEndpoint.class,
@ -64,9 +65,8 @@ class OnEnabledEndpointCondition extends SpringBootCondition {
}
private ConditionOutcome determineAllEndpointsOutcome(ConditionContext context) {
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
context.getEnvironment(), "endpoints.");
boolean match = Boolean.valueOf(resolver.getProperty("enabled", "true"));
boolean match = Boolean.valueOf(
context.getEnvironment().getProperty("endpoints.enabled", "true"));
ConditionMessage message = ConditionMessage
.forCondition(ConditionalOnEnabledEndpoint.class)
.because("All endpoints are " + (match ? "enabled" : "disabled")

View File

@ -17,6 +17,7 @@
package org.springframework.boot.actuate.endpoint.mvc;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@ -27,18 +28,13 @@ import javax.servlet.http.HttpServletRequest;
import org.springframework.boot.actuate.endpoint.HealthEndpoint;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.Status;
import org.springframework.boot.bind.RelaxedNames;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ResponseBody;
/**
@ -53,8 +49,9 @@ import org.springframework.web.bind.annotation.ResponseBody;
* @since 1.1.0
*/
@ConfigurationProperties(prefix = "endpoints.health")
public class HealthMvcEndpoint extends AbstractEndpointMvcAdapter<HealthEndpoint>
implements EnvironmentAware {
public class HealthMvcEndpoint extends AbstractEndpointMvcAdapter<HealthEndpoint> {
private static final List<String> DEFAULT_ROLES = Arrays.asList("ROLE_ACTUATOR");
private final boolean secure;
@ -62,8 +59,6 @@ public class HealthMvcEndpoint extends AbstractEndpointMvcAdapter<HealthEndpoint
private Map<String, HttpStatus> statusMapping = new HashMap<>();
private RelaxedPropertyResolver securityPropertyResolver;
private long lastAccess = 0;
private Health cached;
@ -73,15 +68,16 @@ public class HealthMvcEndpoint extends AbstractEndpointMvcAdapter<HealthEndpoint
}
public HealthMvcEndpoint(HealthEndpoint delegate, boolean secure) {
this(delegate, secure, null);
this(delegate, secure, new ArrayList<>(DEFAULT_ROLES));
}
public HealthMvcEndpoint(HealthEndpoint delegate, boolean secure,
List<String> roles) {
super(delegate);
Assert.notNull(roles, "Roles must not be null");
this.secure = secure;
setupDefaultStatusMapping();
this.roles = roles;
setupDefaultStatusMapping();
}
private void setupDefaultStatusMapping() {
@ -89,12 +85,6 @@ public class HealthMvcEndpoint extends AbstractEndpointMvcAdapter<HealthEndpoint
addStatusMapping(Status.OUT_OF_SERVICE, HttpStatus.SERVICE_UNAVAILABLE);
}
@Override
public void setEnvironment(Environment environment) {
this.securityPropertyResolver = new RelaxedPropertyResolver(environment,
"management.security.");
}
/**
* Set specific status mappings.
* @param statusMapping a map of status code to {@link HttpStatus}
@ -151,19 +141,28 @@ public class HealthMvcEndpoint extends AbstractEndpointMvcAdapter<HealthEndpoint
}
private HttpStatus getStatus(Health health) {
String code = health.getStatus().getCode();
String code = getUniformValue(health.getStatus().getCode());
if (code != null) {
code = code.toLowerCase().replace('_', '-');
for (String candidate : RelaxedNames.forCamelCase(code)) {
HttpStatus status = this.statusMapping.get(candidate);
if (status != null) {
return status;
}
}
return this.statusMapping.keySet().stream()
.filter((key) -> code.equals(getUniformValue(key)))
.map(this.statusMapping::get).findFirst().orElse(null);
}
return null;
}
private String getUniformValue(String code) {
if (code == null) {
return null;
}
StringBuilder builder = new StringBuilder();
for (char ch : code.toCharArray()) {
if (Character.isAlphabetic(ch) || Character.isDigit(ch)) {
builder.append(Character.toLowerCase(ch));
}
}
return builder.toString();
}
private Health getHealth(HttpServletRequest request, Principal principal) {
long accessTime = System.currentTimeMillis();
if (isCacheStale(accessTime)) {
@ -207,14 +206,8 @@ public class HealthMvcEndpoint extends AbstractEndpointMvcAdapter<HealthEndpoint
}
private List<String> getRoles() {
if (this.roles != null) {
return this.roles;
}
String[] roles = StringUtils.commaDelimitedListToStringArray(
this.securityPropertyResolver.getProperty("roles", "ROLE_ACTUATOR"));
roles = StringUtils.trimArrayElements(roles);
return Arrays.asList(roles);
}
private boolean isSpringSecurityAuthentication(Principal principal) {
return ClassUtils.isPresent("org.springframework.security.core.Authentication",

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -16,7 +16,10 @@
package org.springframework.boot.actuate.info;
import org.springframework.boot.bind.PropertySourcesBinder;
import java.util.Map;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.core.env.ConfigurableEnvironment;
/**
@ -24,19 +27,24 @@ import org.springframework.core.env.ConfigurableEnvironment;
*
* @author Meang Akira Tanaka
* @author Stephane Nicoll
* @author Madhura Bhave
* @since 1.4.0
*/
public class EnvironmentInfoContributor implements InfoContributor {
private final PropertySourcesBinder binder;
private static final Bindable<Map<String, Object>> STRING_OBJECT_MAP = Bindable
.mapOf(String.class, Object.class);
private final ConfigurableEnvironment environment;
public EnvironmentInfoContributor(ConfigurableEnvironment environment) {
this.binder = new PropertySourcesBinder(environment);
this.environment = environment;
}
@Override
public void contribute(Info.Builder builder) {
builder.withDetails(this.binder.extractAll("info"));
Binder binder = Binder.get(this.environment);
binder.bind("info", STRING_OBJECT_MAP).ifBound(builder::withDetails);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -17,11 +17,15 @@
package org.springframework.boot.actuate.info;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
import org.springframework.boot.bind.PropertySourcesBinder;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.boot.info.InfoProperties;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.util.StringUtils;
@ -30,11 +34,15 @@ import org.springframework.util.StringUtils;
*
* @param <T> the type of the {@link InfoProperties} to expose
* @author Stephane Nicoll
* @author Madhura Bhave
* @since 1.4.0
*/
public abstract class InfoPropertiesInfoContributor<T extends InfoProperties>
implements InfoContributor {
private static final Bindable<Map<String, Object>> STRING_OBJECT_MAP = Bindable
.mapOf(String.class, Object.class);
private final T properties;
private final Mode mode;
@ -85,7 +93,10 @@ public abstract class InfoPropertiesInfoContributor<T extends InfoProperties>
* @return the raw content
*/
protected Map<String, Object> extractContent(PropertySource<?> propertySource) {
return new PropertySourcesBinder(propertySource).extractAll("");
MutablePropertySources sources = new MutablePropertySources();
sources.addFirst(propertySource);
return new Binder(ConfigurationPropertySources.get(sources))
.bind("", STRING_OBJECT_MAP).orElseGet(LinkedHashMap::new);
}
/**

View File

@ -21,7 +21,6 @@ import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
import javax.sql.DataSource;
@ -55,14 +54,16 @@ import org.springframework.boot.autoconfigure.info.ProjectInfoProperties;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration;
import org.springframework.boot.bind.PropertySourcesBinder;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.MapConfigurationPropertySource;
import org.springframework.boot.logging.LoggingSystem;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.ResolvableType;
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;
@ -310,17 +311,19 @@ public class EndpointAutoConfigurationTests {
private static class GitFullInfoContributor implements InfoContributor {
private static final ResolvableType STRING_OBJECT_MAP = ResolvableType
.forClassWithGenerics(Map.class, String.class, Object.class);
private Map<String, Object> content = new LinkedHashMap<>();
GitFullInfoContributor(Resource location) throws BindException, IOException {
if (location.exists()) {
Properties gitInfoProperties = PropertiesLoaderUtils
.loadProperties(location);
PropertiesPropertySource gitPropertySource = new PropertiesPropertySource(
"git", gitInfoProperties);
this.content = new PropertySourcesBinder(gitPropertySource)
.extractAll("git");
if (!location.exists()) {
return;
}
MapConfigurationPropertySource source = new MapConfigurationPropertySource(
PropertiesLoaderUtils.loadProperties(location));
new Binder(source).bind("info",
Bindable.of(STRING_OBJECT_MAP).withExistingValue(this.content));
}
@Override

View File

@ -62,6 +62,7 @@ import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactor
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration;
import org.springframework.boot.context.event.ApplicationFailedEvent;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.boot.logging.LoggingSystem;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.boot.testutil.Matched;
@ -357,7 +358,7 @@ public class EndpointWebMvcAutoConfigurationTests {
@Test
public void contextPath() throws Exception {
EnvironmentTestUtils.addEnvironment(this.applicationContext,
"management.contextPath:/test", "management.security.enabled:false");
"management.context-path:/test", "management.security.enabled:false");
this.applicationContext.register(RootConfig.class, EndpointConfig.class,
PropertyPlaceholderAutoConfiguration.class,
JacksonAutoConfiguration.class,
@ -448,7 +449,7 @@ public class EndpointWebMvcAutoConfigurationTests {
this.applicationContext.register(RootConfig.class, BaseConfiguration.class,
EndpointWebMvcAutoConfiguration.class);
EnvironmentTestUtils.addEnvironment(this.applicationContext,
"ENDPOINTS_ENABLED:false");
"endpoints.enabled:false");
this.applicationContext.refresh();
assertThat(this.applicationContext.getBeansOfType(MvcEndpoint.class)).isEmpty();
}
@ -646,9 +647,10 @@ public class EndpointWebMvcAutoConfigurationTests {
throws Exception {
this.applicationContext.register(LoggingConfig.class, RootConfig.class,
BaseConfiguration.class, EndpointWebMvcAutoConfiguration.class);
ConfigurationPropertySources.attach(this.applicationContext.getEnvironment());
EnvironmentTestUtils.addEnvironment(this.applicationContext,
"endpoints.enabled:false",
String.format("endpoints_%s_enabled:true", name));
String.format("endpoints.%s.enabled:true", name));
this.applicationContext.refresh();
assertThat(this.applicationContext.getBeansOfType(type)).hasSize(1);
}

View File

@ -34,6 +34,7 @@ import org.springframework.boot.autoconfigure.security.IgnoredRequestCustomizer;
import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration;
import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.http.HttpMethod;
import org.springframework.mock.web.MockHttpServletRequest;
@ -120,6 +121,7 @@ public class CloudFoundryActuatorAutoConfigurationTests {
public void skipSslValidation() throws Exception {
EnvironmentTestUtils.addEnvironment(this.context,
"management.cloudfoundry.skipSslValidation:true");
ConfigurationPropertySources.attach(this.context.getEnvironment());
this.context.refresh();
CloudFoundryEndpointHandlerMapping handlerMapping = getHandlerMapping();
Object interceptor = ReflectionTestUtils.getField(handlerMapping,

View File

@ -16,8 +16,10 @@
package org.springframework.boot.actuate.endpoint.mvc;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
@ -28,11 +30,8 @@ import org.junit.Test;
import org.springframework.boot.actuate.endpoint.HealthEndpoint;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.Status;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockServletContext;
import org.springframework.security.core.Authentication;
@ -54,9 +53,8 @@ import static org.mockito.Mockito.mock;
*/
public class HealthMvcEndpointTests {
private static final PropertySource<?> SECURITY_ROLES = new MapPropertySource("test",
Collections.<String, Object>singletonMap("management.security.roles",
"HERO"));
private static final List<String> SECURITY_ROLES = new ArrayList<>(
Arrays.asList("HERO"));
private HttpServletRequest request = new MockHttpServletRequest();
@ -64,8 +62,6 @@ public class HealthMvcEndpointTests {
private HealthMvcEndpoint mvc = null;
private MockEnvironment environment;
private HttpServletRequest defaultUser = createAuthenticationRequest("ROLE_ACTUATOR");
private HttpServletRequest hero = createAuthenticationRequest("HERO");
@ -81,8 +77,6 @@ public class HealthMvcEndpointTests {
this.endpoint = mock(HealthEndpoint.class);
given(this.endpoint.isEnabled()).willReturn(true);
this.mvc = new HealthMvcEndpoint(this.endpoint);
this.environment = new MockEnvironment();
this.mvc.setEnvironment(this.environment);
}
@Test
@ -123,7 +117,7 @@ public class HealthMvcEndpointTests {
public void customMappingWithRelaxedName() {
given(this.endpoint.invoke())
.willReturn(new Health.Builder().outOfService().build());
this.mvc.setStatusMapping(Collections.singletonMap("out-of-service",
this.mvc.setStatusMapping(Collections.singletonMap("out-OF-serVice",
HttpStatus.INTERNAL_SERVER_ERROR));
Object result = this.mvc.invoke(this.request, null);
assertThat(result instanceof ResponseEntity).isTrue();
@ -165,7 +159,7 @@ public class HealthMvcEndpointTests {
@Test
public void rightAuthorityPresentShouldExposeDetails() throws Exception {
this.environment.getPropertySources().addLast(SECURITY_ROLES);
this.mvc = new HealthMvcEndpoint(this.endpoint, true, SECURITY_ROLES);
Authentication principal = mock(Authentication.class);
Set<SimpleGrantedAuthority> authorities = Collections
.singleton(new SimpleGrantedAuthority("HERO"));
@ -180,7 +174,7 @@ public class HealthMvcEndpointTests {
@Test
public void customRolePresentShouldExposeDetails() {
this.environment.getPropertySources().addLast(SECURITY_ROLES);
this.mvc = new HealthMvcEndpoint(this.endpoint, true, SECURITY_ROLES);
given(this.endpoint.invoke())
.willReturn(new Health.Builder().up().withDetail("foo", "bar").build());
Object result = this.mvc.invoke(this.hero, null);
@ -191,7 +185,7 @@ public class HealthMvcEndpointTests {
@Test
public void customRoleShouldNotExposeDetailsForDefaultRole() {
this.environment.getPropertySources().addLast(SECURITY_ROLES);
this.mvc = new HealthMvcEndpoint(this.endpoint, true, SECURITY_ROLES);
given(this.endpoint.invoke())
.willReturn(new Health.Builder().up().withDetail("foo", "bar").build());
Object result = this.mvc.invoke(this.defaultUser, null);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -16,11 +16,16 @@
package org.springframework.boot.actuate.info;
import java.util.Collections;
import java.util.Map;
import org.junit.Test;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.env.SystemEnvironmentPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@ -50,6 +55,16 @@ public class EnvironmentInfoContributorTests {
assertThat(actual.getDetails().size()).isEqualTo(0);
}
@Test
@SuppressWarnings("unchecked")
public void propertiesFromEnvironmentShouldBindCorrectly() throws Exception {
MutablePropertySources propertySources = this.environment.getPropertySources();
propertySources.addFirst(new SystemEnvironmentPropertySource("system",
Collections.singletonMap("INFO_ENVIRONMENT_FOO", "green")));
Info actual = contributeFrom(this.environment);
assertThat(actual.get("environment", Map.class)).containsEntry("foo", "green");
}
private static Info contributeFrom(ConfigurableEnvironment environment) {
EnvironmentInfoContributor contributor = new EnvironmentInfoContributor(
environment);

View File

@ -20,10 +20,8 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@ -37,7 +35,7 @@ import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.DeferredImportSelector;
@ -52,7 +50,6 @@ import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
* {@link DeferredImportSelector} to handle {@link EnableAutoConfiguration
@ -211,28 +208,14 @@ public class AutoConfigurationImportSelector
}
private List<String> getExcludeAutoConfigurationsProperty() {
String name = "spring.autoconfigure.exclude";
if (getEnvironment() instanceof ConfigurableEnvironment) {
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
this.environment, "spring.autoconfigure.");
Map<String, Object> properties = resolver.getSubProperties("exclude");
if (properties.isEmpty()) {
return Collections.emptyList();
Binder binder = Binder.get(getEnvironment());
return binder.bind(name, String[].class).map(Arrays::asList)
.orElse(Collections.emptyList());
}
List<String> excludes = new ArrayList<>();
for (Map.Entry<String, Object> entry : properties.entrySet()) {
String name = entry.getKey();
Object value = entry.getValue();
if (name.isEmpty() || name.startsWith("[") && value != null) {
excludes.addAll(new HashSet<>(Arrays.asList(StringUtils
.tokenizeToStringArray(String.valueOf(value), ","))));
}
}
return excludes;
}
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(getEnvironment(),
"spring.autoconfigure.");
String[] exclude = resolver.getProperty("exclude", String[].class);
return (Arrays.asList(exclude == null ? new String[0] : exclude));
String[] excludes = getEnvironment().getProperty(name, String[].class);
return (excludes == null ? Collections.emptyList() : Arrays.asList(excludes));
}
private List<String> sort(List<String> configurations,

View File

@ -19,8 +19,11 @@ package org.springframework.boot.autoconfigure.cache;
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.properties.bind.BindException;
import org.springframework.boot.context.properties.bind.BindResult;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
@ -30,6 +33,7 @@ import org.springframework.core.type.ClassMetadata;
*
* @author Stephane Nicoll
* @author Phillip Webb
* @author Madhura Bhave
* @since 1.3.0
*/
class CacheCondition extends SpringBootCondition {
@ -43,18 +47,23 @@ class CacheCondition extends SpringBootCondition {
}
ConditionMessage.Builder message = ConditionMessage.forCondition("Cache",
sourceClass);
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
context.getEnvironment(), "spring.cache.");
if (!resolver.containsProperty("type")) {
Environment environment = context.getEnvironment();
try {
BindResult<CacheType> specified = Binder.get(environment)
.bind("spring.cache.type", CacheType.class);
if (!specified.isBound()) {
return ConditionOutcome.match(message.because("automatic cache type"));
}
CacheType cacheType = CacheConfigurations
CacheType required = CacheConfigurations
.getType(((AnnotationMetadata) metadata).getClassName());
String value = resolver.getProperty("type").replace('-', '_').toUpperCase();
if (value.equals(cacheType.name())) {
return ConditionOutcome.match(message.because(value + " cache type"));
if (specified.get() == required) {
return ConditionOutcome
.match(message.because(specified.get() + " cache type"));
}
return ConditionOutcome.noMatch(message.because(value + " cache type"));
}
catch (BindException ex) {
}
return ConditionOutcome.noMatch(message.because("unknown cache type"));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -35,6 +35,7 @@ import org.springframework.core.io.Resource;
*
* @author Eddú Meléndez
* @author Stephane Nicoll
* @author Madhura Bhave
* @since 1.3.0
*/
@Configuration
@ -78,7 +79,7 @@ class EhCacheCacheConfiguration {
static class ConfigAvailableCondition extends ResourceCondition {
ConfigAvailableCondition() {
super("EhCache", "spring.cache.ehcache", "config", "classpath:/ehcache.xml");
super("EhCache", "spring.cache.ehcache.config", "classpath:/ehcache.xml");
}
}

View File

@ -34,7 +34,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.cache.jcache.JCacheCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ConditionContext;
@ -53,6 +52,7 @@ import org.springframework.util.StringUtils;
* Cache configuration for JSR-107 compliant providers.
*
* @author Stephane Nicoll
* @author Madhura Bhave
* @since 1.3.0
*/
@Configuration
@ -187,9 +187,8 @@ class JCacheCacheConfiguration {
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
ConditionMessage.Builder message = ConditionMessage.forCondition("JCache");
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
context.getEnvironment(), "spring.cache.jcache.");
if (resolver.containsProperty("provider")) {
String providerProperty = "spring.cache.jcache.provider";
if (context.getEnvironment().containsProperty(providerProperty)) {
return ConditionOutcome
.match(message.because("JCache provider specified"));
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -122,10 +122,4 @@ public @interface ConditionalOnProperty {
*/
boolean matchIfMissing() default false;
/**
* If relaxed names should be checked. Defaults to {@code true}.
* @return if relaxed names are used
*/
boolean relaxedNames() default true;
}

View File

@ -23,7 +23,6 @@ import java.util.Map;
import java.util.Map.Entry;
import org.springframework.boot.autoconfigure.condition.ConditionMessage.Style;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.Ordered;
@ -121,8 +120,6 @@ class OnPropertyCondition extends SpringBootCondition {
private final String[] names;
private final boolean relaxedNames;
private final boolean matchIfMissing;
Spec(AnnotationAttributes annotationAttributes) {
@ -133,7 +130,6 @@ class OnPropertyCondition extends SpringBootCondition {
this.prefix = prefix;
this.havingValue = annotationAttributes.getString("havingValue");
this.names = getNames(annotationAttributes);
this.relaxedNames = annotationAttributes.getBoolean("relaxedNames");
this.matchIfMissing = annotationAttributes.getBoolean("matchIfMissing");
}
@ -149,11 +145,8 @@ class OnPropertyCondition extends SpringBootCondition {
private void collectProperties(PropertyResolver resolver, List<String> missing,
List<String> nonMatching) {
if (this.relaxedNames) {
resolver = new RelaxedPropertyResolver(resolver, this.prefix);
}
for (String name : this.names) {
String key = (this.relaxedNames ? name : this.prefix + name);
String key = this.prefix + name;
if (resolver.containsProperty(key)) {
if (!isMatch(resolver.getProperty(key), this.havingValue)) {
nonMatching.add(name);

View File

@ -22,7 +22,6 @@ import java.util.List;
import org.springframework.boot.autoconfigure.condition.ConditionMessage.Builder;
import org.springframework.boot.autoconfigure.condition.ConditionMessage.Style;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotatedTypeMetadata;
@ -33,42 +32,38 @@ import org.springframework.core.type.AnnotatedTypeMetadata;
*
* @author Stephane Nicoll
* @author Phillip Webb
* @author Madhura Bhave
* @since 1.3.0
*/
public abstract class ResourceCondition extends SpringBootCondition {
private final String name;
private final String prefix;
private final String propertyName;
private final String property;
private final String[] resourceLocations;
/**
* Create a new condition.
* @param name the name of the component
* @param prefix the prefix of the configuration key
* @param propertyName the name of the configuration key
* @param property the configuration property
* @param resourceLocations default location(s) where the configuration file can be
* found if the configuration key is not specified
* @since 2.0.0
*/
protected ResourceCondition(String name, String prefix, String propertyName,
protected ResourceCondition(String name, String property,
String... resourceLocations) {
this.name = name;
this.prefix = (prefix.endsWith(".") ? prefix : prefix + ".");
this.propertyName = propertyName;
this.property = property;
this.resourceLocations = resourceLocations;
}
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
context.getEnvironment(), this.prefix);
if (resolver.containsProperty(this.propertyName)) {
return ConditionOutcome.match(startConditionMessage()
.foundExactly("property " + this.prefix + this.propertyName));
if (context.getEnvironment().containsProperty(this.property)) {
return ConditionOutcome.match(
startConditionMessage().foundExactly("property " + this.property));
}
return getResourceOutcome(context, metadata);
}

View File

@ -16,76 +16,42 @@
package org.springframework.boot.autoconfigure.couchbase;
import java.util.AbstractMap;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.boot.bind.PropertySourcesPropertyValues;
import org.springframework.boot.bind.RelaxedDataBinder;
import org.springframework.boot.bind.RelaxedNames;
import org.springframework.boot.context.properties.bind.BindResult;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertySources;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.validation.DataBinder;
/**
* Condition to determine if {@code spring.couchbase.bootstrap-hosts} is specified.
*
* @author Stephane Nicoll
* @author Madhura Bhave
*/
class OnBootstrapHostsCondition extends SpringBootCondition {
private static final Bindable<List<String>> STRING_LIST = Bindable
.listOf(String.class);
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
Environment environment = context.getEnvironment();
PropertyResolver resolver = new PropertyResolver(
((ConfigurableEnvironment) environment).getPropertySources(),
"spring.couchbase");
Map.Entry<String, Object> entry = resolver.resolveProperty("bootstrap-hosts");
if (entry != null) {
String name = "spring.couchbase.bootstrap-hosts";
BindResult<?> property = Binder.get(context.getEnvironment()).bind(name,
STRING_LIST);
if (property.isBound()) {
return ConditionOutcome.match(ConditionMessage
.forCondition(OnBootstrapHostsCondition.class.getName())
.found("property").items("spring.couchbase.bootstrap-hosts"));
.found("property").items(name));
}
return ConditionOutcome.noMatch(ConditionMessage
.forCondition(OnBootstrapHostsCondition.class.getName())
.didNotFind("property").items("spring.couchbase.bootstrap-hosts"));
}
private static class PropertyResolver {
private final String prefix;
private final Map<String, Object> content;
PropertyResolver(PropertySources propertySources, String prefix) {
this.prefix = prefix;
this.content = new HashMap<>();
DataBinder binder = new RelaxedDataBinder(this.content, this.prefix);
binder.bind(new PropertySourcesPropertyValues(propertySources));
}
Map.Entry<String, Object> resolveProperty(String name) {
RelaxedNames prefixes = new RelaxedNames(this.prefix);
RelaxedNames keys = new RelaxedNames(name);
for (String prefix : prefixes) {
for (String relaxedKey : keys) {
String key = prefix + relaxedKey;
if (this.content.containsKey(relaxedKey)) {
return new AbstractMap.SimpleEntry<>(key,
this.content.get(relaxedKey));
}
}
}
return null;
}
return ConditionOutcome.noMatch(
ConditionMessage.forCondition(OnBootstrapHostsCondition.class.getName())
.didNotFind("property").items(name));
}
}

View File

@ -20,7 +20,6 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
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.bind.RelaxedPropertyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
@ -31,6 +30,7 @@ import org.springframework.dao.annotation.PersistenceExceptionTranslationPostPro
*
* @author Andy Wilkinson
* @author Stephane Nicoll
* @author Madhura Bhave
* @since 1.2.0
*/
@ConditionalOnClass(PersistenceExceptionTranslationPostProcessor.class)
@ -42,15 +42,10 @@ public class PersistenceExceptionTranslationAutoConfiguration {
public static PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor(
Environment environment) {
PersistenceExceptionTranslationPostProcessor postProcessor = new PersistenceExceptionTranslationPostProcessor();
postProcessor.setProxyTargetClass(determineProxyTargetClass(environment));
boolean proxyTargetClass = environment.getProperty(
"spring.aop.proxy-target-class", Boolean.class, Boolean.TRUE);
postProcessor.setProxyTargetClass(proxyTargetClass);
return postProcessor;
}
private static boolean determineProxyTargetClass(Environment environment) {
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(environment,
"spring.aop.");
Boolean value = resolver.getProperty("proxyTargetClass", Boolean.class);
return (value != null ? value : true);
}
}

View File

@ -30,12 +30,11 @@ import org.springframework.boot.autoconfigure.cassandra.CassandraProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.domain.EntityScanPackages;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertyResolver;
import org.springframework.data.cassandra.config.CassandraEntityClassScanner;
import org.springframework.data.cassandra.config.CassandraSessionFactoryBean;
import org.springframework.data.cassandra.config.SchemaAction;
@ -54,6 +53,7 @@ import org.springframework.util.StringUtils;
* @author Julien Dubois
* @author Eddú Meléndez
* @author Mark Paluch
* @author Madhura Bhave
* @since 1.3.0
*/
@Configuration
@ -68,15 +68,14 @@ public class CassandraDataAutoConfiguration {
private final Cluster cluster;
private final PropertyResolver propertyResolver;
private final Environment environment;
public CassandraDataAutoConfiguration(BeanFactory beanFactory,
CassandraProperties properties, Cluster cluster, Environment environment) {
this.beanFactory = beanFactory;
this.properties = properties;
this.cluster = cluster;
this.propertyResolver = new RelaxedPropertyResolver(environment,
"spring.data.cassandra.");
this.environment = environment;
}
@Bean
@ -112,10 +111,9 @@ public class CassandraDataAutoConfiguration {
session.setCluster(this.cluster);
session.setConverter(converter);
session.setKeyspaceName(this.properties.getKeyspaceName());
String name = this.propertyResolver.getProperty("schemaAction",
SchemaAction.NONE.name());
SchemaAction schemaAction = SchemaAction.valueOf(name.toUpperCase());
session.setSchemaAction(schemaAction);
Binder binder = Binder.get(this.environment);
binder.bind("spring.data.cassandra.schema-action", SchemaAction.class)
.ifBound(session::setSchemaAction);
return session;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -38,6 +38,7 @@ import org.springframework.core.io.Resource;
* configuration file is found in the environment.
*
* @author Stephane Nicoll
* @author Madhura Bhave
* @since 1.3.0
* @see HazelcastConfigResourceCondition
*/
@ -87,7 +88,7 @@ public class HazelcastAutoConfiguration {
static class ConfigAvailableCondition extends HazelcastConfigResourceCondition {
ConfigAvailableCondition() {
super("spring.hazelcast", "config");
super("spring.hazelcast.config");
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -28,15 +28,15 @@ import org.springframework.core.type.AnnotatedTypeMetadata;
* property referring to the resource to use has been set.
*
* @author Stephane Nicoll
* @author Madhura Bhave
* @since 1.3.0
*/
public abstract class HazelcastConfigResourceCondition extends ResourceCondition {
static final String CONFIG_SYSTEM_PROPERTY = "hazelcast.config";
protected HazelcastConfigResourceCondition(String prefix, String propertyName) {
super("Hazelcast", prefix, propertyName, "file:./hazelcast.xml",
"classpath:/hazelcast.xml");
protected HazelcastConfigResourceCondition(String property) {
super("Hazelcast", property, "file:./hazelcast.xml", "classpath:/hazelcast.xml");
}
@Override

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -25,7 +25,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnResource;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.info.BuildProperties;
import org.springframework.boot.info.GitProperties;
@ -33,7 +32,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.PropertyResolver;
import org.springframework.core.env.Environment;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
@ -44,6 +43,7 @@ import org.springframework.core.type.AnnotatedTypeMetadata;
* {@link EnableAutoConfiguration Auto-configuration} for various project information.
*
* @author Stephane Nicoll
* @author Madhura Bhave
* @since 1.4.0
*/
@Configuration
@ -91,19 +91,12 @@ public class ProjectInfoAutoConfiguration {
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
ResourceLoader loader = context.getResourceLoader();
if (loader == null) {
loader = this.defaultResourceLoader;
}
PropertyResolver propertyResolver = context.getEnvironment();
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
propertyResolver, "spring.info.git.");
String location = resolver.getProperty("location");
loader = (loader != null ? loader : this.defaultResourceLoader);
Environment environment = context.getEnvironment();
String location = environment.getProperty("spring.info.git.location");
if (location == null) {
resolver = new RelaxedPropertyResolver(propertyResolver, "spring.git.");
location = resolver.getProperty("properties");
if (location == null) {
location = "classpath:git.properties";
}
location = environment.getProperty("spring.git.properties");
location = (location != null ? location : "classpath:git.properties");
}
ConditionMessage.Builder message = ConditionMessage
.forCondition("GitResource");

View File

@ -29,7 +29,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
@ -54,6 +53,7 @@ import org.springframework.util.StringUtils;
* @author Dave Syer
* @author Stephane Nicoll
* @author Vedran Pavic
* @author Madhura Bhave
* @since 1.1.0
*/
@Configuration
@ -83,7 +83,7 @@ public class IntegrationAutoConfiguration {
private BeanFactory beanFactory;
private RelaxedPropertyResolver propertyResolver;
private Environment environment;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
@ -92,21 +92,20 @@ public class IntegrationAutoConfiguration {
@Override
public void setEnvironment(Environment environment) {
this.propertyResolver = new RelaxedPropertyResolver(environment,
"spring.jmx.");
this.environment = environment;
}
@Bean
public IntegrationMBeanExporter integrationMbeanExporter() {
IntegrationMBeanExporter exporter = new IntegrationMBeanExporter();
String defaultDomain = this.propertyResolver.getProperty("default-domain");
String defaultDomain = this.environment
.getProperty("spring.jmx.default-domain");
if (StringUtils.hasLength(defaultDomain)) {
exporter.setDefaultDomain(defaultDomain);
}
String server = this.propertyResolver.getProperty("server", "mbeanServer");
if (StringUtils.hasLength(server)) {
exporter.setServer(this.beanFactory.getBean(server, MBeanServer.class));
}
String serverBean = this.environment.getProperty("spring.jmx.server",
"mbeanServer");
exporter.setServer(this.beanFactory.getBean(serverBean, MBeanServer.class));
return exporter;
}

View File

@ -22,8 +22,12 @@ import java.util.Map;
import javax.sql.DataSource;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.boot.bind.RelaxedDataBinder;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
import org.springframework.boot.context.properties.source.ConfigurationPropertyNameAliases;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.context.properties.source.MapConfigurationPropertySource;
import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.util.ClassUtils;
@ -37,6 +41,7 @@ import org.springframework.util.ClassUtils;
* {@code @ConfigurationProperties}.
*
* @author Dave Syer
* @author Madhura Bhave
* @since 1.1.0
*/
public class DataSourceBuilder {
@ -82,9 +87,13 @@ public class DataSourceBuilder {
}
private void bind(DataSource result) {
MutablePropertyValues properties = new MutablePropertyValues(this.properties);
new RelaxedDataBinder(result).withAlias("url", "jdbcUrl")
.withAlias("username", "user").bind(properties);
ConfigurationPropertySource source = new MapConfigurationPropertySource(
this.properties);
ConfigurationPropertyNameAliases aliases = new ConfigurationPropertyNameAliases();
aliases.addAlaises("url", "jdbc-url");
aliases.addAlaises("username", "user");
Binder binder = new Binder(source.withAliases(aliases));
binder.bind(ConfigurationPropertyName.EMPTY, Bindable.ofInstance(result));
}
public DataSourceBuilder type(Class<? extends DataSource> type) {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -21,7 +21,6 @@ import javax.sql.XADataSource;
import javax.transaction.TransactionManager;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
@ -29,8 +28,13 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.bind.RelaxedDataBinder;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
import org.springframework.boot.context.properties.source.ConfigurationPropertyNameAliases;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.context.properties.source.MapConfigurationPropertySource;
import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.boot.jta.XADataSourceWrapper;
import org.springframework.context.annotation.Bean;
@ -44,6 +48,7 @@ import org.springframework.util.StringUtils;
*
* @author Phillip Webb
* @author Josh Long
* @author Madhura Bhave
* @since 1.2.0
*/
@AutoConfigureBefore(DataSourceAutoConfiguration.class)
@ -105,13 +110,22 @@ public class XADataSourceAutoConfiguration implements BeanClassLoaderAware {
}
}
private void bindXaProperties(XADataSource target, DataSourceProperties properties) {
MutablePropertyValues values = new MutablePropertyValues();
values.add("user", this.properties.determineUsername());
values.add("password", this.properties.determinePassword());
values.add("url", this.properties.determineUrl());
values.addPropertyValues(properties.getXa().getProperties());
new RelaxedDataBinder(target).withAlias("user", "username").bind(values);
private void bindXaProperties(XADataSource target,
DataSourceProperties dataSourceProperties) {
Binder binder = new Binder(getBinderSource(dataSourceProperties));
binder.bind(ConfigurationPropertyName.EMPTY, Bindable.ofInstance(target));
}
private ConfigurationPropertySource getBinderSource(
DataSourceProperties dataSourceProperties) {
MapConfigurationPropertySource source = new MapConfigurationPropertySource();
source.put("user", this.properties.determineUsername());
source.put("password", this.properties.determinePassword());
source.put("url", this.properties.determineUrl());
source.putAll(dataSourceProperties.getXa().getProperties());
ConfigurationPropertyNameAliases aliases = new ConfigurationPropertyNameAliases();
aliases.addAlaises("user", "username");
return source.withAliases(aliases);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2015 the original author or authors.
* Copyright 2012-2017 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.
@ -26,7 +26,6 @@ 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.autoconfigure.condition.SearchStrategy;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -49,19 +48,20 @@ import org.springframework.util.StringUtils;
* To disable auto export of annotation beans set {@code spring.jmx.enabled: false}.
*
* @author Christian Dupuis
* @author Madhura Bhave
*/
@Configuration
@ConditionalOnClass({ MBeanExporter.class })
@ConditionalOnProperty(prefix = "spring.jmx", name = "enabled", havingValue = "true", matchIfMissing = true)
public class JmxAutoConfiguration implements EnvironmentAware, BeanFactoryAware {
private RelaxedPropertyResolver propertyResolver;
private Environment environment;
private BeanFactory beanFactory;
@Override
public void setEnvironment(Environment environment) {
this.propertyResolver = new RelaxedPropertyResolver(environment, "spring.jmx.");
this.environment = environment;
}
@Override
@ -76,9 +76,10 @@ public class JmxAutoConfiguration implements EnvironmentAware, BeanFactoryAware
AnnotationMBeanExporter exporter = new AnnotationMBeanExporter();
exporter.setRegistrationPolicy(RegistrationPolicy.FAIL_ON_EXISTING);
exporter.setNamingStrategy(namingStrategy);
String server = this.propertyResolver.getProperty("server", "mbeanServer");
if (StringUtils.hasLength(server)) {
exporter.setServer(this.beanFactory.getBean(server, MBeanServer.class));
String serverBean = this.environment.getProperty("spring.jmx.server",
"mbeanServer");
if (StringUtils.hasLength(serverBean)) {
exporter.setServer(this.beanFactory.getBean(serverBean, MBeanServer.class));
}
return exporter;
}
@ -88,7 +89,7 @@ public class JmxAutoConfiguration implements EnvironmentAware, BeanFactoryAware
public ParentAwareNamingStrategy objectNamingStrategy() {
ParentAwareNamingStrategy namingStrategy = new ParentAwareNamingStrategy(
new AnnotationJmxAttributeSource());
String defaultDomain = this.propertyResolver.getProperty("default-domain");
String defaultDomain = this.environment.getProperty("spring.jmx.default-domain");
if (StringUtils.hasLength(defaultDomain)) {
namingStrategy.setDefaultDomain(defaultDomain);
}
@ -106,7 +107,6 @@ public class JmxAutoConfiguration implements EnvironmentAware, BeanFactoryAware
factory.setLocateExistingServerIfPossible(true);
factory.afterPropertiesSet();
return factory.getObject();
}
}

View File

@ -16,16 +16,10 @@
package org.springframework.boot.autoconfigure.mustache;
import java.util.HashMap;
import java.util.Map;
import com.samskivert.mustache.DefaultCollector;
import com.samskivert.mustache.Mustache.Collector;
import com.samskivert.mustache.Mustache.VariableFetcher;
import org.springframework.boot.bind.PropertySourcesPropertyValues;
import org.springframework.boot.bind.RelaxedDataBinder;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
@ -34,6 +28,7 @@ import org.springframework.core.env.Environment;
* Mustache {@link Collector} to expose properties from the Spring {@link Environment}.
*
* @author Dave Syer
* @author Madhura Bhave
* @since 1.2.2
*/
public class MustacheEnvironmentCollector extends DefaultCollector
@ -41,19 +36,11 @@ public class MustacheEnvironmentCollector extends DefaultCollector
private ConfigurableEnvironment environment;
private Map<String, Object> target;
private RelaxedPropertyResolver propertyResolver;
private final VariableFetcher propertyFetcher = new PropertyVariableFetcher();
@Override
public void setEnvironment(Environment environment) {
this.environment = (ConfigurableEnvironment) environment;
this.target = new HashMap<>();
new RelaxedDataBinder(this.target).bind(
new PropertySourcesPropertyValues(this.environment.getPropertySources()));
this.propertyResolver = new RelaxedPropertyResolver(environment);
}
@Override
@ -62,7 +49,7 @@ public class MustacheEnvironmentCollector extends DefaultCollector
if (fetcher != null) {
return fetcher;
}
if (this.propertyResolver.containsProperty(name)) {
if (this.environment.containsProperty(name)) {
return this.propertyFetcher;
}
return null;
@ -72,7 +59,7 @@ public class MustacheEnvironmentCollector extends DefaultCollector
@Override
public Object get(Object ctx, String name) throws Exception {
return MustacheEnvironmentCollector.this.propertyResolver.getProperty(name);
return MustacheEnvironmentCollector.this.environment.getProperty(name);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2015 the original author or authors.
* Copyright 2012-2017 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.
@ -17,9 +17,7 @@
package org.springframework.boot.autoconfigure.mustache;
import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertyResolver;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.ClassUtils;
@ -28,6 +26,7 @@ import org.springframework.util.ClassUtils;
* Mustache view templates.
*
* @author Dave Syer
* @author Madhura Bhave
* @since 1.2.2
*/
public class MustacheTemplateAvailabilityProvider
@ -37,11 +36,9 @@ public class MustacheTemplateAvailabilityProvider
public boolean isTemplateAvailable(String view, Environment environment,
ClassLoader classLoader, ResourceLoader resourceLoader) {
if (ClassUtils.isPresent("com.samskivert.mustache.Template", classLoader)) {
PropertyResolver resolver = new RelaxedPropertyResolver(environment,
"spring.mustache.");
String prefix = resolver.getProperty("prefix",
String prefix = environment.getProperty("spring.mustache.prefix",
MustacheProperties.DEFAULT_PREFIX);
String suffix = resolver.getProperty("suffix",
String suffix = environment.getProperty("spring.mustache.suffix",
MustacheProperties.DEFAULT_SUFFIX);
return resourceLoader.getResource(prefix + view + suffix).exists();
}

View File

@ -34,6 +34,7 @@ import org.springframework.util.StringUtils;
* @author Andy Wilkinson
* @author Stephane Nicoll
* @author Eddú Meléndez
* @author Madhura Bhave
* @since 1.1.0
*/
@ConfigurationProperties(prefix = "spring.jpa")
@ -169,11 +170,11 @@ public class JpaProperties {
this.ddlAuto = ddlAuto;
}
public boolean isUseNewIdGeneratorMappings() {
public Boolean isUseNewIdGeneratorMappings() {
return this.useNewIdGeneratorMappings;
}
public void setUseNewIdGeneratorMappings(boolean useNewIdGeneratorMappings) {
public void setUseNewIdGeneratorMappings(Boolean useNewIdGeneratorMappings) {
this.useNewIdGeneratorMappings = useNewIdGeneratorMappings;
}

View File

@ -31,7 +31,6 @@ import org.springframework.boot.autoconfigure.condition.NoneNestedConditions;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2RestOperationsConfiguration.OAuth2ClientIdCondition;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
@ -42,7 +41,6 @@ import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.core.env.PropertyResolver;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
@ -62,6 +60,7 @@ import org.springframework.util.StringUtils;
* Configuration for OAuth2 Single Sign On REST operations.
*
* @author Dave Syer
* @author Madhura Bhave
* @since 1.3.0
*/
@Configuration
@ -159,9 +158,8 @@ public class OAuth2RestOperationsConfiguration {
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
PropertyResolver resolver = new RelaxedPropertyResolver(
context.getEnvironment(), "security.oauth2.client.");
String clientId = resolver.getProperty("client-id");
String clientId = context.getEnvironment()
.getProperty("security.oauth2.client.client-id");
ConditionMessage.Builder message = ConditionMessage
.forCondition("OAuth Client ID");
if (StringUtils.hasLength(clientId)) {

View File

@ -16,6 +16,8 @@
package org.springframework.boot.autoconfigure.security.oauth2.resource;
import java.util.Map;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
@ -28,7 +30,8 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplicat
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.boot.autoconfigure.security.oauth2.resource.OAuth2ResourceServerConfiguration.ResourceServerCondition;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
@ -39,6 +42,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ConfigurationCondition;
import org.springframework.context.annotation.Import;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.core.type.StandardAnnotationMetadata;
@ -58,6 +62,7 @@ import org.springframework.util.StringUtils;
*
* @author Greg Turnquist
* @author Dave Syer
* @author Madhura Bhave
* @since 1.3.0
*/
@Configuration
@ -150,6 +155,9 @@ public class OAuth2ResourceServerConfiguration {
protected static class ResourceServerCondition extends SpringBootCondition
implements ConfigurationCondition {
private static final Bindable<Map<String, Object>> STRING_OBJECT_MAP = Bindable
.mapOf(String.class, Object.class);
private static final String AUTHORIZATION_ANNOTATION = "org.springframework."
+ "security.oauth2.config.annotation.web.configuration."
+ "AuthorizationServerEndpointsConfiguration";
@ -165,24 +173,28 @@ public class OAuth2ResourceServerConfiguration {
ConditionMessage.Builder message = ConditionMessage
.forCondition("OAuth ResourceServer Condition");
Environment environment = context.getEnvironment();
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(environment,
"security.oauth2.resource.");
if (!(environment instanceof ConfigurableEnvironment)) {
return ConditionOutcome
.noMatch(message.didNotFind("A ConfigurableEnvironment").atAll());
}
if (hasOAuthClientId(environment)) {
return ConditionOutcome.match(message.foundExactly("client-id property"));
}
if (!resolver.getSubProperties("jwt").isEmpty()) {
Binder binder = Binder.get(environment);
String prefix = "security.oauth2.resource.";
if (binder.bind(prefix + "jwt", STRING_OBJECT_MAP).isBound()) {
return ConditionOutcome
.match(message.foundExactly("JWT resource configuration"));
}
if (!resolver.getSubProperties("jwk").isEmpty()) {
if (binder.bind(prefix + "jwk", STRING_OBJECT_MAP).isBound()) {
return ConditionOutcome
.match(message.foundExactly("JWK resource configuration"));
}
if (StringUtils.hasText(resolver.getProperty("user-info-uri"))) {
if (StringUtils.hasText(environment.getProperty(prefix + "user-info-uri"))) {
return ConditionOutcome
.match(message.foundExactly("user-info-uri property"));
}
if (StringUtils.hasText(resolver.getProperty("token-info-uri"))) {
if (StringUtils.hasText(environment.getProperty(prefix + "token-info-uri"))) {
return ConditionOutcome
.match(message.foundExactly("token-info-uri property"));
}
@ -194,14 +206,13 @@ public class OAuth2ResourceServerConfiguration {
}
}
return ConditionOutcome.noMatch(
message.didNotFind("client id, JWT resource or authorization server")
message.didNotFind("client ID, JWT resource or authorization server")
.atAll());
}
private boolean hasOAuthClientId(Environment environment) {
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(environment,
"security.oauth2.client.");
return StringUtils.hasLength(resolver.getProperty("client-id", ""));
return StringUtils.hasLength(
environment.getProperty("security.oauth2.client.client-id"));
}
}

View File

@ -30,7 +30,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.NoneNestedConditions;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
@ -319,17 +318,17 @@ public class ResourceServerTokenServicesConfiguration {
ConditionMessage.Builder message = ConditionMessage
.forCondition("OAuth TokenInfo Condition");
Environment environment = context.getEnvironment();
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(environment,
"security.oauth2.resource.");
Boolean preferTokenInfo = resolver.getProperty("prefer-token-info",
Boolean.class);
Boolean preferTokenInfo = environment.getProperty(
"security.oauth2.resource.prefer-token-info", Boolean.class);
if (preferTokenInfo == null) {
preferTokenInfo = environment
.resolvePlaceholders("${OAUTH2_RESOURCE_PREFERTOKENINFO:true}")
.equals("true");
}
String tokenInfoUri = resolver.getProperty("token-info-uri");
String userInfoUri = resolver.getProperty("user-info-uri");
String tokenInfoUri = environment
.getProperty("security.oauth2.resource.token-info-uri");
String userInfoUri = environment
.getProperty("security.oauth2.resource.user-info-uri");
if (!StringUtils.hasLength(userInfoUri)
&& !StringUtils.hasLength(tokenInfoUri)) {
return ConditionOutcome
@ -351,10 +350,11 @@ public class ResourceServerTokenServicesConfiguration {
AnnotatedTypeMetadata metadata) {
ConditionMessage.Builder message = ConditionMessage
.forCondition("OAuth JWT Condition");
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
context.getEnvironment(), "security.oauth2.resource.jwt.");
String keyValue = resolver.getProperty("key-value");
String keyUri = resolver.getProperty("key-uri");
Environment environment = context.getEnvironment();
String keyValue = environment
.getProperty("security.oauth2.resource.jwt.key-value");
String keyUri = environment
.getProperty("security.oauth2.resource.jwt.key-uri");
if (StringUtils.hasText(keyValue) || StringUtils.hasText(keyUri)) {
return ConditionOutcome
.match(message.foundExactly("provided public key"));
@ -372,9 +372,9 @@ public class ResourceServerTokenServicesConfiguration {
AnnotatedTypeMetadata metadata) {
ConditionMessage.Builder message = ConditionMessage
.forCondition("OAuth JWK Condition");
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
context.getEnvironment(), "security.oauth2.resource.jwk.");
String keyUri = resolver.getProperty("key-set-uri");
Environment environment = context.getEnvironment();
String keyUri = environment
.getProperty("security.oauth2.resource.jwk.key-set-uri");
if (StringUtils.hasText(keyUri)) {
return ConditionOutcome
.match(message.foundExactly("provided jwk key set URI"));

View File

@ -19,8 +19,10 @@ package org.springframework.boot.autoconfigure.session;
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.properties.bind.BindException;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.core.type.AnnotationMetadata;
@ -29,6 +31,7 @@ import org.springframework.core.type.AnnotationMetadata;
*
* @author Tommy Ludwig
* @author Stephane Nicoll
* @author Madhura Bhave
*/
class SessionCondition extends SpringBootCondition {
@ -37,21 +40,25 @@ class SessionCondition extends SpringBootCondition {
AnnotatedTypeMetadata metadata) {
ConditionMessage.Builder message = ConditionMessage
.forCondition("Session Condition");
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
context.getEnvironment(), "spring.session.");
StoreType sessionStoreType = SessionStoreMappings
Environment environment = context.getEnvironment();
StoreType required = SessionStoreMappings
.getType(((AnnotationMetadata) metadata).getClassName());
if (!resolver.containsProperty("store-type")) {
if (!environment.containsProperty("spring.session.store-type")) {
return ConditionOutcome.noMatch(
message.didNotFind("spring.session.store-type property").atAll());
}
String value = resolver.getProperty("store-type").replace('-', '_').toUpperCase();
if (value.equals(sessionStoreType.name())) {
return ConditionOutcome.match(message
.found("spring.session.store-type property").items(sessionStoreType));
try {
Binder binder = Binder.get(environment);
return binder.bind("spring.session.store-type", StoreType.class)
.map((t) -> new ConditionOutcome(t == required,
message.found("spring.session.store-type property").items(t)))
.orElse(ConditionOutcome.noMatch(message
.didNotFind("spring.session.store-type property").atAll()));
}
catch (BindException ex) {
return ConditionOutcome.noMatch(
message.found("spring.session.store-type property").items(value));
message.found("invalid spring.session.store-type property").atAll());
}
}
}

View File

@ -18,10 +18,8 @@ package org.springframework.boot.autoconfigure.template;
import java.util.List;
import org.springframework.beans.BeanUtils;
import org.springframework.boot.bind.PropertySourcesPropertyValues;
import org.springframework.boot.bind.RelaxedDataBinder;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.boot.autoconfigure.template.PathBasedTemplateAvailabilityProvider.TemplateAvailabilityProperties;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.ClassUtils;
@ -32,20 +30,20 @@ import org.springframework.util.ClassUtils;
*
* @author Andy Wilkinson
* @author Phillip Webb
* @author Madhura Bhave
* @since 1.4.6
*/
public abstract class PathBasedTemplateAvailabilityProvider
public abstract class PathBasedTemplateAvailabilityProvider<T extends TemplateAvailabilityProperties>
implements TemplateAvailabilityProvider {
private final String className;
private final Class<? extends TemplateAvailabilityProperties> propertiesClass;
private final Class<T> propertiesClass;
private final String propertyPrefix;
public PathBasedTemplateAvailabilityProvider(String className,
Class<? extends TemplateAvailabilityProperties> propertiesClass,
String propertyPrefix) {
Class<T> propertiesClass, String propertyPrefix) {
this.className = className;
this.propertiesClass = propertiesClass;
this.propertyPrefix = propertyPrefix;
@ -55,12 +53,10 @@ public abstract class PathBasedTemplateAvailabilityProvider
public boolean isTemplateAvailable(String view, Environment environment,
ClassLoader classLoader, ResourceLoader resourceLoader) {
if (ClassUtils.isPresent(this.className, classLoader)) {
TemplateAvailabilityProperties properties = BeanUtils
.instantiateClass(this.propertiesClass);
RelaxedDataBinder binder = new RelaxedDataBinder(properties,
this.propertyPrefix);
binder.bind(new PropertySourcesPropertyValues(
((ConfigurableEnvironment) environment).getPropertySources()));
Binder binder = Binder.get(environment);
TemplateAvailabilityProperties properties = binder
.bind(this.propertyPrefix, this.propertiesClass)
.orElseCreate(this.propertiesClass);
return isTemplateAvailable(view, resourceLoader, properties);
}
return false;

View File

@ -23,7 +23,6 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
@ -36,6 +35,7 @@ import org.springframework.util.Assert;
* {@code spring.template.provider.cache} property is set to {@code false}.
*
* @author Phillip Webb
* @author Madhura Bhave
* @since 1.4.0
*/
public class TemplateAvailabilityProviders {
@ -134,10 +134,9 @@ public class TemplateAvailabilityProviders {
Assert.notNull(environment, "Environment must not be null");
Assert.notNull(classLoader, "ClassLoader must not be null");
Assert.notNull(resourceLoader, "ResourceLoader must not be null");
RelaxedPropertyResolver propertyResolver = new RelaxedPropertyResolver(
environment, "spring.template.provider.");
if (!propertyResolver.getProperty("cache", Boolean.class, true)) {
Boolean useCache = environment.getProperty("spring.template.provider.cache",
Boolean.class, true);
if (!useCache) {
return findProvider(view, environment, classLoader, resourceLoader);
}
TemplateAvailabilityProvider provider = this.resolved.get(view);

View File

@ -17,9 +17,7 @@
package org.springframework.boot.autoconfigure.thymeleaf;
import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertyResolver;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.ClassUtils;
@ -28,6 +26,7 @@ import org.springframework.util.ClassUtils;
* Thymeleaf view templates.
*
* @author Andy Wilkinson
* @author Madhura Bhave
* @since 1.1.0
*/
public class ThymeleafTemplateAvailabilityProvider
@ -38,11 +37,9 @@ public class ThymeleafTemplateAvailabilityProvider
ClassLoader classLoader, ResourceLoader resourceLoader) {
if (ClassUtils.isPresent("org.thymeleaf.spring5.SpringTemplateEngine",
classLoader)) {
PropertyResolver resolver = new RelaxedPropertyResolver(environment,
"spring.thymeleaf.");
String prefix = resolver.getProperty("prefix",
String prefix = environment.getProperty("spring.thymeleaf.prefix",
ThymeleafProperties.DEFAULT_PREFIX);
String suffix = resolver.getProperty("suffix",
String suffix = environment.getProperty("spring.thymeleaf.suffix",
ThymeleafProperties.DEFAULT_SUFFIX);
return resourceLoader.getResource(prefix + view + suffix).exists();
}

View File

@ -24,7 +24,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnResource;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@ -36,6 +35,7 @@ import org.springframework.validation.beanvalidation.MethodValidationPostProcess
* infrastructure.
*
* @author Stephane Nicoll
* @author Madhura Bhave
* @since 1.5.0
*/
@Configuration
@ -51,16 +51,11 @@ public class ValidationAutoConfiguration {
public static MethodValidationPostProcessor methodValidationPostProcessor(
Environment environment, Validator validator) {
MethodValidationPostProcessor processor = new MethodValidationPostProcessor();
processor.setProxyTargetClass(determineProxyTargetClass(environment));
boolean proxyTargetClass = environment
.getProperty("spring.aop.proxy-target-class", Boolean.class, true);
processor.setProxyTargetClass(proxyTargetClass);
processor.setValidator(validator);
return processor;
}
private static boolean determineProxyTargetClass(Environment environment) {
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(environment,
"spring.aop.");
Boolean value = resolver.getProperty("proxyTargetClass", Boolean.class);
return (value != null ? value : true);
}
}

View File

@ -19,11 +19,9 @@ package org.springframework.boot.autoconfigure.web;
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertyResolver;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.ClassUtils;
@ -33,6 +31,7 @@ import org.springframework.util.ClassUtils;
*
* @author Stephane Nicoll
* @author Phillip Webb
* @author Madhura Bhave
* @see ConditionalOnEnabledResourceChain
*/
class OnEnabledResourceChainCondition extends SpringBootCondition {
@ -66,9 +65,8 @@ class OnEnabledResourceChainCondition extends SpringBootCondition {
private Boolean getEnabledProperty(ConfigurableEnvironment environment, String key,
Boolean defaultValue) {
PropertyResolver resolver = new RelaxedPropertyResolver(environment,
"spring.resources.chain." + key);
return resolver.getProperty("enabled", Boolean.class, defaultValue);
String name = "spring.resources.chain." + key + "enabled";
return environment.getProperty(name, Boolean.class, defaultValue);
}
}

View File

@ -17,9 +17,7 @@
package org.springframework.boot.autoconfigure.web.servlet;
import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertyResolver;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.ClassUtils;
@ -29,6 +27,7 @@ import org.springframework.util.ClassUtils;
*
* @author Andy Wilkinson
* @author Stephane Nicoll
* @author Madhura Bhave
* @since 1.1.0
*/
public class JspTemplateAvailabilityProvider implements TemplateAvailabilityProvider {
@ -44,11 +43,9 @@ public class JspTemplateAvailabilityProvider implements TemplateAvailabilityProv
}
private String getResourceName(String view, Environment environment) {
PropertyResolver resolver = new RelaxedPropertyResolver(environment,
"spring.mvc.view.");
String prefix = resolver.getProperty("prefix",
String prefix = environment.getProperty("spring.mvc.view.prefix",
WebMvcAutoConfiguration.DEFAULT_PREFIX);
String suffix = resolver.getProperty("suffix",
String suffix = environment.getProperty("spring.mvc.view.suffix",
WebMvcAutoConfiguration.DEFAULT_SUFFIX);
return prefix + view + suffix;
}

View File

@ -145,8 +145,7 @@ public class CacheAutoConfigurationTests {
@Test
public void notSupportedCachingMode() {
this.thrown.expect(BeanCreationException.class);
this.thrown.expectMessage("cache");
this.thrown.expectMessage("foobar");
this.thrown.expectMessage("Failed to bind properties under 'spring.cache.type'");
load(DefaultCacheConfiguration.class, "spring.cache.type=foobar");
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -26,10 +26,14 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.StandardEnvironment;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.containsString;
@ -48,7 +52,9 @@ public class ConditionalOnPropertyTests {
@Rule
public ExpectedException thrown = ExpectedException.none();
private AnnotationConfigApplicationContext context;
private ConfigurableApplicationContext context;
private ConfigurableEnvironment environment = new StandardEnvironment();
@After
public void tearDown() {
@ -98,13 +104,6 @@ public class ConditionalOnPropertyTests {
assertThat(this.context.containsBean("foo")).isTrue();
}
@Test
public void nonRelaxedName() throws Exception {
load(NonRelaxedPropertiesRequiredConfiguration.class,
"theRelaxedProperty=value1");
assertThat(this.context.containsBean("foo")).isFalse();
}
@Test
// Enabled by default
public void enabledIfNotConfiguredOtherwise() {
@ -185,18 +184,6 @@ public class ConditionalOnPropertyTests {
assertThat(this.context.containsBean("foo")).isTrue();
}
@Test
public void strictNameMatch() {
load(StrictNameConfig.class, "simple.my-property:bar");
assertThat(this.context.containsBean("foo")).isTrue();
}
@Test
public void strictNameNoMatch() {
load(StrictNameConfig.class, "simple.myProperty:bar");
assertThat(this.context.containsBean("foo")).isFalse();
}
@Test
public void multiValuesAllSet() {
load(MultiValuesConfig.class, "simple.my-property:bar",
@ -271,10 +258,9 @@ public class ConditionalOnPropertyTests {
}
private void load(Class<?> config, String... environment) {
this.context = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(this.context, environment);
this.context.register(config);
this.context.refresh();
EnvironmentTestUtils.addEnvironment(this.environment, environment);
this.context = new SpringApplicationBuilder(config).environment(this.environment)
.web(WebApplicationType.NONE).run();
}
@Configuration
@ -310,17 +296,6 @@ public class ConditionalOnPropertyTests {
}
@Configuration
@ConditionalOnProperty(name = "the-relaxed-property", relaxedNames = false)
protected static class NonRelaxedPropertiesRequiredConfiguration {
@Bean
public String foo() {
return "foo";
}
}
@Configuration
// i.e ${simple.myProperty:true}
@ConditionalOnProperty(prefix = "simple", name = "my-property", havingValue = "true", matchIfMissing = true)
@ -378,17 +353,6 @@ public class ConditionalOnPropertyTests {
}
@Configuration
@ConditionalOnProperty(prefix = "simple", name = "my-property", havingValue = "bar", relaxedNames = false)
static class StrictNameConfig {
@Bean
public String foo() {
return "foo";
}
}
@Configuration
@ConditionalOnProperty(prefix = "simple", name = { "my-property",
"my-another-property" }, havingValue = "bar")
@ -434,6 +398,7 @@ public class ConditionalOnPropertyTests {
}
@Configuration
@ConditionalOnMyFeature
protected static class MetaAnnotation {
@ -444,6 +409,7 @@ public class ConditionalOnPropertyTests {
}
@Configuration
@ConditionalOnMyFeature
@ConditionalOnProperty(prefix = "my.other.feature", name = "enabled", havingValue = "true", matchIfMissing = false)
protected static class MetaAnnotationAndDirectAnnotation {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -96,7 +96,7 @@ public class ResourceConditionTests {
private static class DefaultLocationResourceCondition extends ResourceCondition {
DefaultLocationResourceCondition() {
super("test", "spring.foo.test.", "config", "classpath:/logging.properties");
super("test", "spring.foo.test.config", "classpath:/logging.properties");
}
}
@ -105,7 +105,7 @@ public class ResourceConditionTests {
extends ResourceCondition {
UnknownDefaultLocationResourceCondition() {
super("test", "spring.foo.test", "config",
super("test", "spring.foo.test.config",
"classpath:/this-file-does-not-exist.xml");
}

View File

@ -67,7 +67,7 @@ public class PersistenceExceptionTranslationAutoConfigurationTests {
public void exceptionTranslationPostProcessorCanBeConfiguredToUseJdkProxy() {
this.context = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(this.context,
"spring.aop.proxyTargetClass=false");
"spring.aop.proxy-target-class=false");
this.context.register(PersistenceExceptionTranslationAutoConfiguration.class);
this.context.refresh();
Map<String, PersistenceExceptionTranslationPostProcessor> beans = this.context

View File

@ -81,7 +81,7 @@ public class H2ConsoleAutoConfigurationTests {
@Test
public void customPathMustBeginWithASlash() {
this.thrown.expect(BeanCreationException.class);
this.thrown.expectMessage("Path must start with /");
this.thrown.expectMessage("Failed to bind properties under 'spring.h2.console'");
this.context.register(H2ConsoleAutoConfiguration.class);
EnvironmentTestUtils.addEnvironment(this.context,
"spring.h2.console.enabled:true", "spring.h2.console.path:custom");

View File

@ -31,6 +31,7 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerA
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@ -99,11 +100,12 @@ public class IntegrationAutoConfigurationTests {
load();
AnnotationConfigApplicationContext parent = this.context;
this.context = new AnnotationConfigApplicationContext();
ConfigurationPropertySources.attach(this.context.getEnvironment());
this.context.setParent(parent);
this.context.register(JmxAutoConfiguration.class,
IntegrationAutoConfiguration.class);
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context,
"SPRING_JMX_DEFAULT_DOMAIN=org.foo");
"spring.jmx.default_domain=org.foo");
this.context.refresh();
assertThat(this.context.getBean(HeaderChannelRegistry.class)).isNotNull();
}
@ -129,7 +131,7 @@ public class IntegrationAutoConfigurationTests {
@Test
public void customizeJmxDomain() {
load("SPRING_JMX_DEFAULT_DOMAIN=org.foo");
load("spring.jmx.default_domain=org.foo");
MBeanServer mBeanServer = this.context.getBean(MBeanServer.class);
assertDomains(mBeanServer, true, "org.foo");
assertDomains(mBeanServer, false, "org.springframework.integration",
@ -209,6 +211,8 @@ public class IntegrationAutoConfigurationTests {
if (configs != null) {
ctx.register(configs);
}
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(ctx, environment);
ConfigurationPropertySources.attach(ctx.getEnvironment());
ctx.register(JmxAutoConfiguration.class, IntegrationAutoConfiguration.class);
ctx.refresh();
this.context = ctx;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -65,13 +65,12 @@ public class XADataSourceAutoConfigurationTests {
public void createFromClass() throws Exception {
ApplicationContext context = createContext(FromProperties.class,
"spring.datasource.xa.data-source-class-name:org.hsqldb.jdbc.pool.JDBCXADataSource",
"spring.datasource.xa.properties.database-name:test");
"spring.datasource.xa.properties.login-timeout:123");
context.getBean(DataSource.class);
MockXADataSourceWrapper wrapper = context.getBean(MockXADataSourceWrapper.class);
JDBCXADataSource dataSource = (JDBCXADataSource) wrapper.getXaDataSource();
assertThat(dataSource).isNotNull();
assertThat(dataSource.getDatabaseName()).isEqualTo("test");
assertThat(dataSource.getLoginTimeout()).isEqualTo(123);
}
private ApplicationContext createContext(Class<?> configuration, String... env) {

View File

@ -40,7 +40,7 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
@RunWith(SpringRunner.class)
@DirtiesContext
@SpringBootTest(webEnvironment = WebEnvironment.NONE, properties = { "env.foo=There",
@SpringBootTest(webEnvironment = WebEnvironment.NONE, properties = { "env.FOO=There",
"foo=World" })
public class MustacheStandaloneIntegrationTests {

View File

@ -37,6 +37,7 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerA
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.test.City;
import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@ -131,6 +132,7 @@ public abstract class AbstractJpaAutoConfigurationTests {
EnvironmentTestUtils.addEnvironment(context, "spring.jpa.open_in_view:false");
context.register(TestConfiguration.class, EmbeddedDataSourceConfiguration.class,
PropertyPlaceholderAutoConfiguration.class, getAutoConfigureClass());
ConfigurationPropertySources.attach(context.getEnvironment());
context.refresh();
assertThat(getInterceptorBeans(context).length).isEqualTo(0);
context.close();

View File

@ -38,6 +38,7 @@ import org.springframework.boot.autoconfigure.security.oauth2.resource.OAuth2Res
import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
@ -244,6 +245,7 @@ public class OAuth2AutoConfigurationTests {
EnvironmentTestUtils.addEnvironment(this.context,
"security.oauth2.client.clientId=client",
"security.oauth2.client.grantType=client_credentials");
ConfigurationPropertySources.attach(this.context.getEnvironment());
this.context.refresh();
OAuth2ClientContext bean = this.context.getBean(OAuth2ClientContext.class);
assertThat(bean.getAccessTokenRequest()).isNotNull();
@ -259,6 +261,7 @@ public class OAuth2AutoConfigurationTests {
EnvironmentTestUtils.addEnvironment(this.context,
"security.oauth2.client.clientId=client",
"security.oauth2.client.grantType=client_credentials");
ConfigurationPropertySources.attach(this.context.getEnvironment());
this.context.refresh();
// The primary context is fine (not session scoped):
OAuth2ClientContext bean = this.context.getBean(OAuth2ClientContext.class);
@ -291,6 +294,7 @@ public class OAuth2AutoConfigurationTests {
MinimalSecureWebApplication.class);
EnvironmentTestUtils.addEnvironment(this.context,
"security.oauth2.resource.jwt.keyValue:DEADBEEF");
ConfigurationPropertySources.attach(this.context.getEnvironment());
this.context.refresh();
assertThat(countBeans(RESOURCE_SERVER_CONFIG)).isEqualTo(1);
assertThat(countBeans(AUTHORIZATION_SERVER_CONFIG)).isEqualTo(0);

View File

@ -100,8 +100,7 @@ public class ResourceServerTokenServicesConfigurationTests {
@Test
public void useRemoteTokenServices() {
EnvironmentTestUtils.addEnvironment(this.environment,
"security.oauth2.resource.tokenInfoUri:http://example.com",
"security.oauth2.resource.clientId=acme");
"security.oauth2.resource.tokenInfoUri:http://example.com");
this.context = new SpringApplicationBuilder(ResourceConfiguration.class)
.environment(this.environment).web(WebApplicationType.NONE).run();
RemoteTokenServices services = this.context.getBean(RemoteTokenServices.class);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -22,6 +22,7 @@ import org.junit.After;
import org.junit.Test;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
@ -93,6 +94,7 @@ public class SendGridAutoConfigurationTests {
private void loadContext(Class<?> additionalConfiguration, String... environment) {
this.context = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(this.context, environment);
ConfigurationPropertySources.attach(this.context.getEnvironment());
this.context.register(SendGridAutoConfiguration.class);
if (additionalConfiguration != null) {
this.context.register(additionalConfiguration);

View File

@ -91,10 +91,9 @@ public class SessionAutoConfigurationTests extends AbstractSessionAutoConfigurat
@Test
public void springSessionTimeoutIsNotAValidProperty() {
this.thrown.expect(BeanCreationException.class);
this.thrown.expectMessage("Could not bind");
load("spring.session.store-type=hash-map", "spring.session.timeout=3000");
MapSessionRepository repository = validateSessionRepository(
MapSessionRepository.class);
assertThat(getSessionTimeout(repository)).isNull();
}
@Test

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.social;
import org.junit.Test;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.social.facebook.api.Facebook;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
@ -38,6 +39,7 @@ public class FacebookAutoConfigurationTests extends AbstractSocialAutoConfigurat
"spring.social.facebook.appId:12345");
EnvironmentTestUtils.addEnvironment(this.context,
"spring.social.facebook.appSecret:secret");
ConfigurationPropertySources.attach(this.context.getEnvironment());
this.context.register(FacebookAutoConfiguration.class);
this.context.register(SocialWebAutoConfiguration.class);
this.context.refresh();

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.social;
import org.junit.Test;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.social.linkedin.api.LinkedIn;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
@ -38,6 +39,7 @@ public class LinkedInAutoConfigurationTests extends AbstractSocialAutoConfigurat
"spring.social.linkedin.appId:12345");
EnvironmentTestUtils.addEnvironment(this.context,
"spring.social.linkedin.appSecret:secret");
ConfigurationPropertySources.attach(this.context.getEnvironment());
this.context.register(LinkedInAutoConfiguration.class);
this.context.register(SocialWebAutoConfiguration.class);
this.context.refresh();

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.social;
import org.junit.Test;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.social.facebook.api.Facebook;
import org.springframework.social.linkedin.api.LinkedIn;
@ -111,6 +112,7 @@ public class MultiApiAutoConfigurationTests extends AbstractSocialAutoConfigurat
private void setupContext(String... environment) {
this.context = new AnnotationConfigWebApplicationContext();
EnvironmentTestUtils.addEnvironment(this.context, environment);
ConfigurationPropertySources.attach(this.context.getEnvironment());
this.context.register(TwitterAutoConfiguration.class);
this.context.register(FacebookAutoConfiguration.class);
this.context.register(LinkedInAutoConfiguration.class);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.social;
import org.junit.Test;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.social.twitter.api.Twitter;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
@ -38,6 +39,7 @@ public class TwitterAutoConfigurationTests extends AbstractSocialAutoConfigurati
"spring.social.twitter.appId:12345");
EnvironmentTestUtils.addEnvironment(this.context,
"spring.social.twitter.appSecret:secret");
ConfigurationPropertySources.attach(this.context.getEnvironment());
this.context.register(TwitterAutoConfiguration.class);
this.context.register(SocialWebAutoConfiguration.class);
this.context.refresh();

View File

@ -118,7 +118,7 @@ public class DispatcherServletAutoConfigurationTests {
this.context = new AnnotationConfigWebApplicationContext();
this.context.setServletContext(new MockServletContext());
this.context.register(DispatcherServletAutoConfiguration.class);
EnvironmentTestUtils.addEnvironment(this.context, "server.servlet_path:/spring");
EnvironmentTestUtils.addEnvironment(this.context, "server.servlet.path:/spring");
this.context.refresh();
assertThat(this.context.getBean(DispatcherServlet.class)).isNotNull();
ServletRegistrationBean<?> registration = this.context

View File

@ -332,7 +332,7 @@ public class WebMvcAutoConfigurationTests {
@Test
public void overrideDateFormat() throws Exception {
load(AllResources.class, "spring.mvc.dateFormat:dd*MM*yyyy");
load(AllResources.class, "spring.mvc.date-format:dd*MM*yyyy");
FormattingConversionService cs = this.context
.getBean(FormattingConversionService.class);
Date date = new DateTime(1988, 6, 25, 20, 30).toDate();

View File

@ -59,7 +59,7 @@ public class WebServicesAutoConfigurationTests {
@Test
public void customPathMustBeginWithASlash() {
this.thrown.expect(BeanCreationException.class);
this.thrown.expectMessage("Path must start with /");
this.thrown.expectMessage("Failed to bind properties under 'spring.webservices'");
load(WebServicesAutoConfiguration.class, "spring.webservices.path=invalid");
}

View File

@ -21,7 +21,6 @@ import java.util.HashMap;
import java.util.Map;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.devtools.restart.Restarter;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.core.Ordered;
@ -37,6 +36,7 @@ import org.springframework.core.env.PropertySource;
*
* @author Phillip Webb
* @author Andy Wilkinson
* @author Madhura Bhave
* @since 1.3.0
*/
@Order(Ordered.LOWEST_PRECEDENCE)
@ -90,9 +90,7 @@ public class DevToolsPropertyDefaultsPostProcessor implements EnvironmentPostPro
}
private boolean isRemoteRestartEnabled(Environment environment) {
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(environment,
"spring.devtools.remote.");
return resolver.containsProperty("secret");
return environment.containsProperty("spring.devtools.remote.secret");
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -21,7 +21,6 @@ import javax.net.ServerSocketFactory;
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.devtools.autoconfigure.RemoteDevToolsProperties;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
@ -30,6 +29,7 @@ import org.springframework.core.type.AnnotatedTypeMetadata;
* Condition used to check that the actual local port is available.
*
* @author Phillip Webb
* @author Madhura Bhave
*/
class LocalDebugPortAvailableCondition extends SpringBootCondition {
@ -38,12 +38,9 @@ class LocalDebugPortAvailableCondition extends SpringBootCondition {
AnnotatedTypeMetadata metadata) {
ConditionMessage.Builder message = ConditionMessage
.forCondition("Local Debug Port Condition");
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
context.getEnvironment(), "spring.devtools.remote.debug.");
Integer port = resolver.getProperty("local-port", Integer.class);
if (port == null) {
port = RemoteDevToolsProperties.Debug.DEFAULT_LOCAL_PORT;
}
Integer port = context.getEnvironment().getProperty(
"spring.devtools.remote.debug.local-port", Integer.class,
RemoteDevToolsProperties.Debug.DEFAULT_LOCAL_PORT);
if (isPortAvailable(port)) {
return ConditionOutcome.match(message.foundExactly("local debug port"));
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2015 the original author or authors.
* Copyright 2012-2017 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.
@ -18,9 +18,11 @@ package sample.propertyvalidation;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
@Component
@ConfigurationProperties(prefix = "sample")
@Validated
public class SampleProperties {
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -63,7 +63,7 @@ public class SamplePropertyValidationApplicationTests {
EnvironmentTestUtils.addEnvironment(this.context, "sample.host:xxxxxx",
"sample.port:9090");
this.thrown.expect(BeanCreationException.class);
this.thrown.expectMessage("xxxxxx");
this.thrown.expectMessage("Failed to bind properties under 'sample'");
this.context.refresh();
}
@ -71,8 +71,7 @@ public class SamplePropertyValidationApplicationTests {
public void bindNullHost() {
this.context.register(SamplePropertyValidationApplication.class);
this.thrown.expect(BeanCreationException.class);
this.thrown.expectMessage("null");
this.thrown.expectMessage("host");
this.thrown.expectMessage("Failed to bind properties under 'sample'");
this.context.refresh();
}

View File

@ -21,13 +21,14 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.beans.BeanUtils;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.MapConfigurationPropertySource;
import org.springframework.boot.test.mock.web.SpringBootMockServletContext;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.boot.web.reactive.context.GenericReactiveWebApplicationContext;
@ -40,10 +41,6 @@ import org.springframework.core.SpringVersion;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySources;
import org.springframework.core.env.PropertySourcesPropertyResolver;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.test.context.ContextConfigurationAttributes;
@ -76,6 +73,7 @@ import org.springframework.web.context.support.GenericWebApplicationContext;
* @author Phillip Webb
* @author Andy Wilkinson
* @author Stephane Nicoll
* @author Madhura Bhave
* @see SpringBootTest
*/
public class SpringBootContextLoader extends AbstractContextLoader {
@ -171,19 +169,15 @@ public class SpringBootContextLoader extends AbstractContextLoader {
}
private boolean hasCustomServerPort(List<String> properties) {
PropertySources sources = convertToPropertySources(properties);
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
new PropertySourcesPropertyResolver(sources), "server.");
return resolver.containsProperty("port");
Binder binder = new Binder(convertToConfigurationPropertySource(properties));
return binder.bind("server.port", Bindable.of(String.class)).isBound();
}
private PropertySources convertToPropertySources(List<String> properties) {
Map<String, Object> source = TestPropertySourceUtils
.convertInlinedPropertiesToMap(
properties.toArray(new String[properties.size()]));
MutablePropertySources sources = new MutablePropertySources();
sources.addFirst(new MapPropertySource("inline", source));
return sources;
private MapConfigurationPropertySource convertToConfigurationPropertySource(
List<String> properties) {
String[] array = properties.toArray(new String[properties.size()]);
return new MapConfigurationPropertySource(
TestPropertySourceUtils.convertInlinedPropertiesToMap(array));
}
private List<ApplicationContextInitializer<?>> getInitializers(

View File

@ -21,7 +21,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
@ -29,15 +28,14 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.context.properties.source.MapConfigurationPropertySource;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySources;
import org.springframework.core.env.PropertySourcesPropertyResolver;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.ContextConfigurationAttributes;
@ -71,6 +69,7 @@ import org.springframework.util.ObjectUtils;
* @author Phillip Webb
* @author Andy Wilkinson
* @author Brian Clozel
* @author Madhura Bhave
* @since 1.4.0
* @see SpringBootTest
* @see TestConfiguration
@ -98,7 +97,7 @@ public class SpringBootTestContextBootstrapper extends DefaultTestContextBootstr
verifyConfiguration(context.getTestClass());
WebEnvironment webEnvironment = getWebEnvironment(context.getTestClass());
if (webEnvironment == WebEnvironment.MOCK
&& deduceWebApplication() == WebApplicationType.SERVLET) {
&& deduceWebApplicationType() == WebApplicationType.SERVLET) {
context.setAttribute(ACTIVATE_SERVLET_LISTENER, true);
}
else if (webEnvironment != null && webEnvironment.isEmbedded()) {
@ -181,15 +180,17 @@ public class SpringBootTestContextBootstrapper extends DefaultTestContextBootstr
private WebApplicationType getWebApplicationType(
MergedContextConfiguration configuration) {
WebApplicationType webApplicationType = getConfiguredWebApplicationType(
configuration);
if (webApplicationType != null) {
return webApplicationType;
}
return deduceWebApplication();
ConfigurationPropertySource source = new MapConfigurationPropertySource(
TestPropertySourceUtils.convertInlinedPropertiesToMap(
configuration.getPropertySourceProperties()));
Binder binder = new Binder(source);
return binder
.bind("spring.main.web-application-type",
Bindable.of(WebApplicationType.class))
.orElseGet(this::deduceWebApplicationType);
}
private WebApplicationType deduceWebApplication() {
private WebApplicationType deduceWebApplicationType() {
if (ClassUtils.isPresent(REACTIVE_WEB_ENVIRONMENT_CLASS, null)
&& !ClassUtils.isPresent(MVC_WEB_ENVIRONMENT_CLASS, null)) {
return WebApplicationType.REACTIVE;
@ -228,25 +229,6 @@ public class SpringBootTestContextBootstrapper extends DefaultTestContextBootstr
return false;
}
private WebApplicationType getConfiguredWebApplicationType(
MergedContextConfiguration configuration) {
PropertySources sources = convertToPropertySources(
configuration.getPropertySourceProperties());
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
new PropertySourcesPropertyResolver(sources), "spring.main.");
String property = resolver.getProperty("web-application-type");
return (property != null ? WebApplicationType.valueOf(property.toUpperCase())
: null);
}
private PropertySources convertToPropertySources(String[] properties) {
Map<String, Object> source = TestPropertySourceUtils
.convertInlinedPropertiesToMap(properties);
MutablePropertySources sources = new MutablePropertySources();
sources.addFirst(new MapPropertySource("inline", source));
return sources;
}
protected Class<?>[] getOrFindConfigurationClasses(
MergedContextConfiguration mergedConfig) {
Class<?>[] classes = mergedConfig.getClasses();

View File

@ -16,7 +16,6 @@
package org.springframework.boot.test.web.client;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.web.client.RootUriTemplateHandler;
import org.springframework.core.env.Environment;
import org.springframework.util.Assert;
@ -30,6 +29,7 @@ import org.springframework.web.util.UriTemplateHandler;
* @author Phillip Webb
* @author Andy Wilkinson
* @author Eddú Meléndez
* @author Madhura Bhave
* @since 1.4.0
*/
public class LocalHostUriTemplateHandler extends RootUriTemplateHandler {
@ -38,7 +38,7 @@ public class LocalHostUriTemplateHandler extends RootUriTemplateHandler {
private final String scheme;
private RelaxedPropertyResolver servletPropertyResolver;
private final String prefix = "server.servlet.";
/**
* Create a new {@code LocalHostUriTemplateHandler} that will generate {@code http}
@ -63,14 +63,13 @@ public class LocalHostUriTemplateHandler extends RootUriTemplateHandler {
Assert.notNull(scheme, "Scheme must not be null");
this.environment = environment;
this.scheme = scheme;
this.servletPropertyResolver = new RelaxedPropertyResolver(environment,
"server.servlet.");
}
@Override
public String getRootUri() {
String port = this.environment.getProperty("local.server.port", "8080");
String contextPath = this.servletPropertyResolver.getProperty("context-path", "");
String contextPath = this.environment.getProperty(this.prefix + "context-path",
"");
return this.scheme + "://localhost:" + port + contextPath;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -33,9 +33,7 @@ import org.springframework.boot.ansi.AnsiColor;
import org.springframework.boot.ansi.AnsiColors;
import org.springframework.boot.ansi.AnsiElement;
import org.springframework.boot.ansi.AnsiOutput;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertyResolver;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
@ -45,6 +43,7 @@ import org.springframework.util.Assert;
*
* @author Craig Burke
* @author Phillip Webb
* @author Madhura Bhave
* @since 1.4.0
*/
public class ImageBanner implements Banner {
@ -92,12 +91,11 @@ public class ImageBanner implements Banner {
private void printBanner(Environment environment, PrintStream out)
throws IOException {
PropertyResolver properties = new RelaxedPropertyResolver(environment,
"banner.image.");
int width = properties.getProperty("width", Integer.class, 76);
int height = properties.getProperty("height", Integer.class, 0);
int margin = properties.getProperty("margin", Integer.class, 2);
boolean invert = properties.getProperty("invert", Boolean.class, false);
int width = environment.getProperty("banner.image.width", Integer.class, 76);
int height = environment.getProperty("banner.image.height", Integer.class, 0);
int margin = environment.getProperty("banner.image.margin", Integer.class, 2);
boolean invert = environment.getProperty("banner.image.invert", Boolean.class,
false);
BufferedImage image = readImage(width, height);
printBanner(image, margin, invert, out);
}

View File

@ -40,8 +40,9 @@ import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.boot.Banner.Mode;
import org.springframework.boot.bind.PropertiesConfigurationFactory;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ApplicationListener;
@ -54,8 +55,6 @@ import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.GenericTypeResolver;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.env.CommandLinePropertySource;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
@ -75,7 +74,6 @@ import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StopWatch;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindException;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.StandardServletEnvironment;
@ -375,6 +373,7 @@ public class SpringApplication {
&& this.webApplicationType == WebApplicationType.NONE) {
environment = convertToStandardEnvironment(environment);
}
ConfigurationPropertySources.attach(environment);
return environment;
}
@ -576,9 +575,8 @@ public class SpringApplication {
private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
if (System.getProperty(
CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) {
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(environment,
"spring.beaninfo.");
Boolean ignore = resolver.getProperty("ignore", Boolean.class, Boolean.TRUE);
Boolean ignore = environment.getProperty("spring.beaninfo.ignore",
Boolean.class, Boolean.TRUE);
System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME,
ignore.toString());
}
@ -589,16 +587,10 @@ public class SpringApplication {
* @param environment the environment to bind
*/
protected void bindToSpringApplication(ConfigurableEnvironment environment) {
PropertiesConfigurationFactory<SpringApplication> binder = new PropertiesConfigurationFactory<>(
this);
ConversionService conversionService = new DefaultConversionService();
binder.setTargetName("spring.main");
binder.setConversionService(conversionService);
binder.setPropertySources(environment.getPropertySources());
try {
binder.bindPropertiesToTarget();
Binder.get(environment).bind("spring.main", Bindable.ofInstance(this));
}
catch (BindException ex) {
catch (Exception ex) {
throw new IllegalStateException("Cannot bind to SpringApplication", ex);
}
}

View File

@ -1,118 +0,0 @@
/*
* Copyright 2012-2017 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.Arrays;
import java.util.HashSet;
import java.util.Set;
/**
* {@link PropertyNamePatternsMatcher} that matches when a property name exactly matches
* one of the given names, or starts with one of the given names followed by a delimiter.
* This implementation is optimized for frequent calls.
*
* @author Phillip Webb
* @since 1.2.0
*/
class DefaultPropertyNamePatternsMatcher implements PropertyNamePatternsMatcher {
private final char[] delimiters;
private final boolean ignoreCase;
private final String[] names;
protected DefaultPropertyNamePatternsMatcher(char[] delimiters, String... names) {
this(delimiters, false, names);
}
protected DefaultPropertyNamePatternsMatcher(char[] delimiters, boolean ignoreCase,
String... names) {
this(delimiters, ignoreCase, new HashSet<>(Arrays.asList(names)));
}
DefaultPropertyNamePatternsMatcher(char[] delimiters, boolean ignoreCase,
Set<String> names) {
this.delimiters = delimiters;
this.ignoreCase = ignoreCase;
this.names = names.toArray(new String[names.size()]);
}
@Override
public boolean matches(String propertyName) {
char[] propertyNameChars = propertyName.toCharArray();
boolean[] match = new boolean[this.names.length];
boolean noneMatched = true;
for (int i = 0; i < this.names.length; i++) {
if (this.names[i].length() <= propertyNameChars.length) {
match[i] = true;
noneMatched = false;
}
}
if (noneMatched) {
return false;
}
for (int charIndex = 0; charIndex < propertyNameChars.length; charIndex++) {
for (int nameIndex = 0; nameIndex < this.names.length; nameIndex++) {
if (match[nameIndex]) {
match[nameIndex] = false;
if (charIndex < this.names[nameIndex].length()) {
if (isCharMatch(this.names[nameIndex].charAt(charIndex),
propertyNameChars[charIndex])) {
match[nameIndex] = true;
noneMatched = false;
}
}
else {
char charAfter = propertyNameChars[this.names[nameIndex]
.length()];
if (isDelimiter(charAfter)) {
match[nameIndex] = true;
noneMatched = false;
}
}
}
}
if (noneMatched) {
return false;
}
}
for (int i = 0; i < match.length; i++) {
if (match[i]) {
return true;
}
}
return false;
}
private boolean isCharMatch(char c1, char c2) {
if (this.ignoreCase) {
return Character.toLowerCase(c1) == Character.toLowerCase(c2);
}
return c1 == c2;
}
private boolean isDelimiter(char c) {
for (char delimiter : this.delimiters) {
if (c == delimiter) {
return true;
}
}
return false;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2015 the original author or authors.
* Copyright 2012-2017 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.
@ -26,6 +26,7 @@ import java.net.UnknownHostException;
*
* @author Dave Syer
*/
@Deprecated
public class InetAddressEditor extends PropertyEditorSupport {
@Override

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2015 the original author or authors.
* Copyright 2012-2017 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.
@ -24,6 +24,7 @@ import org.springframework.core.env.PropertySource;
*
* @author Andy Wilkinson
*/
@Deprecated
class OriginCapablePropertyValue extends PropertyValue {
private static final String ATTRIBUTE_PROPERTY_ORIGIN = "propertyOrigin";

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2017 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.
@ -27,6 +27,7 @@ import org.springframework.util.PatternMatchUtils;
* @author Phillip Webb
* @since 1.2.0
*/
@Deprecated
class PatternPropertyNamePatternsMatcher implements PropertyNamePatternsMatcher {
private final String[] patterns;

View File

@ -1,345 +0,0 @@
/*
* Copyright 2012-2017 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.beans.PropertyDescriptor;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.env.PropertySources;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.DataBinder;
import org.springframework.validation.ObjectError;
import org.springframework.validation.Validator;
/**
* Validate some {@link Properties} (or optionally {@link PropertySources}) by binding
* them to an object of a specified type and then optionally running a {@link Validator}
* over it.
*
* @param <T> the target type
* @author Dave Syer
*/
public class PropertiesConfigurationFactory<T>
implements FactoryBean<T>, MessageSourceAware, InitializingBean {
private static final char[] EXACT_DELIMITERS = { '_', '.', '[' };
private static final char[] TARGET_NAME_DELIMITERS = { '_', '.' };
private static final Log logger = LogFactory
.getLog(PropertiesConfigurationFactory.class);
private boolean ignoreUnknownFields = true;
private boolean ignoreInvalidFields;
private PropertySources propertySources;
private final T target;
private Validator validator;
private MessageSource messageSource;
private boolean hasBeenBound = false;
private boolean ignoreNestedProperties = false;
private String targetName;
private ConversionService conversionService;
private boolean resolvePlaceholders = true;
/**
* Create a new {@link PropertiesConfigurationFactory} instance.
* @param target the target object to bind too
* @see #PropertiesConfigurationFactory(Class)
*/
public PropertiesConfigurationFactory(T target) {
Assert.notNull(target, "Target object must not be null");
this.target = target;
}
/**
* Create a new {@link PropertiesConfigurationFactory} instance.
* @param type the target type
* @see #PropertiesConfigurationFactory(Class)
*/
@SuppressWarnings("unchecked")
public PropertiesConfigurationFactory(Class<?> type) {
Assert.notNull(type, "Target type must not be null");
this.target = (T) BeanUtils.instantiateClass(type);
}
/**
* Flag to disable binding of nested properties (i.e. those with period separators in
* their paths). Can be useful to disable this if the name prefix is empty and you
* don't want to ignore unknown fields.
* @param ignoreNestedProperties the flag to set (default false)
*/
public void setIgnoreNestedProperties(boolean ignoreNestedProperties) {
this.ignoreNestedProperties = ignoreNestedProperties;
}
/**
* Set whether to ignore unknown fields, that is, whether to ignore bind parameters
* that do not have corresponding fields in the target object.
* <p>
* Default is "true". Turn this off to enforce that all bind parameters must have a
* matching field in the target object.
* @param ignoreUnknownFields if unknown fields should be ignored
*/
public void setIgnoreUnknownFields(boolean ignoreUnknownFields) {
this.ignoreUnknownFields = ignoreUnknownFields;
}
/**
* Set whether to ignore invalid fields, that is, whether to ignore bind parameters
* that have corresponding fields in the target object which are not accessible (for
* example because of null values in the nested path).
* <p>
* Default is "false". Turn this on to ignore bind parameters for nested objects in
* non-existing parts of the target object graph.
* @param ignoreInvalidFields if invalid fields should be ignored
*/
public void setIgnoreInvalidFields(boolean ignoreInvalidFields) {
this.ignoreInvalidFields = ignoreInvalidFields;
}
/**
* Set the target name.
* @param targetName the target name
*/
public void setTargetName(String targetName) {
this.targetName = targetName;
}
/**
* Set the message source.
* @param messageSource the message source
*/
@Override
public void setMessageSource(MessageSource messageSource) {
this.messageSource = messageSource;
}
/**
* Set the property sources.
* @param propertySources the property sources
*/
public void setPropertySources(PropertySources propertySources) {
this.propertySources = propertySources;
}
/**
* Set the conversion service.
* @param conversionService the conversion service
*/
public void setConversionService(ConversionService conversionService) {
this.conversionService = conversionService;
}
/**
* Set the validator.
* @param validator the validator
*/
public void setValidator(Validator validator) {
this.validator = validator;
}
/**
* Flag to indicate that placeholders should be replaced during binding. Default is
* true.
* @param resolvePlaceholders flag value
*/
public void setResolvePlaceholders(boolean resolvePlaceholders) {
this.resolvePlaceholders = resolvePlaceholders;
}
@Override
public void afterPropertiesSet() throws Exception {
bindPropertiesToTarget();
}
@Override
public Class<?> getObjectType() {
if (this.target == null) {
return Object.class;
}
return this.target.getClass();
}
@Override
public boolean isSingleton() {
return true;
}
@Override
public T getObject() throws Exception {
if (!this.hasBeenBound) {
bindPropertiesToTarget();
}
return this.target;
}
public void bindPropertiesToTarget() throws BindException {
Assert.state(this.propertySources != null, "PropertySources should not be null");
if (logger.isTraceEnabled()) {
logger.trace("Property Sources: " + this.propertySources);
}
this.hasBeenBound = true;
doBindPropertiesToTarget();
}
private void doBindPropertiesToTarget() throws BindException {
RelaxedDataBinder dataBinder = (this.targetName != null
? new RelaxedDataBinder(this.target, this.targetName)
: new RelaxedDataBinder(this.target));
if (this.validator != null
&& this.validator.supports(dataBinder.getTarget().getClass())) {
dataBinder.setValidator(this.validator);
}
if (this.conversionService != null) {
dataBinder.setConversionService(this.conversionService);
}
dataBinder.setAutoGrowCollectionLimit(Integer.MAX_VALUE);
dataBinder.setIgnoreNestedProperties(this.ignoreNestedProperties);
dataBinder.setIgnoreInvalidFields(this.ignoreInvalidFields);
dataBinder.setIgnoreUnknownFields(this.ignoreUnknownFields);
customizeBinder(dataBinder);
Iterable<String> relaxedTargetNames = getRelaxedTargetNames();
Set<String> names = getNames(relaxedTargetNames);
PropertyValues propertyValues = getPropertySourcesPropertyValues(names,
relaxedTargetNames);
dataBinder.bind(propertyValues);
if (this.validator != null) {
dataBinder.validate();
}
checkForBindingErrors(dataBinder);
}
private Iterable<String> getRelaxedTargetNames() {
return (this.target != null && StringUtils.hasLength(this.targetName)
? new RelaxedNames(this.targetName) : null);
}
private Set<String> getNames(Iterable<String> prefixes) {
Set<String> names = new LinkedHashSet<>();
if (this.target != null) {
PropertyDescriptor[] descriptors = BeanUtils
.getPropertyDescriptors(this.target.getClass());
for (PropertyDescriptor descriptor : descriptors) {
String name = descriptor.getName();
if (!name.equals("class")) {
RelaxedNames relaxedNames = RelaxedNames.forCamelCase(name);
if (prefixes == null) {
for (String relaxedName : relaxedNames) {
names.add(relaxedName);
}
}
else {
for (String prefix : prefixes) {
for (String relaxedName : relaxedNames) {
names.add(prefix + "." + relaxedName);
names.add(prefix + "_" + relaxedName);
}
}
}
}
}
}
return names;
}
private PropertyValues getPropertySourcesPropertyValues(Set<String> names,
Iterable<String> relaxedTargetNames) {
PropertyNamePatternsMatcher includes = getPropertyNamePatternsMatcher(names,
relaxedTargetNames);
return new PropertySourcesPropertyValues(this.propertySources, names, includes,
this.resolvePlaceholders);
}
private PropertyNamePatternsMatcher getPropertyNamePatternsMatcher(Set<String> names,
Iterable<String> relaxedTargetNames) {
if (this.ignoreUnknownFields && !isMapTarget()) {
// Since unknown fields are ignored we can filter them out early to save
// unnecessary calls to the PropertySource.
return new DefaultPropertyNamePatternsMatcher(EXACT_DELIMITERS, true, names);
}
if (relaxedTargetNames != null) {
// We can filter properties to those starting with the target name, but
// we can't do a complete filter since we need to trigger the
// unknown fields check
Set<String> relaxedNames = new HashSet<>();
for (String relaxedTargetName : relaxedTargetNames) {
relaxedNames.add(relaxedTargetName);
}
return new DefaultPropertyNamePatternsMatcher(TARGET_NAME_DELIMITERS, true,
relaxedNames);
}
// Not ideal, we basically can't filter anything
return PropertyNamePatternsMatcher.ALL;
}
private boolean isMapTarget() {
return this.target != null && Map.class.isAssignableFrom(this.target.getClass());
}
private void checkForBindingErrors(RelaxedDataBinder dataBinder)
throws BindException {
BindingResult errors = dataBinder.getBindingResult();
if (errors.hasErrors()) {
logger.error("Properties configuration failed validation");
for (ObjectError error : errors.getAllErrors()) {
logger.error(
this.messageSource != null
? this.messageSource.getMessage(error,
Locale.getDefault()) + " (" + error + ")"
: error);
}
throw new BindException(errors);
}
}
/**
* Customize the data binder.
* @param dataBinder the data binder that will be used to bind and validate
*/
protected void customizeBinder(DataBinder dataBinder) {
}
}

View File

@ -22,6 +22,7 @@ package org.springframework.boot.bind;
* @author Phillip Webb
* @since 1.2.0
*/
@Deprecated
interface PropertyNamePatternsMatcher {
PropertyNamePatternsMatcher ALL = new PropertyNamePatternsMatcher() {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2015 the original author or authors.
* Copyright 2012-2017 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.
@ -25,6 +25,7 @@ import org.springframework.core.env.PropertySource;
* @author Andy Wilkinson
* @since 1.3.0
*/
@Deprecated
public class PropertyOrigin {
private final PropertySource<?> source;

View File

@ -1,91 +0,0 @@
/*
* Copyright 2012-2017 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.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.env.PropertySources;
/**
* Convenience class for manipulating PropertySources.
*
* @author Dave Syer
* @see PropertySource
* @see PropertySources
*/
public abstract class PropertySourceUtils {
/**
* Return a Map of all values from the specified {@link PropertySources} that start
* with a particular key.
* @param propertySources the property sources to scan
* @param keyPrefix the key prefixes to test
* @return a map of all sub properties starting with the specified key prefixes.
* @see PropertySourceUtils#getSubProperties(PropertySources, String, String)
*/
public static Map<String, Object> getSubProperties(PropertySources propertySources,
String keyPrefix) {
return PropertySourceUtils.getSubProperties(propertySources, null, keyPrefix);
}
/**
* Return a Map of all values from the specified {@link PropertySources} that start
* with a particular key.
* @param propertySources the property sources to scan
* @param rootPrefix a root prefix to be prepended to the keyPrefix (can be
* {@code null})
* @param keyPrefix the key prefixes to test
* @return a map of all sub properties starting with the specified key prefixes.
* @see #getSubProperties(PropertySources, String, String)
*/
public static Map<String, Object> getSubProperties(PropertySources propertySources,
String rootPrefix, String keyPrefix) {
RelaxedNames keyPrefixes = new RelaxedNames(keyPrefix);
Map<String, Object> subProperties = new LinkedHashMap<>();
for (PropertySource<?> source : propertySources) {
if (source instanceof EnumerablePropertySource) {
for (String name : ((EnumerablePropertySource<?>) source)
.getPropertyNames()) {
String key = PropertySourceUtils.getSubKey(name, rootPrefix,
keyPrefixes);
if (key != null && !subProperties.containsKey(key)) {
subProperties.put(key, source.getProperty(name));
}
}
}
}
return Collections.unmodifiableMap(subProperties);
}
private static String getSubKey(String name, String rootPrefixes,
RelaxedNames keyPrefix) {
rootPrefixes = (rootPrefixes == null ? "" : rootPrefixes);
for (String rootPrefix : new RelaxedNames(rootPrefixes)) {
for (String candidateKeyPrefix : keyPrefix) {
if (name.startsWith(rootPrefix + candidateKeyPrefix)) {
return name.substring((rootPrefix + candidateKeyPrefix).length());
}
}
}
return null;
}
}

View File

@ -1,128 +0,0 @@
/*
* Copyright 2012-2017 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.LinkedHashMap;
import java.util.Map;
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;
/**
* Helper extracting info from {@link PropertySources}.
*
* @author Stephane Nicoll
* @since 1.4.0
*/
public class PropertySourcesBinder {
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 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.
* <p>
* Any key that starts with the {@code prefix} will be included.
* @param prefix the prefix to use
* @return the keys matching the prefix
*/
public Map<String, Object> extractAll(String prefix) {
Map<String, Object> content = new LinkedHashMap<>();
bindTo(prefix, content);
return content;
}
/**
* Bind the specified {@code target} from the environment using the {@code prefix}.
* <p>
* Any key that starts with the {@code prefix} will be bound to the {@code target}.
* @param prefix the prefix to use
* @param target the object to bind to
*/
public void bindTo(String prefix, Object target) {
PropertiesConfigurationFactory<Object> factory = new PropertiesConfigurationFactory<>(
target);
if (StringUtils.hasText(prefix)) {
factory.setTargetName(prefix);
}
if (this.conversionService != null) {
factory.setConversionService(this.conversionService);
}
factory.setPropertySources(this.propertySources);
try {
factory.bindPropertiesToTarget();
}
catch (BindException ex) {
throw new IllegalStateException("Cannot bind to " + target, ex);
}
}
private static PropertySources createPropertySources(
PropertySource<?> propertySource) {
MutablePropertySources propertySources = new MutablePropertySources();
propertySources.addLast(propertySource);
return propertySources;
}
}

View File

@ -25,8 +25,10 @@ import java.util.regex.Pattern;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.PropertyValues;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.core.env.PropertySources;
import org.springframework.core.env.PropertySourcesPropertyResolver;
@ -41,6 +43,7 @@ import org.springframework.validation.DataBinder;
* @author Dave Syer
* @author Phillip Webb
*/
@Deprecated
public class PropertySourcesPropertyValues implements PropertyValues {
private static final Pattern COLLECTION_PROPERTY = Pattern
@ -107,6 +110,10 @@ public class PropertySourcesPropertyValues implements PropertyValues {
PropertyNamePatternsMatcher includes, boolean resolvePlaceholders) {
Assert.notNull(propertySources, "PropertySources must not be null");
Assert.notNull(includes, "Includes must not be null");
MutablePropertySources mutablePropertySources = new MutablePropertySources(
propertySources);
mutablePropertySources.remove(ConfigurationPropertySources.PROPERTY_SOURCE_NAME);
propertySources = mutablePropertySources;
this.propertySources = propertySources;
this.nonEnumerableFallbackNames = nonEnumerableFallbackNames;
this.includes = includes;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2015 the original author or authors.
* Copyright 2012-2017 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.
@ -26,6 +26,7 @@ import org.springframework.beans.NotWritablePropertyException;
* @since 1.3.0
* @see RelaxedDataBinder
*/
@Deprecated
public class RelaxedBindingNotWritablePropertyException
extends NotWritablePropertyException {

View File

@ -36,6 +36,7 @@ import org.springframework.util.Assert;
* @author Stephane Nicoll
* @since 1.1.0
*/
@Deprecated
class RelaxedConversionService implements ConversionService {
private final ConversionService conversionService;

View File

@ -56,6 +56,7 @@ import org.springframework.validation.DataBinder;
* @author Andy Wilkinson
* @see RelaxedNames
*/
@Deprecated
public class RelaxedDataBinder extends DataBinder {
private static final Object BLANK = new Object();

View File

@ -30,8 +30,8 @@ import org.springframework.util.StringUtils;
* @author Phillip Webb
* @author Dave Syer
* @see RelaxedDataBinder
* @see RelaxedPropertyResolver
*/
@Deprecated
public final class RelaxedNames implements Iterable<String> {
private static final Pattern CAMEL_CASE_PATTERN = Pattern.compile("([^A-Z-])([A-Z])");

View File

@ -1,155 +0,0 @@
/*
* 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.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertyResolver;
import org.springframework.core.env.PropertySourcesPropertyResolver;
import org.springframework.util.Assert;
/**
* {@link PropertyResolver} that attempts to resolve values using {@link RelaxedNames}.
*
* @author Phillip Webb
* @see RelaxedNames
*/
public class RelaxedPropertyResolver implements PropertyResolver {
private final PropertyResolver resolver;
private final String prefix;
public RelaxedPropertyResolver(PropertyResolver resolver) {
this(resolver, null);
}
public RelaxedPropertyResolver(PropertyResolver resolver, String prefix) {
Assert.notNull(resolver, "PropertyResolver must not be null");
this.resolver = resolver;
this.prefix = (prefix == null ? "" : prefix);
}
@Override
public String getRequiredProperty(String key) throws IllegalStateException {
return getRequiredProperty(key, String.class);
}
@Override
public <T> T getRequiredProperty(String key, Class<T> targetType)
throws IllegalStateException {
T value = getProperty(key, targetType);
Assert.state(value != null, String.format("required key [%s] not found", key));
return value;
}
@Override
public String getProperty(String key) {
return getProperty(key, String.class, null);
}
@Override
public String getProperty(String key, String defaultValue) {
return getProperty(key, String.class, defaultValue);
}
@Override
public <T> T getProperty(String key, Class<T> targetType) {
return getProperty(key, targetType, null);
}
@Override
public <T> T getProperty(String key, Class<T> targetType, T defaultValue) {
RelaxedNames prefixes = new RelaxedNames(this.prefix);
RelaxedNames keys = new RelaxedNames(key);
for (String prefix : prefixes) {
for (String relaxedKey : keys) {
if (this.resolver.containsProperty(prefix + relaxedKey)) {
return this.resolver.getProperty(prefix + relaxedKey, targetType);
}
}
}
return defaultValue;
}
@Override
public boolean containsProperty(String key) {
RelaxedNames prefixes = new RelaxedNames(this.prefix);
RelaxedNames keys = new RelaxedNames(key);
for (String prefix : prefixes) {
for (String relaxedKey : keys) {
if (this.resolver.containsProperty(prefix + relaxedKey)) {
return true;
}
}
}
return false;
}
@Override
public String resolvePlaceholders(String text) {
throw new UnsupportedOperationException(
"Unable to resolve placeholders with relaxed properties");
}
@Override
public String resolveRequiredPlaceholders(String text)
throws IllegalArgumentException {
throw new UnsupportedOperationException(
"Unable to resolve placeholders with relaxed properties");
}
/**
* Return a Map of all values from all underlying properties that start with the
* specified key. NOTE: this method can only be used if the underlying resolver is a
* {@link ConfigurableEnvironment}.
* @param keyPrefix the key prefix used to filter results
* @return a map of all sub properties starting with the specified key prefix.
* @see PropertySourceUtils#getSubProperties
*/
public Map<String, Object> getSubProperties(String keyPrefix) {
Assert.isInstanceOf(ConfigurableEnvironment.class, this.resolver,
"SubProperties not available.");
ConfigurableEnvironment env = (ConfigurableEnvironment) this.resolver;
return PropertySourceUtils.getSubProperties(env.getPropertySources(), this.prefix,
keyPrefix);
}
/**
* Return a property resolver for the environment, preferring one that ignores
* unresolvable nested placeholders.
* @param environment the source environment
* @param prefix the prefix
* @return a property resolver for the environment
* @since 1.4.3
*/
public static RelaxedPropertyResolver ignoringUnresolvableNestedPlaceholders(
Environment environment, String prefix) {
Assert.notNull(environment, "Environment must not be null");
PropertyResolver resolver = environment;
if (environment instanceof ConfigurableEnvironment) {
resolver = new PropertySourcesPropertyResolver(
((ConfigurableEnvironment) environment).getPropertySources());
((PropertySourcesPropertyResolver) resolver)
.setIgnoreUnresolvableNestedPlaceholders(true);
}
return new RelaxedPropertyResolver(resolver, prefix);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2017 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.
@ -23,6 +23,7 @@ import org.springframework.core.convert.converter.Converter;
*
* @author Phillip Webb
*/
@Deprecated
class StringToCharArrayConverter implements Converter<String, char[]> {
@Override

View File

@ -48,6 +48,7 @@ import org.springframework.validation.Validator;
* @author Luke Taylor
* @author Dave Syer
*/
@Deprecated
public class YamlConfigurationFactory<T>
implements FactoryBean<T>, MessageSourceAware, InitializingBean {

View File

@ -31,6 +31,7 @@ import org.yaml.snakeyaml.nodes.NodeId;
*
* @author Luke Taylor
*/
@Deprecated
public class YamlJavaBeanPropertyConstructor extends Constructor {
private final Map<Class<?>, Map<String, Property>> properties = new HashMap<>();

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -19,10 +19,10 @@ package org.springframework.boot.context;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
/**
* An {@link ApplicationListener} that halts application startup if the system file
@ -42,6 +42,7 @@ import org.springframework.core.Ordered;
* character-encoding value (e.g. "en_GB.UTF-8").
*
* @author Dave Syer
* @author Madhura Bhave
*/
public class FileEncodingApplicationListener
implements ApplicationListener<ApplicationEnvironmentPreparedEvent>, Ordered {
@ -56,11 +57,12 @@ public class FileEncodingApplicationListener
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
event.getEnvironment(), "spring.");
if (resolver.containsProperty("mandatoryFileEncoding")) {
ConfigurableEnvironment environment = event.getEnvironment();
if (!environment.containsProperty("spring.mandatory-file-encoding")) {
return;
}
String encoding = System.getProperty("file.encoding");
String desired = resolver.getProperty("mandatoryFileEncoding");
String desired = environment.getProperty("spring.mandatory-file-encoding");
if (encoding != null && !desired.equalsIgnoreCase(encoding)) {
logger.error("System property 'file.encoding' is currently '" + encoding
+ "'. It should be '" + desired
@ -73,9 +75,7 @@ public class FileEncodingApplicationListener
+ desired + "'.");
throw new IllegalStateException(
"The Java Virtual Machine has not been configured to use the "
+ "desired default character encoding (" + desired
+ ").");
}
+ "desired default character encoding (" + desired + ").");
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2015 the original author or authors.
* Copyright 2012-2017 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.
@ -18,10 +18,11 @@ package org.springframework.boot.context.config;
import org.springframework.boot.ansi.AnsiOutput;
import org.springframework.boot.ansi.AnsiOutput.Enabled;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.ApplicationListener;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
/**
* An {@link ApplicationListener} that configures {@link AnsiOutput} depending on the
@ -29,6 +30,7 @@ import org.springframework.core.Ordered;
* values.
*
* @author Raphael von der Grün
* @author Madhura Bhave
* @since 1.2.0
*/
public class AnsiOutputApplicationListener
@ -36,23 +38,17 @@ public class AnsiOutputApplicationListener
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
event.getEnvironment(), "spring.output.ansi.");
if (resolver.containsProperty("enabled")) {
String enabled = resolver.getProperty("enabled");
AnsiOutput.setEnabled(Enum.valueOf(Enabled.class, enabled.toUpperCase()));
}
if (resolver.containsProperty("console-available")) {
AnsiOutput.setConsoleAvailable(
resolver.getProperty("console-available", Boolean.class));
}
ConfigurableEnvironment environment = event.getEnvironment();
Binder.get(environment)
.bind("spring.output.ansi.enabled", AnsiOutput.Enabled.class)
.ifBound(AnsiOutput::setEnabled);
AnsiOutput.setConsoleAvailable(environment
.getProperty("spring.output.ansi.console-available", Boolean.class));
}
@Override
public int getOrder() {
// Apply after ConfigFileApplicationListener has called all
// EnvironmentPostProcessors
// Apply after ConfigFileApplicationListener has called EnvironmentPostProcessors
return ConfigFileApplicationListener.DEFAULT_ORDER + 1;
}

View File

@ -34,10 +34,11 @@ import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.bind.PropertySourcesPropertyValues;
import org.springframework.boot.bind.RelaxedDataBinder;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.bind.PropertySourcesPlaceholdersResolver;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.boot.env.EnumerableCompositePropertySource;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.env.PropertySourcesLoader;
@ -90,6 +91,7 @@ import org.springframework.util.StringUtils;
* @author Stephane Nicoll
* @author Andy Wilkinson
* @author Eddú Meléndez
* @author Madhura Bhave
*/
public class ConfigFileApplicationListener implements EnvironmentPostProcessor,
ApplicationListener<ApplicationEvent>, Ordered {
@ -256,8 +258,7 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor,
}
private void reorderSources(ConfigurableEnvironment environment) {
ConfigurationPropertySources
.finishAndRelocate(environment.getPropertySources());
LoadedPropertySources.finishAndRelocate(environment.getPropertySources());
PropertySource<?> defaultProperties = environment.getPropertySources()
.remove(DEFAULT_PROPERTIES);
if (defaultProperties != null) {
@ -344,11 +345,11 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor,
}
// Any pre-existing active profiles set via property sources (e.g. System
// properties) take precedence over those added in config files.
SpringProfiles springProfiles = bindSpringProfiles(
this.environment.getPropertySources());
Set<Profile> activeProfiles = new LinkedHashSet<>(
springProfiles.getActiveProfiles());
activeProfiles.addAll(springProfiles.getIncludeProfiles());
Set<Profile> active = getProfiles(this.environment, "spring.profiles.active");
Set<Profile> activeProfiles = new LinkedHashSet<>(active);
Set<Profile> include = getProfiles(this.environment,
"spring.profiles.include");
activeProfiles.addAll(include);
maybeActivateProfiles(activeProfiles);
return activeProfiles;
}
@ -474,33 +475,34 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor,
}
private void handleProfileProperties(PropertySource<?> propertySource) {
SpringProfiles springProfiles = bindSpringProfiles(propertySource);
maybeActivateProfiles(springProfiles.getActiveProfiles());
addProfiles(springProfiles.getIncludeProfiles());
}
private SpringProfiles bindSpringProfiles(PropertySource<?> propertySource) {
MutablePropertySources propertySources = new MutablePropertySources();
propertySources.addFirst(propertySource);
return bindSpringProfiles(propertySources);
Set<Profile> active = getProfiles(propertySources, "spring.profiles.active");
Set<Profile> include = getProfiles(propertySources,
"spring.profiles.include");
maybeActivateProfiles(active);
addProfiles(include);
}
private SpringProfiles bindSpringProfiles(PropertySources propertySources) {
SpringProfiles springProfiles = new SpringProfiles();
RelaxedDataBinder dataBinder = new RelaxedDataBinder(springProfiles,
"spring.profiles");
dataBinder.bind(new PropertySourcesPropertyValues(propertySources, false));
springProfiles.setActive(resolvePlaceholders(springProfiles.getActive()));
springProfiles.setInclude(resolvePlaceholders(springProfiles.getInclude()));
return springProfiles;
private Set<Profile> getProfiles(ConfigurableEnvironment environment,
String name) {
return getProfiles(environment.getPropertySources(), name);
}
private List<String> resolvePlaceholders(List<String> values) {
List<String> resolved = new ArrayList<>();
for (String value : values) {
resolved.add(this.environment.resolvePlaceholders(value));
private Set<Profile> getProfiles(PropertySources sources, String name) {
Binder binder = new Binder(ConfigurationPropertySources.get(sources),
new PropertySourcesPlaceholdersResolver(this.environment));
return binder.bind(name, String[].class).map(this::asProfileSet)
.orElse(Collections.emptySet());
}
return resolved;
private Set<Profile> asProfileSet(String[] profileNames) {
List<Profile> profiles = new ArrayList<>();
for (String profileName : profileNames) {
profiles.add(new Profile(profileName));
}
Collections.reverse(profiles);
return new LinkedHashSet<>(profiles);
}
private void maybeActivateProfiles(Set<Profile> profiles) {
@ -601,19 +603,17 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor,
for (PropertySource<?> item : sources) {
reorderedSources.add(item);
}
addConfigurationProperties(
new ConfigurationPropertySources(reorderedSources));
addConfigurationProperties(new LoadedPropertySources(reorderedSources));
}
private void addConfigurationProperties(
ConfigurationPropertySources configurationSources) {
private void addConfigurationProperties(LoadedPropertySources loadedSources) {
MutablePropertySources existingSources = this.environment
.getPropertySources();
if (existingSources.contains(DEFAULT_PROPERTIES)) {
existingSources.addBefore(DEFAULT_PROPERTIES, configurationSources);
existingSources.addBefore(DEFAULT_PROPERTIES, loadedSources);
}
else {
existingSources.addLast(configurationSources);
existingSources.addLast(loadedSources);
}
}
@ -670,14 +670,14 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor,
* Holds the configuration {@link PropertySource}s as they are loaded can relocate
* them once configuration classes have been processed.
*/
static class ConfigurationPropertySources
static class LoadedPropertySources
extends EnumerablePropertySource<Collection<PropertySource<?>>> {
private final Collection<PropertySource<?>> sources;
private final String[] names;
ConfigurationPropertySources(Collection<PropertySource<?>> sources) {
LoadedPropertySources(Collection<PropertySource<?>> sources) {
super(APPLICATION_CONFIGURATION_PROPERTY_SOURCE_NAME, sources);
this.sources = sources;
List<String> names = new ArrayList<>();
@ -703,7 +703,7 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor,
public static void finishAndRelocate(MutablePropertySources propertySources) {
String name = APPLICATION_CONFIGURATION_PROPERTY_SOURCE_NAME;
ConfigurationPropertySources removed = (ConfigurationPropertySources) propertySources
LoadedPropertySources removed = (LoadedPropertySources) propertySources
.get(name);
if (removed != null) {
for (PropertySource<?> propertySource : removed.sources) {
@ -729,48 +729,4 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor,
}
/**
* Holder for {@code spring.profiles} properties.
*/
static final class SpringProfiles {
private List<String> active = new ArrayList<>();
private List<String> include = new ArrayList<>();
public List<String> getActive() {
return this.active;
}
public void setActive(List<String> active) {
this.active = active;
}
public List<String> getInclude() {
return this.include;
}
public void setInclude(List<String> include) {
this.include = include;
}
Set<Profile> getActiveProfiles() {
return asProfileSet(this.active);
}
Set<Profile> getIncludeProfiles() {
return asProfileSet(this.include);
}
private Set<Profile> asProfileSet(List<String> profileNames) {
List<Profile> profiles = new ArrayList<>();
for (String profileName : profileNames) {
profiles.add(new Profile(profileName));
}
Collections.reverse(profiles);
return new LinkedHashSet<>(profiles);
}
}
}

View File

@ -16,9 +16,9 @@
package org.springframework.boot.context.logging;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.commons.logging.Log;
@ -26,11 +26,12 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.event.ApplicationFailedEvent;
import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.boot.context.event.ApplicationStartingEvent;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.logging.LogFile;
import org.springframework.boot.logging.LogLevel;
import org.springframework.boot.logging.LoggingInitializationContext;
@ -77,11 +78,15 @@ import org.springframework.util.StringUtils;
* @author Dave Syer
* @author Phillip Webb
* @author Andy Wilkinson
* @author Madhura Bhave
* @since 2.0.0
* @see LoggingSystem#get(ClassLoader)
*/
public class LoggingApplicationListener implements GenericApplicationListener {
private static final Bindable<Map<String, String>> STRING_STRING_MAP = Bindable
.mapOf(String.class, String.class);
/**
* The default order for the LoggingApplicationListener.
*/
@ -294,20 +299,18 @@ public class LoggingApplicationListener implements GenericApplicationListener {
}
protected void setLogLevels(LoggingSystem system, Environment environment) {
Map<String, Object> levels = new RelaxedPropertyResolver(environment)
.getSubProperties("logging.level.");
for (Entry<String, Object> entry : levels.entrySet()) {
setLogLevel(system, environment, entry.getKey(), entry.getValue().toString());
if (!(environment instanceof ConfigurableEnvironment)) {
return;
}
Binder binder = Binder.get(environment);
binder.bind("logging.level", STRING_STRING_MAP).orElseGet(Collections::emptyMap)
.forEach((name, level) -> setLogLevel(system, environment, name, level));
}
private void setLogLevel(LoggingSystem system, Environment environment, String name,
String level) {
try {
if (name.equalsIgnoreCase(LoggingSystem.ROOT_LOGGER_NAME)) {
name = null;
}
level = environment.resolvePlaceholders(level);
name = (name.equalsIgnoreCase(LoggingSystem.ROOT_LOGGER_NAME) ? null : name);
system.setLogLevel(name, coerceLogLevel(level));
}
catch (RuntimeException ex) {
@ -324,7 +327,7 @@ public class LoggingApplicationListener implements GenericApplicationListener {
private void registerShutdownHookIfNecessary(Environment environment,
LoggingSystem loggingSystem) {
boolean registerShutdownHook = new RelaxedPropertyResolver(environment)
boolean registerShutdownHook = environment
.getProperty(REGISTER_SHUTDOWN_HOOK_PROPERTY, Boolean.class, false);
if (registerShutdownHook) {
Runnable shutdownHandler = loggingSystem.getShutdownHandler();

View File

@ -17,7 +17,6 @@
package org.springframework.boot.context.properties;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@ -34,7 +33,15 @@ import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.bind.PropertiesConfigurationFactory;
import org.springframework.boot.context.properties.bind.BindHandler;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.bind.PropertySourcesPlaceholdersResolver;
import org.springframework.boot.context.properties.bind.handler.IgnoreErrorsBindHandler;
import org.springframework.boot.context.properties.bind.handler.IgnoreNestedPropertiesBindHandler;
import org.springframework.boot.context.properties.bind.handler.NoUnboundElementsBindHandler;
import org.springframework.boot.context.properties.bind.validation.ValidationBindHandler;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.boot.validation.MessageInterpolatorFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@ -53,13 +60,10 @@ import org.springframework.core.convert.converter.GenericConverter;
import org.springframework.core.convert.support.DefaultConversionService;
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.core.env.StandardEnvironment;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import org.springframework.validation.annotation.Validated;
@ -73,6 +77,7 @@ import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
* @author Phillip Webb
* @author Christian Dupuis
* @author Stephane Nicoll
* @author Madhura Bhave
*/
public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProcessor,
BeanFactoryAware, EnvironmentAware, ApplicationContextAware, InitializingBean,
@ -113,6 +118,10 @@ public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProc
private int order = Ordered.HIGHEST_PRECEDENCE + 1;
private ConfigurationPropertySources configurationSources;
private Binder binder;
/**
* A list of custom converters (in addition to the defaults) to use when converting
* properties for binding.
@ -212,6 +221,8 @@ public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProc
ConfigurableApplicationContext.CONVERSION_SERVICE_BEAN_NAME,
ConversionService.class);
}
this.configurationSources = ConfigurationPropertySources
.get(this.propertySources);
}
@Override
@ -240,18 +251,13 @@ public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProc
private PropertySources deducePropertySources() {
PropertySourcesPlaceholderConfigurer configurer = getSinglePropertySourcesPlaceholderConfigurer();
if (configurer != null) {
// Flatten the sources into a single list so they can be iterated
return new FlatPropertySources(configurer.getAppliedPropertySources());
return configurer.getAppliedPropertySources();
}
if (this.environment instanceof ConfigurableEnvironment) {
MutablePropertySources propertySources = ((ConfigurableEnvironment) this.environment)
.getPropertySources();
return new FlatPropertySources(propertySources);
return ((ConfigurableEnvironment) this.environment).getPropertySources();
}
// empty, so not very useful, but fulfils the contract
logger.warn("Unable to obtain PropertySources from "
throw new IllegalStateException("Unable to obtain PropertySources from "
+ "PropertySourcesPlaceholderConfigurer or Environment");
return new MutablePropertySources();
}
private PropertySourcesPlaceholderConfigurer getSinglePropertySourcesPlaceholderConfigurer() {
@ -287,15 +293,16 @@ public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProc
throws BeansException {
ConfigurationProperties annotation = AnnotationUtils
.findAnnotation(bean.getClass(), ConfigurationProperties.class);
Object bound = bean;
if (annotation != null) {
postProcessBeforeInitialization(bean, beanName, annotation);
bound = postProcessBeforeInitialization(bean, beanName, annotation);
}
annotation = this.beans.findFactoryAnnotation(beanName,
ConfigurationProperties.class);
if (annotation != null) {
postProcessBeforeInitialization(bean, beanName, annotation);
bound = postProcessBeforeInitialization(bean, beanName, annotation);
}
return bean;
return bound;
}
@Override
@ -304,35 +311,53 @@ public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProc
return bean;
}
private void postProcessBeforeInitialization(Object bean, String beanName,
private Object postProcessBeforeInitialization(Object bean, String beanName,
ConfigurationProperties annotation) {
Object target = bean;
PropertiesConfigurationFactory<Object> factory = new PropertiesConfigurationFactory<>(
target);
factory.setPropertySources(this.propertySources);
factory.setValidator(determineValidator(bean));
// If no explicit conversion service is provided we add one so that (at least)
// comma-separated arrays of convertibles can be bound automatically
factory.setConversionService(this.conversionService == null
? getDefaultConversionService() : this.conversionService);
if (annotation != null) {
factory.setIgnoreInvalidFields(annotation.ignoreInvalidFields());
factory.setIgnoreUnknownFields(annotation.ignoreUnknownFields());
factory.setIgnoreNestedProperties(annotation.ignoreNestedProperties());
if (StringUtils.hasLength(annotation.prefix())) {
factory.setTargetName(annotation.prefix());
}
}
Binder binder = getBinder();
Validator validator = determineValidator(bean);
BindHandler handler = getBindHandler(annotation, validator);
Bindable<?> bindable = Bindable.ofInstance(bean);
try {
factory.bindPropertiesToTarget();
binder.bind(annotation.prefix(), bindable, handler);
return bean;
}
catch (Exception ex) {
String targetClass = ClassUtils.getShortName(target.getClass());
String targetClass = ClassUtils.getShortName(bean.getClass());
throw new BeanCreationException(beanName, "Could not bind properties to "
+ targetClass + " (" + getAnnotationDetails(annotation) + ")", ex);
}
}
private Binder getBinder() {
Binder binder = this.binder;
if (binder == null) {
ConversionService conversionService = this.conversionService;
if (conversionService == null) {
conversionService = getDefaultConversionService();
}
binder = new Binder(this.configurationSources,
new PropertySourcesPlaceholdersResolver(this.propertySources),
conversionService);
this.binder = binder;
}
return binder;
}
private ConversionService getDefaultConversionService() {
if (this.defaultConversionService == null) {
DefaultConversionService conversionService = new DefaultConversionService();
this.applicationContext.getAutowireCapableBeanFactory().autowireBean(this);
for (Converter<?, ?> converter : this.converters) {
conversionService.addConverter(converter);
}
for (GenericConverter genericConverter : this.genericConverters) {
conversionService.addConverter(genericConverter);
}
this.defaultConversionService = conversionService;
}
return this.defaultConversionService;
}
private String getAnnotationDetails(ConfigurationProperties annotation) {
if (annotation == null) {
return "";
@ -379,19 +404,22 @@ public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProc
return true;
}
private ConversionService getDefaultConversionService() {
if (this.defaultConversionService == null) {
DefaultConversionService conversionService = new DefaultConversionService();
this.applicationContext.getAutowireCapableBeanFactory().autowireBean(this);
for (Converter<?, ?> converter : this.converters) {
conversionService.addConverter(converter);
private BindHandler getBindHandler(ConfigurationProperties annotation,
Validator validator) {
BindHandler handler = BindHandler.DEFAULT;
if (annotation.ignoreInvalidFields()) {
handler = new IgnoreErrorsBindHandler(handler);
}
for (GenericConverter genericConverter : this.genericConverters) {
conversionService.addConverter(genericConverter);
if (!annotation.ignoreUnknownFields()) {
handler = new NoUnboundElementsBindHandler(handler);
}
this.defaultConversionService = conversionService;
if (annotation.ignoreNestedProperties()) {
handler = new IgnoreNestedPropertiesBindHandler(handler);
}
return this.defaultConversionService;
if (validator != null) {
handler = new ValidationBindHandler(handler, validator);
}
return handler;
}
/**
@ -465,56 +493,4 @@ public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProc
}
/**
* Convenience class to flatten out a tree of property sources without losing the
* reference to the backing data (which can therefore be updated in the background).
*/
private static class FlatPropertySources implements PropertySources {
private PropertySources propertySources;
FlatPropertySources(PropertySources propertySources) {
this.propertySources = propertySources;
}
@Override
public Iterator<PropertySource<?>> iterator() {
MutablePropertySources result = getFlattened();
return result.iterator();
}
@Override
public boolean contains(String name) {
return get(name) != null;
}
@Override
public PropertySource<?> get(String name) {
return getFlattened().get(name);
}
private MutablePropertySources getFlattened() {
MutablePropertySources result = new MutablePropertySources();
for (PropertySource<?> propertySource : this.propertySources) {
flattenPropertySources(propertySource, result);
}
return result;
}
private void flattenPropertySources(PropertySource<?> propertySource,
MutablePropertySources result) {
Object source = propertySource.getSource();
if (source instanceof ConfigurableEnvironment) {
ConfigurableEnvironment environment = (ConfigurableEnvironment) source;
for (PropertySource<?> childSource : environment.getPropertySources()) {
flattenPropertySources(childSource, result);
}
}
else {
result.addLast(propertySource);
}
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2013 the original author or authors.
* Copyright 2012-2017 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.

View File

@ -45,6 +45,7 @@ import org.springframework.util.StringUtils;
* @author Christian Dupuis
* @author Stephane Nicoll
*/
@Deprecated
class EnableConfigurationPropertiesImportSelector implements ImportSelector {
@Override

View File

@ -0,0 +1,73 @@
/*
* Copyright 2012-2017 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.context.properties.bind;
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
import org.springframework.util.Assert;
/**
* Abstract base class for {@link BindHandler} implementations.
*
* @author Phillip Webb
* @author Madhura Bhave
* @since 2.0.0
*/
public abstract class AbstractBindHandler implements BindHandler {
private final BindHandler parent;
/**
* Create a new binding handler instance.
*/
public AbstractBindHandler() {
this(BindHandler.DEFAULT);
}
/**
* Create a new binding handler instance with a specific parent.
* @param parent the parent handler
*/
public AbstractBindHandler(BindHandler parent) {
Assert.notNull(parent, "Parent must not be null");
this.parent = parent;
}
@Override
public boolean onStart(ConfigurationPropertyName name, Bindable<?> target,
BindContext context) {
return this.parent.onStart(name, target, context);
}
@Override
public Object onSuccess(ConfigurationPropertyName name, Bindable<?> target,
BindContext context, Object result) {
return this.parent.onSuccess(name, target, context, result);
}
@Override
public Object onFailure(ConfigurationPropertyName name, Bindable<?> target,
BindContext context, Exception error) throws Exception {
return this.parent.onFailure(name, target, context, error);
}
@Override
public void onFinish(ConfigurationPropertyName name, Bindable<?> target,
BindContext context, Object result) throws Exception {
this.parent.onFinish(name, target, context, result);
}
}

Some files were not shown because too many files have changed in this diff Show More