Rework ConfigurationPropertySources
Rework the ConfigurationPropertySources and related adapter classes to help with performance. The ConfigurationPropertySources class now only monitors for updates when `.attach` is used. The `.get` methods now return the adapted version, but no longer checks to see if sources have been added or removed on each call. This commit also fixes a few caching issues and makes both the `PropertyMapper` implementations true static singletons. See gh-9000
This commit is contained in:
parent
133f11df2f
commit
fa4de13519
|
@ -25,7 +25,6 @@ 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;
|
||||
|
||||
|
@ -93,9 +92,7 @@ public abstract class InfoPropertiesInfoContributor<T extends InfoProperties>
|
|||
* @return the raw content
|
||||
*/
|
||||
protected Map<String, Object> extractContent(PropertySource<?> propertySource) {
|
||||
MutablePropertySources sources = new MutablePropertySources();
|
||||
sources.addFirst(propertySource);
|
||||
return new Binder(ConfigurationPropertySources.get(sources))
|
||||
return new Binder(ConfigurationPropertySources.from(propertySource))
|
||||
.bind("", STRING_OBJECT_MAP).orElseGet(LinkedHashMap::new);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import java.util.Collection;
|
|||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
|
@ -320,9 +321,8 @@ public class EndpointAutoConfigurationTests {
|
|||
if (!location.exists()) {
|
||||
return;
|
||||
}
|
||||
MapConfigurationPropertySource source = new MapConfigurationPropertySource(
|
||||
PropertiesLoaderUtils.loadProperties(location));
|
||||
new Binder(source).bind("info",
|
||||
Properties properties = PropertiesLoaderUtils.loadProperties(location);
|
||||
new Binder(new MapConfigurationPropertySource(properties)).bind("info",
|
||||
Bindable.of(STRING_OBJECT_MAP).withExistingValue(this.content));
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.springframework.boot.SpringApplication;
|
|||
import org.springframework.boot.WebApplicationType;
|
||||
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.mock.web.SpringBootMockServletContext;
|
||||
import org.springframework.boot.test.util.EnvironmentTestUtils;
|
||||
|
@ -173,7 +174,7 @@ public class SpringBootContextLoader extends AbstractContextLoader {
|
|||
return binder.bind("server.port", Bindable.of(String.class)).isBound();
|
||||
}
|
||||
|
||||
private MapConfigurationPropertySource convertToConfigurationPropertySource(
|
||||
private ConfigurationPropertySource convertToConfigurationPropertySource(
|
||||
List<String> properties) {
|
||||
String[] array = properties.toArray(new String[properties.size()]);
|
||||
return new MapConfigurationPropertySource(
|
||||
|
|
|
@ -480,9 +480,7 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor,
|
|||
}
|
||||
|
||||
private void handleProfileProperties(PropertySource<?> propertySource) {
|
||||
MutablePropertySources propertySources = new MutablePropertySources();
|
||||
propertySources.addFirst(propertySource);
|
||||
Binder binder = new Binder(ConfigurationPropertySources.get(propertySources),
|
||||
Binder binder = new Binder(ConfigurationPropertySources.from(propertySource),
|
||||
new PropertySourcesPlaceholdersResolver(this.environment));
|
||||
Set<Profile> active = getProfiles(binder, "spring.profiles.active");
|
||||
Set<Profile> include = getProfiles(binder, "spring.profiles.include");
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.springframework.boot.context.properties.bind.PropertySourcesPlacehold
|
|||
import org.springframework.boot.context.properties.bind.handler.IgnoreErrorsBindHandler;
|
||||
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.ConfigurationPropertySource;
|
||||
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
|
||||
import org.springframework.boot.validation.MessageInterpolatorFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
@ -59,6 +60,7 @@ 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.PropertySource;
|
||||
import org.springframework.core.env.PropertySources;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.util.Assert;
|
||||
|
@ -95,7 +97,7 @@ public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProc
|
|||
|
||||
private ConfigurationBeanFactoryMetaData beans = new ConfigurationBeanFactoryMetaData();
|
||||
|
||||
private PropertySources propertySources;
|
||||
private Iterable<PropertySource<?>> propertySources;
|
||||
|
||||
private Validator validator;
|
||||
|
||||
|
@ -117,7 +119,7 @@ public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProc
|
|||
|
||||
private int order = Ordered.HIGHEST_PRECEDENCE + 1;
|
||||
|
||||
private ConfigurationPropertySources configurationSources;
|
||||
private Iterable<ConfigurationPropertySource> configurationSources;
|
||||
|
||||
private Binder binder;
|
||||
|
||||
|
@ -164,7 +166,7 @@ public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProc
|
|||
* Set the property sources to bind.
|
||||
* @param propertySources the property sources
|
||||
*/
|
||||
public void setPropertySources(PropertySources propertySources) {
|
||||
public void setPropertySources(Iterable<PropertySource<?>> propertySources) {
|
||||
this.propertySources = propertySources;
|
||||
}
|
||||
|
||||
|
@ -221,7 +223,7 @@ public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProc
|
|||
ConversionService.class);
|
||||
}
|
||||
this.configurationSources = ConfigurationPropertySources
|
||||
.get(this.propertySources);
|
||||
.from(this.propertySources);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -37,7 +37,6 @@ import org.springframework.boot.context.properties.source.ConfigurationPropertyN
|
|||
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
|
||||
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||
import org.springframework.util.Assert;
|
||||
|
@ -331,13 +330,12 @@ public class Binder {
|
|||
|
||||
/**
|
||||
* Create a new {@link Binder} instance from the specified environment.
|
||||
* @param environment the environment (must be a {@link ConfigurableEnvironment})
|
||||
* @param environment the environment source (must have attached
|
||||
* {@link ConfigurationPropertySources})
|
||||
* @return a {@link Binder} instance
|
||||
*/
|
||||
public static Binder get(Environment environment) {
|
||||
Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
|
||||
return new Binder(
|
||||
ConfigurationPropertySources.get((ConfigurableEnvironment) environment),
|
||||
return new Binder(ConfigurationPropertySources.get(environment),
|
||||
new PropertySourcesPlaceholdersResolver(environment));
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ import org.springframework.util.SystemPropertyUtils;
|
|||
*/
|
||||
public class PropertySourcesPlaceholdersResolver implements PlaceholdersResolver {
|
||||
|
||||
private final PropertySources sources;
|
||||
private final Iterable<PropertySource<?>> sources;
|
||||
|
||||
private final PropertyPlaceholderHelper helper;
|
||||
|
||||
|
@ -41,11 +41,11 @@ public class PropertySourcesPlaceholdersResolver implements PlaceholdersResolver
|
|||
this(getSources(environment), null);
|
||||
}
|
||||
|
||||
public PropertySourcesPlaceholdersResolver(PropertySources sources) {
|
||||
public PropertySourcesPlaceholdersResolver(Iterable<PropertySource<?>> sources) {
|
||||
this(sources, null);
|
||||
}
|
||||
|
||||
public PropertySourcesPlaceholdersResolver(PropertySources sources,
|
||||
public PropertySourcesPlaceholdersResolver(Iterable<PropertySource<?>> sources,
|
||||
PropertyPlaceholderHelper helper) {
|
||||
this.sources = sources;
|
||||
this.helper = (helper != null ? helper
|
||||
|
|
|
@ -16,72 +16,115 @@
|
|||
|
||||
package org.springframework.boot.context.properties.source;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.function.Function;
|
||||
import java.util.Collections;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.springframework.boot.env.RandomValuePropertySource;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.EnumerablePropertySource;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.MutablePropertySources;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.env.PropertySource.StubPropertySource;
|
||||
import org.springframework.core.env.PropertySources;
|
||||
import org.springframework.core.env.PropertySourcesPropertyResolver;
|
||||
import org.springframework.core.env.SystemEnvironmentPropertySource;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A managed set of {@link ConfigurationPropertySource} instances, usually adapted from
|
||||
* Spring's {@link PropertySources}.
|
||||
* Provides access to {@link ConfigurationPropertySource ConfigurationPropertySources}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Madhura Bhave
|
||||
* @since 2.0.0
|
||||
* @see #attach(MutablePropertySources)
|
||||
* @see #get(PropertySources)
|
||||
*/
|
||||
public class ConfigurationPropertySources
|
||||
implements Iterable<ConfigurationPropertySource> {
|
||||
|
||||
private static final ConfigurationPropertyName RANDOM = ConfigurationPropertyName
|
||||
.of("random");
|
||||
public final class ConfigurationPropertySources {
|
||||
|
||||
/**
|
||||
* The name of the {@link PropertySource} {@link #adapt adapter}.
|
||||
*/
|
||||
public static final String PROPERTY_SOURCE_NAME = "configurationProperties";
|
||||
private static final String ATTACHED_PROPERTY_SOURCE_NAME = "configurationProperties";
|
||||
|
||||
private final PropertySources propertySources;
|
||||
|
||||
private final Map<PropertySource<?>, ConfigurationPropertySource> adapters = new WeakHashMap<>();
|
||||
private ConfigurationPropertySources() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link ConfigurationPropertySources} instance.
|
||||
* @param propertySources the property sources to expose
|
||||
* Attach a {@link ConfigurationPropertySource} support to the specified
|
||||
* {@link Environment}. Adapts each {@link PropertySource} managed by the environment
|
||||
* to a {@link ConfigurationPropertySource} and allows classic
|
||||
* {@link PropertySourcesPropertyResolver} calls to resolve using
|
||||
* {@link ConfigurationPropertyName configuration property names}.
|
||||
* <p>
|
||||
* The attached resolver will dynamically track any additions or removals from the
|
||||
* underlying {@link Environment} property sources.
|
||||
* @param environment the source environment (must be an instance of
|
||||
* {@link ConfigurableEnvironment})
|
||||
* @see #get(Environment)
|
||||
*/
|
||||
ConfigurationPropertySources(PropertySources propertySources) {
|
||||
Assert.notNull(propertySources, "PropertySources must not be null");
|
||||
this.propertySources = propertySources;
|
||||
public static void attach(Environment environment) {
|
||||
Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
|
||||
MutablePropertySources sources = ((ConfigurableEnvironment) environment)
|
||||
.getPropertySources();
|
||||
if (!sources.contains(ATTACHED_PROPERTY_SOURCE_NAME)) {
|
||||
sources.addFirst(new ConfigurationPropertySourcesPropertySource(
|
||||
ATTACHED_PROPERTY_SOURCE_NAME,
|
||||
new SpringConfigurationPropertySources(sources)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<ConfigurationPropertySource> iterator() {
|
||||
return streamPropertySources(this.propertySources)
|
||||
.filter(s -> !(s instanceof ConfigurationPropertySourcesPropertySource))
|
||||
.map(this::adapt).iterator();
|
||||
/**
|
||||
* Return a set of {@link ConfigurationPropertySource} instances that have previously
|
||||
* been {@link #attach(Environment) attached} to the {@link Environment}.
|
||||
* @param environment the source environment (must be an instance of
|
||||
* {@link ConfigurableEnvironment})
|
||||
* @return an iterable set of configuration property sources
|
||||
* @throws IllegalStateException if not configuration property sources have been
|
||||
* attached
|
||||
*/
|
||||
public static Iterable<ConfigurationPropertySource> get(Environment environment) {
|
||||
Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
|
||||
MutablePropertySources sources = ((ConfigurableEnvironment) environment)
|
||||
.getPropertySources();
|
||||
ConfigurationPropertySourcesPropertySource attached = (ConfigurationPropertySourcesPropertySource) sources
|
||||
.get(ATTACHED_PROPERTY_SOURCE_NAME);
|
||||
if (attached == null) {
|
||||
return from(sources);
|
||||
}
|
||||
return attached.getSource();
|
||||
}
|
||||
|
||||
private Stream<PropertySource<?>> streamPropertySources(PropertySources sources) {
|
||||
return StreamSupport.stream(sources.spliterator(), false).flatMap(this::flatten)
|
||||
.filter(this::notStubSource);
|
||||
/**
|
||||
* Return {@link Iterable} containing a single new {@link ConfigurationPropertySource}
|
||||
* adapted from the given Spring {@link PropertySource}.
|
||||
* @param source the Spring property source to adapt
|
||||
* @return an {@link Iterable} containing a single newly adapted
|
||||
* {@link SpringConfigurationPropertySource}
|
||||
*/
|
||||
public static Iterable<ConfigurationPropertySource> from(PropertySource<?> source) {
|
||||
return Collections.singleton(SpringConfigurationPropertySource.from(source));
|
||||
}
|
||||
|
||||
private Stream<PropertySource<?>> flatten(PropertySource<?> source) {
|
||||
/**
|
||||
* Return {@link Iterable} containing new {@link ConfigurationPropertySource}
|
||||
* instances adapted from the given Spring {@link PropertySource PropertySources}.
|
||||
* <p>
|
||||
* This method will flatten any nested property sources and will filter all
|
||||
* {@link StubPropertySource stub property sources}.
|
||||
* @param sources the Spring property sources to adapt
|
||||
* @return an {@link Iterable} containing a single newly adapted
|
||||
* {@link SpringConfigurationPropertySource} instances
|
||||
*/
|
||||
public static Iterable<ConfigurationPropertySource> from(
|
||||
Iterable<PropertySource<?>> sources) {
|
||||
return streamPropertySources(sources).map(SpringConfigurationPropertySource::from)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static Stream<PropertySource<?>> streamPropertySources(
|
||||
Iterable<PropertySource<?>> sources) {
|
||||
return StreamSupport.stream(sources.spliterator(), false)
|
||||
.flatMap(ConfigurationPropertySources::flatten)
|
||||
.filter(ConfigurationPropertySources::isIncluded);
|
||||
}
|
||||
|
||||
private static Stream<PropertySource<?>> flatten(PropertySource<?> source) {
|
||||
if (source.getSource() instanceof ConfigurableEnvironment) {
|
||||
return streamPropertySources(
|
||||
((ConfigurableEnvironment) source.getSource()).getPropertySources());
|
||||
|
@ -89,124 +132,9 @@ public class ConfigurationPropertySources
|
|||
return Stream.of(source);
|
||||
}
|
||||
|
||||
private boolean notStubSource(PropertySource<?> source) {
|
||||
return !(source instanceof StubPropertySource);
|
||||
}
|
||||
|
||||
private ConfigurationPropertySource adapt(PropertySource<?> source) {
|
||||
return this.adapters.computeIfAbsent(source, this::createAdapter);
|
||||
}
|
||||
|
||||
private ConfigurationPropertySource createAdapter(PropertySource<?> source) {
|
||||
PropertyMapper mapper = getPropertyMapper(source);
|
||||
if (isFullEnumerable(source)) {
|
||||
return new PropertySourceIterableConfigurationPropertySource(
|
||||
(EnumerablePropertySource<?>) source, mapper);
|
||||
}
|
||||
return new PropertySourceConfigurationPropertySource(source, mapper,
|
||||
getContainsDescendantOfMethod(source));
|
||||
}
|
||||
|
||||
private PropertyMapper getPropertyMapper(PropertySource<?> source) {
|
||||
if (source instanceof SystemEnvironmentPropertySource) {
|
||||
return SystemEnvironmentPropertyMapper.INSTANCE;
|
||||
}
|
||||
return DefaultPropertyMapper.INSTANCE;
|
||||
}
|
||||
|
||||
private boolean isFullEnumerable(PropertySource<?> source) {
|
||||
PropertySource<?> rootSource = getRootSource(source);
|
||||
if (rootSource.getSource() instanceof Map) {
|
||||
// Check we're not security restricted
|
||||
try {
|
||||
((Map<?, ?>) rootSource.getSource()).size();
|
||||
}
|
||||
catch (UnsupportedOperationException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return (source instanceof EnumerablePropertySource);
|
||||
}
|
||||
|
||||
private PropertySource<?> getRootSource(PropertySource<?> source) {
|
||||
while (source.getSource() != null
|
||||
&& source.getSource() instanceof PropertySource) {
|
||||
source = (PropertySource<?>) source.getSource();
|
||||
}
|
||||
return source;
|
||||
}
|
||||
|
||||
private Function<ConfigurationPropertyName, Optional<Boolean>> getContainsDescendantOfMethod(
|
||||
PropertySource<?> source) {
|
||||
if (source instanceof RandomValuePropertySource) {
|
||||
return (name) -> Optional
|
||||
.of(name.isAncestorOf(RANDOM) || name.equals(RANDOM));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach a {@link ConfigurationPropertySources} instance to the specified
|
||||
* {@link ConfigurableEnvironment} so that classic
|
||||
* {@link PropertySourcesPropertyResolver} calls will resolve using
|
||||
* {@link ConfigurationPropertyName configuration property names}.
|
||||
* @param environment the source environment
|
||||
* @return the instance attached
|
||||
*/
|
||||
public static ConfigurationPropertySources attach(
|
||||
ConfigurableEnvironment environment) {
|
||||
return attach(environment.getPropertySources());
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach a {@link ConfigurationPropertySources} instance to the specified
|
||||
* {@link PropertySources} so that classic {@link PropertySourcesPropertyResolver}
|
||||
* calls will resolve using using {@link ConfigurationPropertyName configuration
|
||||
* property names}.
|
||||
* @param propertySources the source property sources
|
||||
* @return the instance attached
|
||||
*/
|
||||
public static ConfigurationPropertySources attach(
|
||||
MutablePropertySources propertySources) {
|
||||
ConfigurationPropertySources adapted = new ConfigurationPropertySources(
|
||||
propertySources);
|
||||
propertySources.addFirst(new ConfigurationPropertySourcesPropertySource(
|
||||
PROPERTY_SOURCE_NAME, adapted));
|
||||
return adapted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a {@link ConfigurationPropertySources} instance for the specified
|
||||
* {@link PropertySources} (either previously {@link #attach(MutablePropertySources)
|
||||
* attached} or a new instance.
|
||||
* @param propertySources the source property sources
|
||||
* @return a {@link ConfigurationPropertySources} instance
|
||||
*/
|
||||
public static ConfigurationPropertySources get(PropertySources propertySources) {
|
||||
if (propertySources == null) {
|
||||
return null;
|
||||
}
|
||||
PropertySource<?> source = propertySources.get(PROPERTY_SOURCE_NAME);
|
||||
if (source != null) {
|
||||
return (ConfigurationPropertySources) source.getSource();
|
||||
}
|
||||
return new ConfigurationPropertySources(propertySources);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a {@link ConfigurationPropertySources} instance for the {@link PropertySources}
|
||||
* from the specified {@link ConfigurableEnvironment}, (either previously
|
||||
* {@link #attach(MutablePropertySources) attached} or a new instance.
|
||||
* @param environment the configurable environment
|
||||
* @return a {@link ConfigurationPropertySources} instance
|
||||
*/
|
||||
public static ConfigurationPropertySources get(ConfigurableEnvironment environment) {
|
||||
MutablePropertySources propertySources = environment.getPropertySources();
|
||||
PropertySource<?> source = propertySources.get(PROPERTY_SOURCE_NAME);
|
||||
if (source != null) {
|
||||
return (ConfigurationPropertySources) source.getSource();
|
||||
}
|
||||
return new ConfigurationPropertySources(propertySources);
|
||||
private static boolean isIncluded(PropertySource<?> source) {
|
||||
return !(source instanceof StubPropertySource)
|
||||
&& !(source instanceof ConfigurationPropertySourcesPropertySource);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,10 +16,6 @@
|
|||
|
||||
package org.springframework.boot.context.properties.source;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.springframework.boot.origin.Origin;
|
||||
import org.springframework.boot.origin.OriginLookup;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
@ -70,10 +66,14 @@ class ConfigurationPropertySourcesPropertySource
|
|||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
Stream<ConfigurationPropertySource> sources = StreamSupport
|
||||
.stream(getSource().spliterator(), false);
|
||||
return sources.map(source -> source.getConfigurationProperty(name))
|
||||
.filter(Objects::nonNull).findFirst().orElse(null);
|
||||
for (ConfigurationPropertySource configurationPropertySource : getSource()) {
|
||||
ConfigurationProperty configurationProperty = configurationPropertySource
|
||||
.getConfigurationProperty(name);
|
||||
if (configurationProperty != null) {
|
||||
return configurationProperty;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,11 +17,10 @@
|
|||
package org.springframework.boot.context.properties.source;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Default {@link PropertyMapper} implementation. Names are mapped by removing invalid
|
||||
|
@ -31,36 +30,48 @@ import org.springframework.core.env.PropertySource;
|
|||
* @author Phillip Webb
|
||||
* @author Madhura Bhave
|
||||
* @see PropertyMapper
|
||||
* @see PropertySourceConfigurationPropertySource
|
||||
* @see SpringConfigurationPropertySource
|
||||
*/
|
||||
class DefaultPropertyMapper implements PropertyMapper {
|
||||
final class DefaultPropertyMapper implements PropertyMapper {
|
||||
|
||||
public static final PropertyMapper INSTANCE = new DefaultPropertyMapper();
|
||||
|
||||
private final Cache<ConfigurationPropertyName> configurationPropertySourceCache = new Cache<>();
|
||||
private LastMapping<ConfigurationPropertyName> lastMappedConfigurationPropertyName;
|
||||
|
||||
private final Cache<String> propertySourceCache = new Cache<>();
|
||||
private LastMapping<String> lastMappedPropertyName;
|
||||
|
||||
private final ConfigurationPropertyNameBuilder nameBuilder = new ConfigurationPropertyNameBuilder();
|
||||
|
||||
private DefaultPropertyMapper() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PropertyMapping> map(PropertySource<?> propertySource,
|
||||
ConfigurationPropertyName configurationPropertyName) {
|
||||
List<PropertyMapping> mapping = this.configurationPropertySourceCache
|
||||
.get(configurationPropertyName);
|
||||
if (mapping == null) {
|
||||
String convertedName = configurationPropertyName.toString();
|
||||
mapping = Collections.singletonList(
|
||||
new PropertyMapping(convertedName, configurationPropertyName));
|
||||
this.configurationPropertySourceCache.put(configurationPropertyName, mapping);
|
||||
// Use a local copy in case another thread changes things
|
||||
LastMapping<ConfigurationPropertyName> last = this.lastMappedConfigurationPropertyName;
|
||||
if (last != null && last.isFrom(configurationPropertyName)) {
|
||||
return last.getMapping();
|
||||
}
|
||||
String convertedName = configurationPropertyName.toString();
|
||||
List<PropertyMapping> mapping = Collections.singletonList(
|
||||
new PropertyMapping(convertedName, configurationPropertyName));
|
||||
this.lastMappedConfigurationPropertyName = new LastMapping<>(
|
||||
configurationPropertyName, mapping);
|
||||
return mapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PropertyMapping> map(PropertySource<?> propertySource,
|
||||
String propertySourceName) {
|
||||
return this.propertySourceCache.computeIfAbsent(propertySourceName, this::tryMap);
|
||||
// Use a local copy in case another thread changes things
|
||||
LastMapping<String> last = this.lastMappedPropertyName;
|
||||
if (last != null && last.isFrom(propertySourceName)) {
|
||||
return last.getMapping();
|
||||
}
|
||||
List<PropertyMapping> mapping = tryMap(propertySourceName);
|
||||
this.lastMappedPropertyName = new LastMapping<>(propertySourceName, mapping);
|
||||
return mapping;
|
||||
}
|
||||
|
||||
private List<PropertyMapping> tryMap(String propertySourceName) {
|
||||
|
@ -75,23 +86,23 @@ class DefaultPropertyMapper implements PropertyMapper {
|
|||
}
|
||||
}
|
||||
|
||||
private static class Cache<K> extends LinkedHashMap<K, List<PropertyMapping>> {
|
||||
private static class LastMapping<T> {
|
||||
|
||||
private final int capacity;
|
||||
private final T from;
|
||||
|
||||
Cache() {
|
||||
this(1);
|
||||
private final List<PropertyMapping> mapping;
|
||||
|
||||
LastMapping(T from, List<PropertyMapping> mapping) {
|
||||
this.from = from;
|
||||
this.mapping = mapping;
|
||||
}
|
||||
|
||||
Cache(int capacity) {
|
||||
super(capacity, (float) 0.75, true);
|
||||
this.capacity = capacity;
|
||||
public boolean isFrom(T from) {
|
||||
return ObjectUtils.nullSafeEquals(from, this.from);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<K, List<PropertyMapping>> eldest) {
|
||||
return size() > this.capacity;
|
||||
|
||||
public List<PropertyMapping> getMapping() {
|
||||
return this.mapping;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@ import org.springframework.util.Assert;
|
|||
*
|
||||
* @author Phillip Webb
|
||||
* @author Madhura Bhave
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class MapConfigurationPropertySource
|
||||
implements IterableConfigurationPropertySource {
|
||||
|
@ -54,9 +53,9 @@ public class MapConfigurationPropertySource
|
|||
*/
|
||||
public MapConfigurationPropertySource(Map<?, ?> map) {
|
||||
this.source = new LinkedHashMap<>();
|
||||
this.delegate = new PropertySourceIterableConfigurationPropertySource(
|
||||
this.delegate = new SpringIterableConfigurationPropertySource(
|
||||
new MapPropertySource("source", this.source),
|
||||
new DefaultPropertyMapper());
|
||||
DefaultPropertyMapper.INSTANCE);
|
||||
putAll(map);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,16 +27,16 @@ import org.springframework.core.env.PropertySource;
|
|||
* <P>
|
||||
* Mappings should be provided for both {@link ConfigurationPropertyName
|
||||
* ConfigurationPropertyName} types and {@code String} based names. This allows the
|
||||
* {@link PropertySourceConfigurationPropertySource} to first attempt any direct mappings
|
||||
* {@link SpringConfigurationPropertySource} to first attempt any direct mappings
|
||||
* (i.e. map the {@link ConfigurationPropertyName} directly to the {@link PropertySource}
|
||||
* name) before falling back to {@link EnumerablePropertySource enumerating} property
|
||||
* names, mapping them to a {@link ConfigurationPropertyName} and checking for
|
||||
* {@link PropertyMapping#isApplicable(ConfigurationPropertyName) applicability}. See
|
||||
* {@link PropertySourceConfigurationPropertySource} for more details.
|
||||
* {@link SpringConfigurationPropertySource} for more details.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Madhura Bhave
|
||||
* @see PropertySourceConfigurationPropertySource
|
||||
* @see SpringConfigurationPropertySource
|
||||
*/
|
||||
interface PropertyMapper {
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ import org.springframework.core.env.PropertySource;
|
|||
*
|
||||
* @author Phillip Webb
|
||||
* @author Madhura Bhave
|
||||
* @see PropertySourceConfigurationPropertySource
|
||||
* @see SpringConfigurationPropertySource
|
||||
*/
|
||||
class PropertyMapping {
|
||||
|
||||
|
|
|
@ -18,14 +18,17 @@ package org.springframework.boot.context.properties.source;
|
|||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.boot.env.RandomValuePropertySource;
|
||||
import org.springframework.boot.origin.Origin;
|
||||
import org.springframework.boot.origin.PropertySourceOrigin;
|
||||
import org.springframework.core.env.EnumerablePropertySource;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.env.SystemEnvironmentPropertySource;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
|
@ -41,16 +44,19 @@ import org.springframework.util.Assert;
|
|||
* {@link ConfigurationPropertyName} to one or more {@code String} based names. This
|
||||
* allows fast property resolution for well formed property sources.
|
||||
* <p>
|
||||
* If at all possible the {@link PropertySourceIterableConfigurationPropertySource} should
|
||||
* be used in preference to this implementation since it supports "relaxed" style
|
||||
* resolution.
|
||||
* When possible the {@link SpringIterableConfigurationPropertySource} will be used in
|
||||
* preference to this implementation since it supports full "relaxed" style resolution.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Madhura Bhave
|
||||
* @see #from(PropertySource)
|
||||
* @see PropertyMapper
|
||||
* @see PropertySourceIterableConfigurationPropertySource
|
||||
* @see SpringIterableConfigurationPropertySource
|
||||
*/
|
||||
class PropertySourceConfigurationPropertySource implements ConfigurationPropertySource {
|
||||
class SpringConfigurationPropertySource implements ConfigurationPropertySource {
|
||||
|
||||
private static final ConfigurationPropertyName RANDOM = ConfigurationPropertyName
|
||||
.of("random");
|
||||
|
||||
private final PropertySource<?> propertySource;
|
||||
|
||||
|
@ -59,21 +65,21 @@ class PropertySourceConfigurationPropertySource implements ConfigurationProperty
|
|||
private final Function<ConfigurationPropertyName, Optional<Boolean>> containsDescendantOfMethod;
|
||||
|
||||
/**
|
||||
* Create a new {@link PropertySourceConfigurationPropertySource} implementation.
|
||||
* Create a new {@link SpringConfigurationPropertySource} implementation.
|
||||
* @param propertySource the source property source
|
||||
* @param mapper the property mapper
|
||||
* @param containsDescendantOfMethod function used to implement
|
||||
* {@link #containsDescendantOf(ConfigurationPropertyName)} (may be {@code null})
|
||||
*/
|
||||
PropertySourceConfigurationPropertySource(PropertySource<?> propertySource,
|
||||
SpringConfigurationPropertySource(PropertySource<?> propertySource,
|
||||
PropertyMapper mapper,
|
||||
Function<ConfigurationPropertyName, Optional<Boolean>> containsDescendantOfMethod) {
|
||||
Assert.notNull(propertySource, "PropertySource must not be null");
|
||||
Assert.notNull(mapper, "Mapper must not be null");
|
||||
this.propertySource = propertySource;
|
||||
this.mapper = new ExceptionSwallowingPropertyMapper(mapper);
|
||||
this.containsDescendantOfMethod = (containsDescendantOfMethod != null ? containsDescendantOfMethod
|
||||
: (n) -> Optional.empty());
|
||||
this.containsDescendantOfMethod = (containsDescendantOfMethod != null
|
||||
? containsDescendantOfMethod : (n) -> Optional.empty());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -120,6 +126,62 @@ class PropertySourceConfigurationPropertySource implements ConfigurationProperty
|
|||
return this.propertySource.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link SpringConfigurationPropertySource} for the specified
|
||||
* {@link PropertySource}.
|
||||
* @param source the source Spring {@link PropertySource}
|
||||
* @return a {@link SpringConfigurationPropertySource} or
|
||||
* {@link SpringIterableConfigurationPropertySource} instance
|
||||
*/
|
||||
public static SpringConfigurationPropertySource from(PropertySource<?> source) {
|
||||
Assert.notNull(source, "Source must not be null");
|
||||
PropertyMapper mapper = getPropertyMapper(source);
|
||||
if (isFullEnumerable(source)) {
|
||||
return new SpringIterableConfigurationPropertySource(
|
||||
(EnumerablePropertySource<?>) source, mapper);
|
||||
}
|
||||
return new SpringConfigurationPropertySource(source, mapper,
|
||||
getContainsDescendantOfMethod(source));
|
||||
}
|
||||
|
||||
private static PropertyMapper getPropertyMapper(PropertySource<?> source) {
|
||||
if (source instanceof SystemEnvironmentPropertySource) {
|
||||
return SystemEnvironmentPropertyMapper.INSTANCE;
|
||||
}
|
||||
return DefaultPropertyMapper.INSTANCE;
|
||||
}
|
||||
|
||||
private static boolean isFullEnumerable(PropertySource<?> source) {
|
||||
PropertySource<?> rootSource = getRootSource(source);
|
||||
if (rootSource.getSource() instanceof Map) {
|
||||
// Check we're not security restricted
|
||||
try {
|
||||
((Map<?, ?>) rootSource.getSource()).size();
|
||||
}
|
||||
catch (UnsupportedOperationException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return (source instanceof EnumerablePropertySource);
|
||||
}
|
||||
|
||||
private static PropertySource<?> getRootSource(PropertySource<?> source) {
|
||||
while (source.getSource() != null
|
||||
&& source.getSource() instanceof PropertySource) {
|
||||
source = (PropertySource<?>) source.getSource();
|
||||
}
|
||||
return source;
|
||||
}
|
||||
|
||||
private static Function<ConfigurationPropertyName, Optional<Boolean>> getContainsDescendantOfMethod(
|
||||
PropertySource<?> source) {
|
||||
if (source instanceof RandomValuePropertySource) {
|
||||
return (name) -> Optional
|
||||
.of(name.isAncestorOf(RANDOM) || name.equals(RANDOM));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link PropertyMapper} that swallows exceptions when the mapping fails.
|
||||
*/
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* 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.source;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.MutablePropertySources;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.env.PropertySource.StubPropertySource;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Adapter to convert Spring's {@link MutablePropertySources} to
|
||||
* {@link ConfigurationPropertySource ConfigurationPropertySources}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class SpringConfigurationPropertySources
|
||||
implements Iterable<ConfigurationPropertySource> {
|
||||
|
||||
private final MutablePropertySources sources;
|
||||
|
||||
private volatile PropertySourcesKey lastKey;
|
||||
|
||||
private volatile List<ConfigurationPropertySource> adaptedSources;
|
||||
|
||||
SpringConfigurationPropertySources(MutablePropertySources sources) {
|
||||
Assert.notNull(sources, "Sources must not be null");
|
||||
this.sources = sources;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<ConfigurationPropertySource> iterator() {
|
||||
checkForChanges();
|
||||
return this.adaptedSources.iterator();
|
||||
}
|
||||
|
||||
private void checkForChanges() {
|
||||
PropertySourcesKey lastKey = this.lastKey;
|
||||
PropertySourcesKey currentKey = new PropertySourcesKey(this.sources);
|
||||
if (!currentKey.equals(lastKey)) {
|
||||
onChange(this.sources);
|
||||
this.lastKey = currentKey;
|
||||
}
|
||||
}
|
||||
|
||||
private void onChange(MutablePropertySources sources) {
|
||||
this.adaptedSources = streamPropertySources(sources)
|
||||
.map(SpringConfigurationPropertySource::from)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private Stream<PropertySource<?>> streamPropertySources(
|
||||
Iterable<PropertySource<?>> sources) {
|
||||
return StreamSupport.stream(sources.spliterator(), false).flatMap(this::flatten)
|
||||
.filter(this::isIncluded);
|
||||
}
|
||||
|
||||
private Stream<PropertySource<?>> flatten(PropertySource<?> source) {
|
||||
if (source.getSource() instanceof ConfigurableEnvironment) {
|
||||
return streamPropertySources(
|
||||
((ConfigurableEnvironment) source.getSource()).getPropertySources());
|
||||
}
|
||||
return Stream.of(source);
|
||||
}
|
||||
|
||||
private boolean isIncluded(PropertySource<?> source) {
|
||||
return !(source instanceof StubPropertySource)
|
||||
&& !(source instanceof ConfigurationPropertySourcesPropertySource);
|
||||
}
|
||||
|
||||
private static class PropertySourcesKey {
|
||||
|
||||
private final List<PropertySourceKey> keys = new ArrayList<>();
|
||||
|
||||
PropertySourcesKey(MutablePropertySources sources) {
|
||||
sources.forEach(this::addKey);
|
||||
}
|
||||
|
||||
private void addKey(PropertySource<?> source) {
|
||||
this.keys.add(new PropertySourceKey(source));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.keys.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null || getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
return this.keys.equals(((PropertySourcesKey) obj).keys);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class PropertySourceKey {
|
||||
|
||||
private final String name;
|
||||
|
||||
private final Class<?> type;
|
||||
|
||||
PropertySourceKey(PropertySource<?> source) {
|
||||
this.name = source.getName();
|
||||
this.type = source.getClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ObjectUtils.nullSafeHashCode(this.name);
|
||||
result = prime * result + ObjectUtils.nullSafeHashCode(this.type);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null || getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
PropertySourceKey other = (PropertySourceKey) obj;
|
||||
boolean result = true;
|
||||
result = result && ObjectUtils.nullSafeEquals(this.name, other.name);
|
||||
result = result && ObjectUtils.nullSafeEquals(this.type, other.type);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -31,21 +31,24 @@ import org.springframework.util.ObjectUtils;
|
|||
|
||||
/**
|
||||
* {@link ConfigurationPropertySource} backed by a {@link EnumerablePropertySource}.
|
||||
* Extends {@link PropertySourceConfigurationPropertySource} with full "relaxed" mapping
|
||||
* support. In order to use this adapter the underlying {@link PropertySource} must be
|
||||
* fully enumerable. A security restricted {@link SystemEnvironmentPropertySource} cannot
|
||||
* be adapted.
|
||||
* Extends {@link SpringConfigurationPropertySource} with full "relaxed" mapping support.
|
||||
* In order to use this adapter the underlying {@link PropertySource} must be fully
|
||||
* enumerable. A security restricted {@link SystemEnvironmentPropertySource} cannot be
|
||||
* adapted.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Madhura Bhave
|
||||
* @see PropertyMapper
|
||||
*/
|
||||
class PropertySourceIterableConfigurationPropertySource
|
||||
extends PropertySourceConfigurationPropertySource
|
||||
class SpringIterableConfigurationPropertySource extends SpringConfigurationPropertySource
|
||||
implements IterableConfigurationPropertySource {
|
||||
|
||||
PropertySourceIterableConfigurationPropertySource(
|
||||
EnumerablePropertySource<?> propertySource, PropertyMapper mapper) {
|
||||
private volatile Object cacheKey;
|
||||
|
||||
private volatile Cache cache;
|
||||
|
||||
SpringIterableConfigurationPropertySource(EnumerablePropertySource<?> propertySource,
|
||||
PropertyMapper mapper) {
|
||||
super(propertySource, mapper, null);
|
||||
assertEnumerablePropertySource(propertySource);
|
||||
}
|
||||
|
@ -63,10 +66,6 @@ class PropertySourceIterableConfigurationPropertySource
|
|||
}
|
||||
}
|
||||
|
||||
private volatile Object cacheKey;
|
||||
|
||||
private volatile Cache cache;
|
||||
|
||||
@Override
|
||||
public ConfigurationProperty getConfigurationProperty(
|
||||
ConfigurationPropertyName name) {
|
|
@ -41,15 +41,18 @@ import org.springframework.util.StringUtils;
|
|||
* @author Phillip Webb
|
||||
* @author Madhura Bhave
|
||||
* @see PropertyMapper
|
||||
* @see PropertySourceConfigurationPropertySource
|
||||
* @see SpringConfigurationPropertySource
|
||||
*/
|
||||
class SystemEnvironmentPropertyMapper implements PropertyMapper {
|
||||
final class SystemEnvironmentPropertyMapper implements PropertyMapper {
|
||||
|
||||
public static final PropertyMapper INSTANCE = new SystemEnvironmentPropertyMapper();
|
||||
|
||||
private final ConfigurationPropertyNameBuilder nameBuilder = new ConfigurationPropertyNameBuilder(
|
||||
this::createElement);
|
||||
|
||||
private SystemEnvironmentPropertyMapper() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PropertyMapping> map(PropertySource<?> propertySource,
|
||||
String propertySourceName) {
|
||||
|
|
|
@ -48,7 +48,6 @@ import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEven
|
|||
import org.springframework.boot.context.event.ApplicationPreparedEvent;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.boot.context.event.ApplicationStartingEvent;
|
||||
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
|
||||
import org.springframework.boot.testutil.InternalOutputCapture;
|
||||
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
|
||||
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
|
||||
|
@ -868,8 +867,7 @@ public class SpringApplicationTests {
|
|||
assertThat(this.context.getEnvironment().getProperty("foo")).isEqualTo("bar");
|
||||
Iterator<PropertySource<?>> iterator = this.context.getEnvironment()
|
||||
.getPropertySources().iterator();
|
||||
assertThat(iterator.next().getName())
|
||||
.isEqualTo(ConfigurationPropertySources.PROPERTY_SOURCE_NAME);
|
||||
assertThat(iterator.next().getName()).isEqualTo("configurationProperties");
|
||||
assertThat(iterator.next().getName()).isEqualTo(
|
||||
TestPropertySourceUtils.INLINED_PROPERTIES_PROPERTY_SOURCE_NAME);
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@ public class LoggingApplicationListenerTests {
|
|||
new File("target/foo.log").delete();
|
||||
new File(tmpDir() + "/spring.log").delete();
|
||||
ConfigurableEnvironment environment = this.context.getEnvironment();
|
||||
ConfigurationPropertySources.attach(environment.getPropertySources());
|
||||
ConfigurationPropertySources.attach(environment);
|
||||
}
|
||||
|
||||
@After
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
package org.springframework.boot.context.properties.source;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -25,7 +24,7 @@ import org.junit.Rule;
|
|||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.boot.env.RandomValuePropertySource;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
import org.springframework.core.env.MutablePropertySources;
|
||||
|
@ -41,169 +40,47 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
* Tests for {@link ConfigurationPropertySources}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
public class ConfigurationPropertySourcesTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void createWhenPropertySourcesIsNullShouldThrowException() throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("PropertySources must not be null");
|
||||
new ConfigurationPropertySources(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void iteratorShouldAdaptPropertySource() throws Exception {
|
||||
MutablePropertySources sources = new MutablePropertySources();
|
||||
sources.addFirst(new MapPropertySource("test",
|
||||
Collections.<String, Object>singletonMap("a", "b")));
|
||||
Iterator<ConfigurationPropertySource> iterator = new ConfigurationPropertySources(
|
||||
sources).iterator();
|
||||
assertThat(iterator.next()
|
||||
.getConfigurationProperty(ConfigurationPropertyName.of("a")).getValue())
|
||||
.isEqualTo("b");
|
||||
assertThat(iterator.hasNext()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void iteratorShouldAdaptSystemEnvironmentPropertySource() throws Exception {
|
||||
MutablePropertySources sources = new MutablePropertySources();
|
||||
sources.addLast(new SystemEnvironmentPropertySource("system",
|
||||
Collections.<String, Object>singletonMap("SERVER_PORT", "1234")));
|
||||
Iterator<ConfigurationPropertySource> iterator = new ConfigurationPropertySources(
|
||||
sources).iterator();
|
||||
assertThat(
|
||||
iterator.next()
|
||||
.getConfigurationProperty(
|
||||
ConfigurationPropertyName.of("server.port"))
|
||||
.getValue()).isEqualTo("1234");
|
||||
assertThat(iterator.hasNext()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void iteratorShouldAdaptMultiplePropertySources() throws Exception {
|
||||
MutablePropertySources sources = new MutablePropertySources();
|
||||
sources.addLast(new SystemEnvironmentPropertySource("system",
|
||||
Collections.<String, Object>singletonMap("SERVER_PORT", "1234")));
|
||||
sources.addLast(new MapPropertySource("test1",
|
||||
Collections.<String, Object>singletonMap("server.po-rt", "4567")));
|
||||
sources.addLast(new MapPropertySource("test2",
|
||||
Collections.<String, Object>singletonMap("a", "b")));
|
||||
Iterator<ConfigurationPropertySource> iterator = new ConfigurationPropertySources(
|
||||
sources).iterator();
|
||||
assertThat(
|
||||
iterator.next()
|
||||
.getConfigurationProperty(
|
||||
ConfigurationPropertyName.of("server.port"))
|
||||
.getValue()).isEqualTo("1234");
|
||||
assertThat(
|
||||
iterator.next()
|
||||
.getConfigurationProperty(
|
||||
ConfigurationPropertyName.of("server.port"))
|
||||
.getValue()).isEqualTo("4567");
|
||||
assertThat(iterator.next()
|
||||
.getConfigurationProperty(ConfigurationPropertyName.of("a")).getValue())
|
||||
.isEqualTo("b");
|
||||
assertThat(iterator.hasNext()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void attachShouldAddAdapterAtBeginning() throws Exception {
|
||||
MutablePropertySources sources = new MutablePropertySources();
|
||||
ConfigurableEnvironment environment = new StandardEnvironment();
|
||||
MutablePropertySources sources = environment.getPropertySources();
|
||||
sources.addLast(new SystemEnvironmentPropertySource("system",
|
||||
Collections.<String, Object>singletonMap("SERVER_PORT", "1234")));
|
||||
sources.addLast(new MapPropertySource("config",
|
||||
Collections.<String, Object>singletonMap("server.port", "4568")));
|
||||
assertThat(sources.size()).isEqualTo(2);
|
||||
ConfigurationPropertySources.attach(sources);
|
||||
int size = sources.size();
|
||||
ConfigurationPropertySources.attach(environment);
|
||||
assertThat(sources.size()).isEqualTo(size + 1);
|
||||
PropertyResolver resolver = new PropertySourcesPropertyResolver(sources);
|
||||
assertThat(resolver.getProperty("server.port")).isEqualTo("1234");
|
||||
assertThat(sources.size()).isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenNotAttachedShouldReturnAdapted() throws Exception {
|
||||
ConfigurableEnvironment environment = new StandardEnvironment();
|
||||
assertThat(ConfigurationPropertySources.get(environment)).isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenAttachedShouldReturnAttached() throws Exception {
|
||||
MutablePropertySources sources = new MutablePropertySources();
|
||||
ConfigurableEnvironment environment = new StandardEnvironment();
|
||||
MutablePropertySources sources = environment.getPropertySources();
|
||||
sources.addFirst(new MapPropertySource("test",
|
||||
Collections.<String, Object>singletonMap("a", "b")));
|
||||
ConfigurationPropertySources attached = ConfigurationPropertySources
|
||||
.attach(sources);
|
||||
assertThat(ConfigurationPropertySources.get(sources)).isSameAs(attached);
|
||||
int expectedSize = sources.size();
|
||||
ConfigurationPropertySources.attach(environment);
|
||||
assertThat(ConfigurationPropertySources.get(environment)).hasSize(expectedSize);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenNotAttachedShouldReturnNew() throws Exception {
|
||||
MutablePropertySources sources = new MutablePropertySources();
|
||||
sources.addFirst(new MapPropertySource("test",
|
||||
Collections.<String, Object>singletonMap("a", "b")));
|
||||
assertThat(ConfigurationPropertySources.get(sources)).isNotNull();
|
||||
assertThat(sources.size()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenNonEnumerableShouldNotBeIterable() throws Exception {
|
||||
StandardEnvironment environment = new StandardEnvironment();
|
||||
Map<String, Object> source = new LinkedHashMap<String, Object>() {
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
throw new UnsupportedOperationException("Same as security restricted");
|
||||
}
|
||||
|
||||
};
|
||||
PropertySource<?> propertySource = new MapPropertySource("test", source);
|
||||
environment.getPropertySources().addFirst(propertySource);
|
||||
ConfigurationPropertySources sources = ConfigurationPropertySources
|
||||
.get(environment);
|
||||
ConfigurationPropertySource configurationPropertySource = sources.iterator()
|
||||
.next();
|
||||
assertThat(configurationPropertySource)
|
||||
.isNotInstanceOf(IterableConfigurationPropertySource.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenEnumerableButRestrictedShouldNotBeIterable() throws Exception {
|
||||
StandardEnvironment environment = new StandardEnvironment();
|
||||
PropertySource<?> propertySource = new PropertySource<Object>("test",
|
||||
new Object()) {
|
||||
|
||||
@Override
|
||||
public Object getProperty(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
};
|
||||
environment.getPropertySources().addFirst(propertySource);
|
||||
ConfigurationPropertySources sources = ConfigurationPropertySources
|
||||
.get(environment);
|
||||
ConfigurationPropertySource configurationPropertySource = sources.iterator()
|
||||
.next();
|
||||
assertThat(configurationPropertySource)
|
||||
.isNotInstanceOf(IterableConfigurationPropertySource.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenEnumerableShouldBeIterable() throws Exception {
|
||||
StandardEnvironment environment = new StandardEnvironment();
|
||||
Map<String, Object> source = new LinkedHashMap<>();
|
||||
source.put("fooBar", "Spring ${barBaz} ${bar-baz}");
|
||||
source.put("barBaz", "Boot");
|
||||
PropertySource<?> propertySource = new MapPropertySource("test", source);
|
||||
environment.getPropertySources().addFirst(propertySource);
|
||||
ConfigurationPropertySources sources = ConfigurationPropertySources
|
||||
.get(environment);
|
||||
ConfigurationPropertySource configurationPropertySource = sources.iterator()
|
||||
.next();
|
||||
assertThat(configurationPropertySource)
|
||||
.isInstanceOf(IterableConfigurationPropertySource.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void environmentPropertyExpansionShouldWorkWhenAttached() throws Exception {
|
||||
StandardEnvironment environment = new StandardEnvironment();
|
||||
public void environmentProperyExpansionShouldWorkWhenAttached() throws Exception {
|
||||
ConfigurableEnvironment environment = new StandardEnvironment();
|
||||
Map<String, Object> source = new LinkedHashMap<>();
|
||||
source.put("fooBar", "Spring ${barBaz} ${bar-baz}");
|
||||
source.put("barBaz", "Boot");
|
||||
|
@ -214,7 +91,18 @@ public class ConfigurationPropertySourcesTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void environmentSourceShouldBeFlattened() throws Exception {
|
||||
public void fromPropertySourceShouldReturnSpringConfigurationPropertySource()
|
||||
throws Exception {
|
||||
PropertySource<?> source = new MapPropertySource("foo",
|
||||
Collections.<String, Object>singletonMap("foo", "bar"));
|
||||
ConfigurationPropertySource configurationPropertySource = ConfigurationPropertySources
|
||||
.from(source).iterator().next();
|
||||
assertThat(configurationPropertySource)
|
||||
.isInstanceOf(SpringConfigurationPropertySource.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromPropertySourcseShouldFlattenPropertySources() throws Exception {
|
||||
StandardEnvironment environment = new StandardEnvironment();
|
||||
environment.getPropertySources().addFirst(new MapPropertySource("foo",
|
||||
Collections.<String, Object>singletonMap("foo", "bar")));
|
||||
|
@ -231,27 +119,9 @@ public class ConfigurationPropertySourcesTests {
|
|||
});
|
||||
sources.addLast(new MapPropertySource("baz",
|
||||
Collections.<String, Object>singletonMap("baz", "barf")));
|
||||
ConfigurationPropertySources configurationSources = ConfigurationPropertySources
|
||||
.get(sources);
|
||||
Iterable<ConfigurationPropertySource> configurationSources = ConfigurationPropertySources
|
||||
.from(sources);
|
||||
assertThat(configurationSources.iterator()).hasSize(5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void containsDescendantOfForRandomSourceShouldDetectNamesStartingRandom()
|
||||
throws Exception {
|
||||
StandardEnvironment environment = new StandardEnvironment();
|
||||
environment.getPropertySources().addFirst(new RandomValuePropertySource());
|
||||
ConfigurationPropertySource source = ConfigurationPropertySources.get(environment)
|
||||
.iterator().next();
|
||||
assertThat(source.containsDescendantOf(ConfigurationPropertyName.of("")))
|
||||
.contains(true);
|
||||
assertThat(source.containsDescendantOf(ConfigurationPropertyName.of("random")))
|
||||
.contains(true);
|
||||
assertThat(source.containsDescendantOf(ConfigurationPropertyName.of("other")))
|
||||
.contains(false);
|
||||
assertThat(
|
||||
source.containsDescendantOf(ConfigurationPropertyName.of("random.foo")))
|
||||
.contains(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,11 +28,9 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
*/
|
||||
public class DefaultPropertyMapperTests extends AbstractPropertyMapperTests {
|
||||
|
||||
private DefaultPropertyMapper mapper = new DefaultPropertyMapper();
|
||||
|
||||
@Override
|
||||
protected PropertyMapper getMapper() {
|
||||
return this.mapper;
|
||||
return DefaultPropertyMapper.INSTANCE;
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -32,12 +32,12 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link PropertySourceConfigurationPropertySource}.
|
||||
* Tests for {@link SpringConfigurationPropertySource}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
public class PropertySourceConfigurationPropertySourceTests {
|
||||
public class SpringConfigurationPropertySourceTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
@ -46,16 +46,14 @@ public class PropertySourceConfigurationPropertySourceTests {
|
|||
public void createWhenPropertySourceIsNullShouldThrowException() throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("PropertySource must not be null");
|
||||
new PropertySourceConfigurationPropertySource(null, mock(PropertyMapper.class),
|
||||
null);
|
||||
new SpringConfigurationPropertySource(null, mock(PropertyMapper.class), null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWhenMapperIsNullShouldThrowException() throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Mapper must not be null");
|
||||
new PropertySourceConfigurationPropertySource(mock(PropertySource.class), null,
|
||||
null);
|
||||
new SpringConfigurationPropertySource(mock(PropertySource.class), null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -68,7 +66,7 @@ public class PropertySourceConfigurationPropertySourceTests {
|
|||
TestPropertyMapper mapper = new TestPropertyMapper();
|
||||
ConfigurationPropertyName name = ConfigurationPropertyName.of("my.key");
|
||||
mapper.addFromConfigurationProperty(name, "key2");
|
||||
PropertySourceConfigurationPropertySource adapter = new PropertySourceConfigurationPropertySource(
|
||||
SpringConfigurationPropertySource adapter = new SpringConfigurationPropertySource(
|
||||
propertySource, mapper, null);
|
||||
assertThat(adapter.getConfigurationProperty(name).getValue()).isEqualTo("value2");
|
||||
}
|
||||
|
@ -82,7 +80,7 @@ public class PropertySourceConfigurationPropertySourceTests {
|
|||
ConfigurationPropertyName name = ConfigurationPropertyName.of("my.key");
|
||||
mapper.addFromConfigurationProperty(name, "key",
|
||||
(value) -> value.toString().replace("ue", "let"));
|
||||
PropertySourceConfigurationPropertySource adapter = new PropertySourceConfigurationPropertySource(
|
||||
SpringConfigurationPropertySource adapter = new SpringConfigurationPropertySource(
|
||||
propertySource, mapper, null);
|
||||
assertThat(adapter.getConfigurationProperty(name).getValue()).isEqualTo("vallet");
|
||||
}
|
||||
|
@ -95,7 +93,7 @@ public class PropertySourceConfigurationPropertySourceTests {
|
|||
TestPropertyMapper mapper = new TestPropertyMapper();
|
||||
ConfigurationPropertyName name = ConfigurationPropertyName.of("my.key");
|
||||
mapper.addFromConfigurationProperty(name, "key");
|
||||
PropertySourceConfigurationPropertySource adapter = new PropertySourceConfigurationPropertySource(
|
||||
SpringConfigurationPropertySource adapter = new SpringConfigurationPropertySource(
|
||||
propertySource, mapper, null);
|
||||
assertThat(adapter.getConfigurationProperty(name).getOrigin().toString())
|
||||
.isEqualTo("\"key\" from property source \"test\"");
|
||||
|
@ -110,7 +108,7 @@ public class PropertySourceConfigurationPropertySourceTests {
|
|||
TestPropertyMapper mapper = new TestPropertyMapper();
|
||||
ConfigurationPropertyName name = ConfigurationPropertyName.of("my.key");
|
||||
mapper.addFromConfigurationProperty(name, "key");
|
||||
PropertySourceConfigurationPropertySource adapter = new PropertySourceConfigurationPropertySource(
|
||||
SpringConfigurationPropertySource adapter = new SpringConfigurationPropertySource(
|
||||
propertySource, mapper, null);
|
||||
assertThat(adapter.getConfigurationProperty(name).getOrigin().toString())
|
||||
.isEqualTo("TestOrigin key");
|
||||
|
@ -121,12 +119,61 @@ public class PropertySourceConfigurationPropertySourceTests {
|
|||
Map<String, Object> source = new LinkedHashMap<>();
|
||||
source.put("foo.bar", "value");
|
||||
PropertySource<?> propertySource = new MapPropertySource("test", source);
|
||||
PropertySourceConfigurationPropertySource adapter = new PropertySourceConfigurationPropertySource(
|
||||
propertySource, new DefaultPropertyMapper(), null);
|
||||
SpringConfigurationPropertySource adapter = new SpringConfigurationPropertySource(
|
||||
propertySource, DefaultPropertyMapper.INSTANCE, null);
|
||||
assertThat(adapter.containsDescendantOf(ConfigurationPropertyName.of("foo")))
|
||||
.isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromWhenPropertySourceIsNullShouldThrowException() throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Source must not be null");
|
||||
SpringConfigurationPropertySource.from(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromWhenNonEnumerableShouldReturnNonIterable() throws Exception {
|
||||
PropertySource<?> propertySource = new PropertySource<Object>("test",
|
||||
new Object()) {
|
||||
|
||||
@Override
|
||||
public Object getProperty(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
};
|
||||
assertThat(SpringConfigurationPropertySource.from(propertySource))
|
||||
.isNotInstanceOf(IterableConfigurationPropertySource.class);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromWhenEnumerableButRestrictedShouldReturnNonIterable()
|
||||
throws Exception {
|
||||
Map<String, Object> source = new LinkedHashMap<String, Object>() {
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
throw new UnsupportedOperationException("Same as security restricted");
|
||||
}
|
||||
|
||||
};
|
||||
PropertySource<?> propertySource = new MapPropertySource("test", source);
|
||||
assertThat(SpringConfigurationPropertySource.from(propertySource))
|
||||
.isNotInstanceOf(IterableConfigurationPropertySource.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenEnumerableShouldBeIterable() throws Exception {
|
||||
Map<String, Object> source = new LinkedHashMap<>();
|
||||
source.put("fooBar", "Spring ${barBaz} ${bar-baz}");
|
||||
source.put("barBaz", "Boot");
|
||||
PropertySource<?> propertySource = new MapPropertySource("test", source);
|
||||
assertThat(SpringConfigurationPropertySource.from(propertySource))
|
||||
.isInstanceOf(IterableConfigurationPropertySource.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test {@link PropertySource} that's also a {@link OriginLookup}.
|
||||
*/
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* 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.source;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
import org.springframework.core.env.MutablePropertySources;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.core.env.SystemEnvironmentPropertySource;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link SpringConfigurationPropertySources}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
public class SpringConfigurationPropertySourcesTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void createWhenPropertySourcesIsNullShouldThrowException() throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Sources must not be null");
|
||||
new SpringConfigurationPropertySources(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAdaptPropertySource() throws Exception {
|
||||
MutablePropertySources sources = new MutablePropertySources();
|
||||
sources.addFirst(new MapPropertySource("test",
|
||||
Collections.<String, Object>singletonMap("a", "b")));
|
||||
Iterator<ConfigurationPropertySource> iterator = new SpringConfigurationPropertySources(
|
||||
sources).iterator();
|
||||
ConfigurationPropertyName name = ConfigurationPropertyName.of("a");
|
||||
assertThat(iterator.next().getConfigurationProperty(name).getValue())
|
||||
.isEqualTo("b");
|
||||
assertThat(iterator.hasNext()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAdaptSystemEnvironmentPropertySource() throws Exception {
|
||||
MutablePropertySources sources = new MutablePropertySources();
|
||||
sources.addLast(new SystemEnvironmentPropertySource("system",
|
||||
Collections.<String, Object>singletonMap("SERVER_PORT", "1234")));
|
||||
Iterator<ConfigurationPropertySource> iterator = new SpringConfigurationPropertySources(
|
||||
sources).iterator();
|
||||
ConfigurationPropertyName name = ConfigurationPropertyName.of("server.port");
|
||||
assertThat(iterator.next().getConfigurationProperty(name).getValue())
|
||||
.isEqualTo("1234");
|
||||
assertThat(iterator.hasNext()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAdaptMultiplePropertySources() throws Exception {
|
||||
MutablePropertySources sources = new MutablePropertySources();
|
||||
sources.addLast(new SystemEnvironmentPropertySource("system",
|
||||
Collections.<String, Object>singletonMap("SERVER_PORT", "1234")));
|
||||
sources.addLast(new MapPropertySource("test1",
|
||||
Collections.<String, Object>singletonMap("server.po-rt", "4567")));
|
||||
sources.addLast(new MapPropertySource("test2",
|
||||
Collections.<String, Object>singletonMap("a", "b")));
|
||||
Iterator<ConfigurationPropertySource> iterator = new SpringConfigurationPropertySources(
|
||||
sources).iterator();
|
||||
ConfigurationPropertyName name = ConfigurationPropertyName.of("server.port");
|
||||
assertThat(iterator.next().getConfigurationProperty(name).getValue())
|
||||
.isEqualTo("1234");
|
||||
assertThat(iterator.next().getConfigurationProperty(name).getValue())
|
||||
.isEqualTo("4567");
|
||||
assertThat(iterator.next()
|
||||
.getConfigurationProperty(ConfigurationPropertyName.of("a")).getValue())
|
||||
.isEqualTo("b");
|
||||
assertThat(iterator.hasNext()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFlattenEnvironment() throws Exception {
|
||||
StandardEnvironment environment = new StandardEnvironment();
|
||||
environment.getPropertySources().addFirst(new MapPropertySource("foo",
|
||||
Collections.<String, Object>singletonMap("foo", "bar")));
|
||||
environment.getPropertySources().addFirst(new MapPropertySource("far",
|
||||
Collections.<String, Object>singletonMap("far", "far")));
|
||||
MutablePropertySources sources = new MutablePropertySources();
|
||||
sources.addFirst(new PropertySource<Environment>("env", environment) {
|
||||
|
||||
@Override
|
||||
public String getProperty(String key) {
|
||||
return this.source.getProperty(key);
|
||||
}
|
||||
|
||||
});
|
||||
sources.addLast(new MapPropertySource("baz",
|
||||
Collections.<String, Object>singletonMap("baz", "barf")));
|
||||
SpringConfigurationPropertySources configurationSources = new SpringConfigurationPropertySources(
|
||||
sources);
|
||||
assertThat(configurationSources.iterator()).hasSize(5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldTrackChanges() throws Exception {
|
||||
MutablePropertySources sources = new MutablePropertySources();
|
||||
sources.addLast(new MapPropertySource("test1",
|
||||
Collections.<String, Object>singletonMap("a", "b")));
|
||||
assertThat(new SpringConfigurationPropertySources(sources).iterator()).hasSize(1);
|
||||
sources.addLast(new MapPropertySource("test2",
|
||||
Collections.<String, Object>singletonMap("b", "c")));
|
||||
assertThat(new SpringConfigurationPropertySources(sources).iterator()).hasSize(2);
|
||||
}
|
||||
|
||||
}
|
|
@ -33,12 +33,12 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link PropertySourceIterableConfigurationPropertySource}.
|
||||
* Tests for {@link SpringIterableConfigurationPropertySource}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
public class PropertySourceIterableConfigurationPropertySourceTests {
|
||||
public class SpringIterableConfigurationPropertySourceTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
@ -47,15 +47,14 @@ public class PropertySourceIterableConfigurationPropertySourceTests {
|
|||
public void createWhenPropertySourceIsNullShouldThrowException() throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("PropertySource must not be null");
|
||||
new PropertySourceIterableConfigurationPropertySource(null,
|
||||
mock(PropertyMapper.class));
|
||||
new SpringIterableConfigurationPropertySource(null, mock(PropertyMapper.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWhenMapperIsNullShouldThrowException() throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Mapper must not be null");
|
||||
new PropertySourceIterableConfigurationPropertySource(
|
||||
new SpringIterableConfigurationPropertySource(
|
||||
mock(EnumerablePropertySource.class), null);
|
||||
}
|
||||
|
||||
|
@ -72,7 +71,7 @@ public class PropertySourceIterableConfigurationPropertySourceTests {
|
|||
mapper.addFromPropertySource("key1", "my.key1");
|
||||
mapper.addFromPropertySource("key2", "my.key2a", "my.key2b");
|
||||
mapper.addFromPropertySource("key4", "my.key4");
|
||||
PropertySourceIterableConfigurationPropertySource adapter = new PropertySourceIterableConfigurationPropertySource(
|
||||
SpringIterableConfigurationPropertySource adapter = new SpringIterableConfigurationPropertySource(
|
||||
propertySource, mapper);
|
||||
assertThat(adapter.iterator()).extracting(Object::toString)
|
||||
.containsExactly("my.key1", "my.key2a", "my.key2b", "my.key4");
|
||||
|
@ -89,7 +88,7 @@ public class PropertySourceIterableConfigurationPropertySourceTests {
|
|||
TestPropertyMapper mapper = new TestPropertyMapper();
|
||||
ConfigurationPropertyName name = ConfigurationPropertyName.of("my.key");
|
||||
mapper.addFromConfigurationProperty(name, "key2");
|
||||
PropertySourceIterableConfigurationPropertySource adapter = new PropertySourceIterableConfigurationPropertySource(
|
||||
SpringIterableConfigurationPropertySource adapter = new SpringIterableConfigurationPropertySource(
|
||||
propertySource, mapper);
|
||||
assertThat(adapter.getConfigurationProperty(name).getValue()).isEqualTo("value2");
|
||||
}
|
||||
|
@ -105,7 +104,7 @@ public class PropertySourceIterableConfigurationPropertySourceTests {
|
|||
TestPropertyMapper mapper = new TestPropertyMapper();
|
||||
mapper.addFromPropertySource("key1", "my.missing");
|
||||
mapper.addFromPropertySource("key2", "my.k-e-y");
|
||||
PropertySourceIterableConfigurationPropertySource adapter = new PropertySourceIterableConfigurationPropertySource(
|
||||
SpringIterableConfigurationPropertySource adapter = new SpringIterableConfigurationPropertySource(
|
||||
propertySource, mapper);
|
||||
ConfigurationPropertyName name = ConfigurationPropertyName.of("my.key");
|
||||
assertThat(adapter.getConfigurationProperty(name).getValue()).isEqualTo("value2");
|
||||
|
@ -121,7 +120,7 @@ public class PropertySourceIterableConfigurationPropertySourceTests {
|
|||
ConfigurationPropertyName name = ConfigurationPropertyName.of("my.key");
|
||||
mapper.addFromConfigurationProperty(name, "key",
|
||||
(value) -> value.toString().replace("ue", "let"));
|
||||
PropertySourceIterableConfigurationPropertySource adapter = new PropertySourceIterableConfigurationPropertySource(
|
||||
SpringIterableConfigurationPropertySource adapter = new SpringIterableConfigurationPropertySource(
|
||||
propertySource, mapper);
|
||||
assertThat(adapter.getConfigurationProperty(name).getValue()).isEqualTo("vallet");
|
||||
}
|
||||
|
@ -135,7 +134,7 @@ public class PropertySourceIterableConfigurationPropertySourceTests {
|
|||
TestPropertyMapper mapper = new TestPropertyMapper();
|
||||
ConfigurationPropertyName name = ConfigurationPropertyName.of("my.key");
|
||||
mapper.addFromConfigurationProperty(name, "key");
|
||||
PropertySourceIterableConfigurationPropertySource adapter = new PropertySourceIterableConfigurationPropertySource(
|
||||
SpringIterableConfigurationPropertySource adapter = new SpringIterableConfigurationPropertySource(
|
||||
propertySource, mapper);
|
||||
assertThat(adapter.getConfigurationProperty(name).getOrigin().toString())
|
||||
.isEqualTo("\"key\" from property source \"test\"");
|
||||
|
@ -150,7 +149,7 @@ public class PropertySourceIterableConfigurationPropertySourceTests {
|
|||
TestPropertyMapper mapper = new TestPropertyMapper();
|
||||
ConfigurationPropertyName name = ConfigurationPropertyName.of("my.key");
|
||||
mapper.addFromConfigurationProperty(name, "key");
|
||||
PropertySourceIterableConfigurationPropertySource adapter = new PropertySourceIterableConfigurationPropertySource(
|
||||
SpringIterableConfigurationPropertySource adapter = new SpringIterableConfigurationPropertySource(
|
||||
propertySource, mapper);
|
||||
assertThat(adapter.getConfigurationProperty(name).getOrigin().toString())
|
||||
.isEqualTo("TestOrigin key");
|
||||
|
@ -163,8 +162,8 @@ public class PropertySourceIterableConfigurationPropertySourceTests {
|
|||
source.put("faf", "value");
|
||||
EnumerablePropertySource<?> propertySource = new OriginCapablePropertySource<>(
|
||||
new MapPropertySource("test", source));
|
||||
PropertySourceIterableConfigurationPropertySource adapter = new PropertySourceIterableConfigurationPropertySource(
|
||||
propertySource, new DefaultPropertyMapper());
|
||||
SpringIterableConfigurationPropertySource adapter = new SpringIterableConfigurationPropertySource(
|
||||
propertySource, DefaultPropertyMapper.INSTANCE);
|
||||
assertThat(adapter.containsDescendantOf(ConfigurationPropertyName.of("foo")))
|
||||
.contains(true);
|
||||
assertThat(adapter.containsDescendantOf(ConfigurationPropertyName.of("faf")))
|
|
@ -36,11 +36,9 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
*/
|
||||
public class SystemEnvironmentPropertyMapperTests extends AbstractPropertyMapperTests {
|
||||
|
||||
private SystemEnvironmentPropertyMapper mapper = new SystemEnvironmentPropertyMapper();
|
||||
|
||||
@Override
|
||||
protected PropertyMapper getMapper() {
|
||||
return this.mapper;
|
||||
return SystemEnvironmentPropertyMapper.INSTANCE;
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -75,7 +73,7 @@ public class SystemEnvironmentPropertyMapperTests extends AbstractPropertyMapper
|
|||
Map<String, Object> source = new LinkedHashMap<>();
|
||||
source.put("SERVER__", "foo,bar,baz");
|
||||
PropertySource<?> propertySource = new MapPropertySource("test", source);
|
||||
List<PropertyMapping> mappings = this.mapper.map(propertySource, "SERVER__");
|
||||
List<PropertyMapping> mappings = getMapper().map(propertySource, "SERVER__");
|
||||
List<Object> result = new ArrayList<>();
|
||||
for (PropertyMapping mapping : mappings) {
|
||||
Object value = propertySource.getProperty(mapping.getPropertySourceName());
|
||||
|
@ -91,7 +89,7 @@ public class SystemEnvironmentPropertyMapperTests extends AbstractPropertyMapper
|
|||
Map<String, Object> source = new LinkedHashMap<>();
|
||||
source.put("SERVER__", "foo,bar,baz");
|
||||
PropertySource<?> propertySource = new MapPropertySource("test", source);
|
||||
List<PropertyMapping> mappings = this.mapper.map(propertySource,
|
||||
List<PropertyMapping> mappings = getMapper().map(propertySource,
|
||||
ConfigurationPropertyName.of("server[1]"));
|
||||
List<Object> result = new ArrayList<>();
|
||||
for (PropertyMapping mapping : mappings) {
|
||||
|
@ -108,7 +106,7 @@ public class SystemEnvironmentPropertyMapperTests extends AbstractPropertyMapper
|
|||
public void underscoreShouldNotMapToEmptyString() throws Exception {
|
||||
Map<String, Object> source = new LinkedHashMap<>();
|
||||
PropertySource<?> propertySource = new MapPropertySource("test", source);
|
||||
List<PropertyMapping> mappings = this.mapper.map(propertySource, "_");
|
||||
List<PropertyMapping> mappings = getMapper().map(propertySource, "_");
|
||||
boolean applicable = false;
|
||||
for (PropertyMapping mapping : mappings) {
|
||||
applicable = mapping.isApplicable(ConfigurationPropertyName.of(""));
|
||||
|
@ -120,7 +118,7 @@ public class SystemEnvironmentPropertyMapperTests extends AbstractPropertyMapper
|
|||
public void underscoreWithWhitespaceShouldNotMapToEmptyString() throws Exception {
|
||||
Map<String, Object> source = new LinkedHashMap<>();
|
||||
PropertySource<?> propertySource = new MapPropertySource("test", source);
|
||||
List<PropertyMapping> mappings = this.mapper.map(propertySource, " _");
|
||||
List<PropertyMapping> mappings = getMapper().map(propertySource, " _");
|
||||
boolean applicable = false;
|
||||
for (PropertyMapping mapping : mappings) {
|
||||
applicable = mapping.isApplicable(ConfigurationPropertyName.of(""));
|
||||
|
|
Loading…
Reference in New Issue