Allow placeholders to be used in imports
Allow `${..}` property placeholders to be used in `spring.config.import` properties. Prior to this commit, placeholders were not resolved when binding the `ConfigDataProperty` instance. Furthermore, binding happened too early for all placeholders to be resolved correctly. The `ConfigDataEnvironmentContributor` class now has two states for imported contributors, `UNBOUND_IMPORT` has the initial unbound state and is eventually replaced with a `BOUND_IMPORT`. Closes gh-23020
This commit is contained in:
parent
00cb5bbd86
commit
758df17c7d
|
@ -235,7 +235,7 @@ class ConfigDataEnvironment {
|
||||||
MutablePropertySources propertySources = this.environment.getPropertySources();
|
MutablePropertySources propertySources = this.environment.getPropertySources();
|
||||||
this.logger.trace("Applying config data environment contributions");
|
this.logger.trace("Applying config data environment contributions");
|
||||||
for (ConfigDataEnvironmentContributor contributor : contributors) {
|
for (ConfigDataEnvironmentContributor contributor : contributors) {
|
||||||
if (contributor.getKind() == ConfigDataEnvironmentContributor.Kind.IMPORTED
|
if (contributor.getKind() == ConfigDataEnvironmentContributor.Kind.BOUND_IMPORT
|
||||||
&& contributor.getPropertySource() != null) {
|
&& contributor.getPropertySource() != null) {
|
||||||
if (!contributor.isActive(activationContext)) {
|
if (!contributor.isActive(activationContext)) {
|
||||||
this.logger.trace(LogMessage.format("Skipping inactive property source '%s'",
|
this.logger.trace(LogMessage.format("Skipping inactive property source '%s'",
|
||||||
|
|
|
@ -59,6 +59,8 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
|
||||||
|
|
||||||
private final ConfigDataProperties properties;
|
private final ConfigDataProperties properties;
|
||||||
|
|
||||||
|
private final boolean ignoreImports;
|
||||||
|
|
||||||
private final Map<ImportPhase, List<ConfigDataEnvironmentContributor>> children;
|
private final Map<ImportPhase, List<ConfigDataEnvironmentContributor>> children;
|
||||||
|
|
||||||
private final Kind kind;
|
private final Kind kind;
|
||||||
|
@ -71,16 +73,18 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
|
||||||
* @param configurationPropertySource the configuration property source for the data
|
* @param configurationPropertySource the configuration property source for the data
|
||||||
* or {@code null}
|
* or {@code null}
|
||||||
* @param properties the config data properties or {@code null}
|
* @param properties the config data properties or {@code null}
|
||||||
|
* @param ignoreImports if import properties should be ignored
|
||||||
* @param children the children of this contributor at each {@link ImportPhase}
|
* @param children the children of this contributor at each {@link ImportPhase}
|
||||||
*/
|
*/
|
||||||
ConfigDataEnvironmentContributor(Kind kind, ConfigDataLocation location, PropertySource<?> propertySource,
|
ConfigDataEnvironmentContributor(Kind kind, ConfigDataLocation location, PropertySource<?> propertySource,
|
||||||
ConfigurationPropertySource configurationPropertySource, ConfigDataProperties properties,
|
ConfigurationPropertySource configurationPropertySource, ConfigDataProperties properties,
|
||||||
Map<ImportPhase, List<ConfigDataEnvironmentContributor>> children) {
|
boolean ignoreImports, Map<ImportPhase, List<ConfigDataEnvironmentContributor>> children) {
|
||||||
this.kind = kind;
|
this.kind = kind;
|
||||||
this.location = location;
|
this.location = location;
|
||||||
this.properties = properties;
|
this.properties = properties;
|
||||||
this.propertySource = propertySource;
|
this.propertySource = propertySource;
|
||||||
this.configurationPropertySource = configurationPropertySource;
|
this.configurationPropertySource = configurationPropertySource;
|
||||||
|
this.ignoreImports = ignoreImports;
|
||||||
this.children = (children != null) ? children : Collections.emptyMap();
|
this.children = (children != null) ? children : Collections.emptyMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,6 +179,16 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
|
||||||
return new ContributorIterator();
|
return new ContributorIterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ConfigDataEnvironmentContributor withBoundProperties(Binder binder) {
|
||||||
|
UseLegacyConfigProcessingException.throwIfRequested(binder);
|
||||||
|
ConfigDataProperties properties = ConfigDataProperties.get(binder);
|
||||||
|
if (this.ignoreImports) {
|
||||||
|
properties = properties.withoutImports();
|
||||||
|
}
|
||||||
|
return new ConfigDataEnvironmentContributor(Kind.BOUND_IMPORT, this.location, this.propertySource,
|
||||||
|
this.configurationPropertySource, properties, this.ignoreImports, null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@link ConfigDataEnvironmentContributor} instance with a new set of
|
* Create a new {@link ConfigDataEnvironmentContributor} instance with a new set of
|
||||||
* children for the given phase.
|
* children for the given phase.
|
||||||
|
@ -187,7 +201,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
|
||||||
Map<ImportPhase, List<ConfigDataEnvironmentContributor>> updatedChildren = new LinkedHashMap<>(this.children);
|
Map<ImportPhase, List<ConfigDataEnvironmentContributor>> updatedChildren = new LinkedHashMap<>(this.children);
|
||||||
updatedChildren.put(importPhase, children);
|
updatedChildren.put(importPhase, children);
|
||||||
return new ConfigDataEnvironmentContributor(this.kind, this.location, this.propertySource,
|
return new ConfigDataEnvironmentContributor(this.kind, this.location, this.propertySource,
|
||||||
this.configurationPropertySource, this.properties, updatedChildren);
|
this.configurationPropertySource, this.properties, this.ignoreImports, updatedChildren);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -212,7 +226,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
|
||||||
updatedChildren.put(importPhase, Collections.unmodifiableList(updatedContributors));
|
updatedChildren.put(importPhase, Collections.unmodifiableList(updatedContributors));
|
||||||
});
|
});
|
||||||
return new ConfigDataEnvironmentContributor(this.kind, this.location, this.propertySource,
|
return new ConfigDataEnvironmentContributor(this.kind, this.location, this.propertySource,
|
||||||
this.configurationPropertySource, this.properties, updatedChildren);
|
this.configurationPropertySource, this.properties, this.ignoreImports, updatedChildren);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -223,20 +237,20 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
|
||||||
static ConfigDataEnvironmentContributor of(List<ConfigDataEnvironmentContributor> contributors) {
|
static ConfigDataEnvironmentContributor of(List<ConfigDataEnvironmentContributor> contributors) {
|
||||||
Map<ImportPhase, List<ConfigDataEnvironmentContributor>> children = new LinkedHashMap<>();
|
Map<ImportPhase, List<ConfigDataEnvironmentContributor>> children = new LinkedHashMap<>();
|
||||||
children.put(ImportPhase.BEFORE_PROFILE_ACTIVATION, Collections.unmodifiableList(contributors));
|
children.put(ImportPhase.BEFORE_PROFILE_ACTIVATION, Collections.unmodifiableList(contributors));
|
||||||
return new ConfigDataEnvironmentContributor(Kind.ROOT, null, null, null, null, children);
|
return new ConfigDataEnvironmentContributor(Kind.ROOT, null, null, null, null, false, children);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory method to create a {@link Kind#INITIAL_IMPORT initial import} contributor.
|
* Factory method to create a {@link Kind#INITIAL_IMPORT initial import} contributor.
|
||||||
* This contributor is used to trigger initial imports of additional contributors. It
|
* This contributor is used to trigger initial imports of additional contributors. It
|
||||||
* does not contribute any properties itself.
|
* does not contribute any properties itself.
|
||||||
* @param importLocation the initial import location
|
* @param importLocation the initial import location (with placeholder resolved)
|
||||||
* @return a new {@link ConfigDataEnvironmentContributor} instance
|
* @return a new {@link ConfigDataEnvironmentContributor} instance
|
||||||
*/
|
*/
|
||||||
static ConfigDataEnvironmentContributor ofInitialImport(String importLocation) {
|
static ConfigDataEnvironmentContributor ofInitialImport(String importLocation) {
|
||||||
List<String> imports = Collections.singletonList(importLocation);
|
List<String> imports = Collections.singletonList(importLocation);
|
||||||
ConfigDataProperties properties = new ConfigDataProperties(imports, null);
|
ConfigDataProperties properties = new ConfigDataProperties(imports, null);
|
||||||
return new ConfigDataEnvironmentContributor(Kind.INITIAL_IMPORT, null, null, null, properties, null);
|
return new ConfigDataEnvironmentContributor(Kind.INITIAL_IMPORT, null, null, null, properties, false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -248,31 +262,25 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
|
||||||
*/
|
*/
|
||||||
static ConfigDataEnvironmentContributor ofExisting(PropertySource<?> propertySource) {
|
static ConfigDataEnvironmentContributor ofExisting(PropertySource<?> propertySource) {
|
||||||
return new ConfigDataEnvironmentContributor(Kind.EXISTING, null, propertySource,
|
return new ConfigDataEnvironmentContributor(Kind.EXISTING, null, propertySource,
|
||||||
ConfigurationPropertySource.from(propertySource), null, null);
|
ConfigurationPropertySource.from(propertySource), null, false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory method to create a {@link Kind#IMPORTED imported} contributor. This
|
* Factory method to create an {@link Kind#UNBOUND_IMPORT unbound import} contributor.
|
||||||
* contributor has been actively imported from another contributor and may itself
|
* This contributor has been actively imported from another contributor and may itself
|
||||||
* import further contributors later.
|
* import further contributors later.
|
||||||
* @param location the location of imported config data
|
* @param location the location of imported config data
|
||||||
* @param configData the config data
|
* @param configData the config data
|
||||||
* @param propertySourceIndex the index of the property source that should be used
|
* @param propertySourceIndex the index of the property source that should be used
|
||||||
* @param activationContext the current activation context
|
|
||||||
* @return a new {@link ConfigDataEnvironmentContributor} instance
|
* @return a new {@link ConfigDataEnvironmentContributor} instance
|
||||||
*/
|
*/
|
||||||
static ConfigDataEnvironmentContributor ofImported(ConfigDataLocation location, ConfigData configData,
|
static ConfigDataEnvironmentContributor ofUnboundImport(ConfigDataLocation location, ConfigData configData,
|
||||||
int propertySourceIndex, ConfigDataActivationContext activationContext) {
|
int propertySourceIndex) {
|
||||||
PropertySource<?> propertySource = configData.getPropertySources().get(propertySourceIndex);
|
PropertySource<?> propertySource = configData.getPropertySources().get(propertySourceIndex);
|
||||||
ConfigurationPropertySource configurationPropertySource = ConfigurationPropertySource.from(propertySource);
|
ConfigurationPropertySource configurationPropertySource = ConfigurationPropertySource.from(propertySource);
|
||||||
Binder binder = new Binder(configurationPropertySource);
|
boolean ignoreImports = configData.getOptions().contains(ConfigData.Option.IGNORE_IMPORTS);
|
||||||
UseLegacyConfigProcessingException.throwIfRequested(binder);
|
return new ConfigDataEnvironmentContributor(Kind.UNBOUND_IMPORT, location, propertySource,
|
||||||
ConfigDataProperties properties = ConfigDataProperties.get(binder);
|
configurationPropertySource, null, ignoreImports, null);
|
||||||
if (configData.getOptions().contains(ConfigData.Option.IGNORE_IMPORTS)) {
|
|
||||||
properties = properties.withoutImports();
|
|
||||||
}
|
|
||||||
return new ConfigDataEnvironmentContributor(Kind.IMPORTED, location, propertySource,
|
|
||||||
configurationPropertySource, properties, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -296,9 +304,16 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
|
||||||
EXISTING,
|
EXISTING,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A contributor with {@link ConfigData} imported from another contributor.
|
* A contributor with {@link ConfigData} imported from another contributor but not
|
||||||
|
* yet bound.
|
||||||
*/
|
*/
|
||||||
IMPORTED;
|
UNBOUND_IMPORT,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A contributor with {@link ConfigData} imported from another contributor that
|
||||||
|
* has been.
|
||||||
|
*/
|
||||||
|
BOUND_IMPORT;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ import java.util.stream.Stream;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
|
|
||||||
import org.springframework.boot.context.config.ConfigDataEnvironmentContributor.ImportPhase;
|
import org.springframework.boot.context.config.ConfigDataEnvironmentContributor.ImportPhase;
|
||||||
|
import org.springframework.boot.context.config.ConfigDataEnvironmentContributor.Kind;
|
||||||
import org.springframework.boot.context.properties.bind.BindContext;
|
import org.springframework.boot.context.properties.bind.BindContext;
|
||||||
import org.springframework.boot.context.properties.bind.BindHandler;
|
import org.springframework.boot.context.properties.bind.BindHandler;
|
||||||
import org.springframework.boot.context.properties.bind.Bindable;
|
import org.springframework.boot.context.properties.bind.Bindable;
|
||||||
|
@ -91,27 +92,38 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen
|
||||||
this.logger.trace(LogMessage.format("Processing imports for phase %s. %s", importPhase,
|
this.logger.trace(LogMessage.format("Processing imports for phase %s. %s", importPhase,
|
||||||
(activationContext != null) ? activationContext : "no activation context"));
|
(activationContext != null) ? activationContext : "no activation context"));
|
||||||
ConfigDataEnvironmentContributors result = this;
|
ConfigDataEnvironmentContributors result = this;
|
||||||
int processedCount = 0;
|
int processed = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
ConfigDataEnvironmentContributor unprocessed = getFirstUnprocessed(result, activationContext, importPhase);
|
ConfigDataEnvironmentContributor contributor = getNextToProcess(result, activationContext, importPhase);
|
||||||
if (unprocessed == null) {
|
if (contributor == null) {
|
||||||
this.logger.trace(LogMessage.format("Processed imports for of %d contributors", processedCount));
|
this.logger.trace(LogMessage.format("Processed imports for of %d contributors", processed));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
if (contributor.getKind() == Kind.UNBOUND_IMPORT) {
|
||||||
|
Iterable<ConfigurationPropertySource> sources = Collections
|
||||||
|
.singleton(contributor.getConfigurationPropertySource());
|
||||||
|
PlaceholdersResolver placeholdersResolver = new ConfigDataEnvironmentContributorPlaceholdersResolver(
|
||||||
|
result, activationContext, true);
|
||||||
|
Binder binder = new Binder(sources, placeholdersResolver, null, null, null);
|
||||||
|
ConfigDataEnvironmentContributor bound = contributor.withBoundProperties(binder);
|
||||||
|
result = new ConfigDataEnvironmentContributors(this.logger, this.bootstrapRegistry,
|
||||||
|
result.getRoot().withReplacement(contributor, bound));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
ConfigDataLocationResolverContext locationResolverContext = new ContributorConfigDataLocationResolverContext(
|
ConfigDataLocationResolverContext locationResolverContext = new ContributorConfigDataLocationResolverContext(
|
||||||
result, unprocessed, activationContext);
|
result, contributor, activationContext);
|
||||||
ConfigDataLoaderContext loaderContext = new ContributorDataLoaderContext(this);
|
ConfigDataLoaderContext loaderContext = new ContributorDataLoaderContext(this);
|
||||||
List<String> imports = unprocessed.getImports();
|
List<String> imports = contributor.getImports();
|
||||||
this.logger.trace(LogMessage.format("Processing imports %s", imports));
|
this.logger.trace(LogMessage.format("Processing imports %s", imports));
|
||||||
Map<ConfigDataLocation, ConfigData> imported = importer.resolveAndLoad(activationContext,
|
Map<ConfigDataLocation, ConfigData> imported = importer.resolveAndLoad(activationContext,
|
||||||
locationResolverContext, loaderContext, imports);
|
locationResolverContext, loaderContext, imports);
|
||||||
this.logger.trace(LogMessage.of(() -> imported.isEmpty() ? "Nothing imported" : "Imported "
|
this.logger.trace(LogMessage.of(() -> imported.isEmpty() ? "Nothing imported" : "Imported "
|
||||||
+ imported.size() + " location " + ((imported.size() != 1) ? "s" : "") + imported.keySet()));
|
+ imported.size() + " location " + ((imported.size() != 1) ? "s" : "") + imported.keySet()));
|
||||||
ConfigDataEnvironmentContributor processed = unprocessed.withChildren(importPhase,
|
ConfigDataEnvironmentContributor contributorAndChildren = contributor.withChildren(importPhase,
|
||||||
asContributors(activationContext, imported));
|
asContributors(imported));
|
||||||
result = new ConfigDataEnvironmentContributors(this.logger, this.bootstrapRegistry,
|
result = new ConfigDataEnvironmentContributors(this.logger, this.bootstrapRegistry,
|
||||||
result.getRoot().withReplacement(unprocessed, processed));
|
result.getRoot().withReplacement(contributor, contributorAndChildren));
|
||||||
processedCount++;
|
processed++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,22 +131,27 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen
|
||||||
return this.bootstrapRegistry;
|
return this.bootstrapRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConfigDataEnvironmentContributor getFirstUnprocessed(ConfigDataEnvironmentContributors contributors,
|
private ConfigDataEnvironmentContributor getNextToProcess(ConfigDataEnvironmentContributors contributors,
|
||||||
ConfigDataActivationContext activationContext, ImportPhase importPhase) {
|
ConfigDataActivationContext activationContext, ImportPhase importPhase) {
|
||||||
for (ConfigDataEnvironmentContributor contributor : contributors.getRoot()) {
|
for (ConfigDataEnvironmentContributor contributor : contributors.getRoot()) {
|
||||||
if (contributor.isActive(activationContext) && contributor.hasUnprocessedImports(importPhase)) {
|
if (contributor.getKind() == Kind.UNBOUND_IMPORT
|
||||||
|
|| isActiveWithUnprocessedImports(activationContext, importPhase, contributor)) {
|
||||||
return contributor;
|
return contributor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ConfigDataEnvironmentContributor> asContributors(ConfigDataActivationContext activationContext,
|
private boolean isActiveWithUnprocessedImports(ConfigDataActivationContext activationContext,
|
||||||
Map<ConfigDataLocation, ConfigData> imported) {
|
ImportPhase importPhase, ConfigDataEnvironmentContributor contributor) {
|
||||||
|
return contributor.isActive(activationContext) && contributor.hasUnprocessedImports(importPhase);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ConfigDataEnvironmentContributor> asContributors(Map<ConfigDataLocation, ConfigData> imported) {
|
||||||
List<ConfigDataEnvironmentContributor> contributors = new ArrayList<>(imported.size() * 5);
|
List<ConfigDataEnvironmentContributor> contributors = new ArrayList<>(imported.size() * 5);
|
||||||
imported.forEach((location, data) -> {
|
imported.forEach((location, data) -> {
|
||||||
for (int i = data.getPropertySources().size() - 1; i >= 0; i--) {
|
for (int i = data.getPropertySources().size() - 1; i >= 0; i--) {
|
||||||
contributors.add(ConfigDataEnvironmentContributor.ofImported(location, data, i, activationContext));
|
contributors.add(ConfigDataEnvironmentContributor.ofUnboundImport(location, data, i));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return Collections.unmodifiableList(contributors);
|
return Collections.unmodifiableList(contributors);
|
||||||
|
@ -155,14 +172,18 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen
|
||||||
* @return a binder instance
|
* @return a binder instance
|
||||||
*/
|
*/
|
||||||
Binder getBinder(ConfigDataActivationContext activationContext, BinderOption... options) {
|
Binder getBinder(ConfigDataActivationContext activationContext, BinderOption... options) {
|
||||||
return getBinder(activationContext, ObjectUtils.isEmpty(options) ? EnumSet.noneOf(BinderOption.class)
|
return getBinder(activationContext, asBinderOptionsSet(options));
|
||||||
: EnumSet.copyOf(Arrays.asList(options)));
|
}
|
||||||
|
|
||||||
|
private Set<BinderOption> asBinderOptionsSet(BinderOption... options) {
|
||||||
|
return ObjectUtils.isEmpty(options) ? EnumSet.noneOf(BinderOption.class)
|
||||||
|
: EnumSet.copyOf(Arrays.asList(options));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Binder getBinder(ConfigDataActivationContext activationContext, Set<BinderOption> options) {
|
private Binder getBinder(ConfigDataActivationContext activationContext, Set<BinderOption> options) {
|
||||||
boolean failOnInactiveSource = options.contains(BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE);
|
boolean failOnInactiveSource = options.contains(BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE);
|
||||||
Iterable<ConfigurationPropertySource> sources = () -> getBinderSources(activationContext,
|
Iterable<ConfigurationPropertySource> sources = () -> getBinderSources(activationContext,
|
||||||
!failOnInactiveSource);
|
!options.contains(BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE));
|
||||||
PlaceholdersResolver placeholdersResolver = new ConfigDataEnvironmentContributorPlaceholdersResolver(this.root,
|
PlaceholdersResolver placeholdersResolver = new ConfigDataEnvironmentContributorPlaceholdersResolver(this.root,
|
||||||
activationContext, failOnInactiveSource);
|
activationContext, failOnInactiveSource);
|
||||||
BindHandler bindHandler = !failOnInactiveSource ? null : new InactiveSourceChecker(activationContext);
|
BindHandler bindHandler = !failOnInactiveSource ? null : new InactiveSourceChecker(activationContext);
|
||||||
|
|
|
@ -122,7 +122,7 @@ class ConfigDataEnvironmentContributorPlaceholdersResolverTests {
|
||||||
private final boolean active;
|
private final boolean active;
|
||||||
|
|
||||||
protected TestConfigDataEnvironmentContributor(PropertySource<?> propertySource, boolean active) {
|
protected TestConfigDataEnvironmentContributor(PropertySource<?> propertySource, boolean active) {
|
||||||
super(Kind.ROOT, null, propertySource, null, null, null);
|
super(Kind.ROOT, null, propertySource, null, null, false, null);
|
||||||
this.active = active;
|
this.active = active;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.boot.cloud.CloudPlatform;
|
import org.springframework.boot.cloud.CloudPlatform;
|
||||||
import org.springframework.boot.context.config.ConfigDataEnvironmentContributor.ImportPhase;
|
import org.springframework.boot.context.config.ConfigDataEnvironmentContributor.ImportPhase;
|
||||||
import org.springframework.boot.context.config.ConfigDataEnvironmentContributor.Kind;
|
import org.springframework.boot.context.config.ConfigDataEnvironmentContributor.Kind;
|
||||||
|
import org.springframework.boot.context.properties.bind.Binder;
|
||||||
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
|
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
|
||||||
import org.springframework.mock.env.MockPropertySource;
|
import org.springframework.mock.env.MockPropertySource;
|
||||||
|
|
||||||
|
@ -63,8 +64,7 @@ class ConfigDataEnvironmentContributorTests {
|
||||||
MockPropertySource propertySource = new MockPropertySource();
|
MockPropertySource propertySource = new MockPropertySource();
|
||||||
propertySource.setProperty("spring.config.activate.on-cloud-platform", "kubernetes");
|
propertySource.setProperty("spring.config.activate.on-cloud-platform", "kubernetes");
|
||||||
ConfigData configData = new ConfigData(Collections.singleton(propertySource));
|
ConfigData configData = new ConfigData(Collections.singleton(propertySource));
|
||||||
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofImported(null, configData, 0,
|
ConfigDataEnvironmentContributor contributor = createBoundContributor(null, configData, 0);
|
||||||
this.activationContext);
|
|
||||||
assertThat(contributor.isActive(this.activationContext)).isTrue();
|
assertThat(contributor.isActive(this.activationContext)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,8 +73,7 @@ class ConfigDataEnvironmentContributorTests {
|
||||||
MockPropertySource propertySource = new MockPropertySource();
|
MockPropertySource propertySource = new MockPropertySource();
|
||||||
propertySource.setProperty("spring.config.activate.on-cloud-platform", "heroku");
|
propertySource.setProperty("spring.config.activate.on-cloud-platform", "heroku");
|
||||||
ConfigData configData = new ConfigData(Collections.singleton(propertySource));
|
ConfigData configData = new ConfigData(Collections.singleton(propertySource));
|
||||||
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofImported(null, configData, 0,
|
ConfigDataEnvironmentContributor contributor = createBoundContributor(null, configData, 0);
|
||||||
this.activationContext);
|
|
||||||
assertThat(contributor.isActive(this.activationContext)).isFalse();
|
assertThat(contributor.isActive(this.activationContext)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,8 +81,8 @@ class ConfigDataEnvironmentContributorTests {
|
||||||
void getLocationReturnsLocation() {
|
void getLocationReturnsLocation() {
|
||||||
ConfigData configData = new ConfigData(Collections.singleton(new MockPropertySource()));
|
ConfigData configData = new ConfigData(Collections.singleton(new MockPropertySource()));
|
||||||
ConfigDataLocation location = mock(ConfigDataLocation.class);
|
ConfigDataLocation location = mock(ConfigDataLocation.class);
|
||||||
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofImported(location, configData,
|
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofUnboundImport(location,
|
||||||
0, this.activationContext);
|
configData, 0);
|
||||||
assertThat(contributor.getLocation()).isSameAs(location);
|
assertThat(contributor.getLocation()).isSameAs(location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,8 +98,8 @@ class ConfigDataEnvironmentContributorTests {
|
||||||
MockPropertySource propertySource = new MockPropertySource();
|
MockPropertySource propertySource = new MockPropertySource();
|
||||||
propertySource.setProperty("spring", "boot");
|
propertySource.setProperty("spring", "boot");
|
||||||
ConfigData configData = new ConfigData(Collections.singleton(propertySource));
|
ConfigData configData = new ConfigData(Collections.singleton(propertySource));
|
||||||
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofImported(null, configData, 0,
|
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofUnboundImport(null,
|
||||||
this.activationContext);
|
configData, 0);
|
||||||
assertThat(contributor.getConfigurationPropertySource()
|
assertThat(contributor.getConfigurationPropertySource()
|
||||||
.getConfigurationProperty(ConfigurationPropertyName.of("spring")).getValue()).isEqualTo("boot");
|
.getConfigurationProperty(ConfigurationPropertyName.of("spring")).getValue()).isEqualTo("boot");
|
||||||
}
|
}
|
||||||
|
@ -108,8 +107,7 @@ class ConfigDataEnvironmentContributorTests {
|
||||||
@Test
|
@Test
|
||||||
void getImportsWhenPropertiesIsNullReturnsEmptyList() {
|
void getImportsWhenPropertiesIsNullReturnsEmptyList() {
|
||||||
ConfigData configData = new ConfigData(Collections.singleton(new MockPropertySource()));
|
ConfigData configData = new ConfigData(Collections.singleton(new MockPropertySource()));
|
||||||
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofImported(null, configData, 0,
|
ConfigDataEnvironmentContributor contributor = createBoundContributor(null, configData, 0);
|
||||||
this.activationContext);
|
|
||||||
assertThat(contributor.getImports()).isEmpty();
|
assertThat(contributor.getImports()).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,16 +116,14 @@ class ConfigDataEnvironmentContributorTests {
|
||||||
MockPropertySource propertySource = new MockPropertySource();
|
MockPropertySource propertySource = new MockPropertySource();
|
||||||
propertySource.setProperty("spring.config.import", "spring,boot");
|
propertySource.setProperty("spring.config.import", "spring,boot");
|
||||||
ConfigData configData = new ConfigData(Collections.singleton(propertySource));
|
ConfigData configData = new ConfigData(Collections.singleton(propertySource));
|
||||||
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofImported(null, configData, 0,
|
ConfigDataEnvironmentContributor contributor = createBoundContributor(null, configData, 0);
|
||||||
this.activationContext);
|
|
||||||
assertThat(contributor.getImports()).containsExactly("spring", "boot");
|
assertThat(contributor.getImports()).containsExactly("spring", "boot");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void hasUnprocessedImportsWhenNoImportsReturnsFalse() {
|
void hasUnprocessedImportsWhenNoImportsReturnsFalse() {
|
||||||
ConfigData configData = new ConfigData(Collections.singleton(new MockPropertySource()));
|
ConfigData configData = new ConfigData(Collections.singleton(new MockPropertySource()));
|
||||||
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofImported(null, configData, 0,
|
ConfigDataEnvironmentContributor contributor = createBoundContributor(null, configData, 0);
|
||||||
this.activationContext);
|
|
||||||
assertThat(contributor.hasUnprocessedImports(ImportPhase.BEFORE_PROFILE_ACTIVATION)).isFalse();
|
assertThat(contributor.hasUnprocessedImports(ImportPhase.BEFORE_PROFILE_ACTIVATION)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,8 +132,7 @@ class ConfigDataEnvironmentContributorTests {
|
||||||
MockPropertySource propertySource = new MockPropertySource();
|
MockPropertySource propertySource = new MockPropertySource();
|
||||||
propertySource.setProperty("spring.config.import", "springboot");
|
propertySource.setProperty("spring.config.import", "springboot");
|
||||||
ConfigData configData = new ConfigData(Collections.singleton(propertySource));
|
ConfigData configData = new ConfigData(Collections.singleton(propertySource));
|
||||||
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofImported(null, configData, 0,
|
ConfigDataEnvironmentContributor contributor = createBoundContributor(null, configData, 0);
|
||||||
this.activationContext);
|
|
||||||
assertThat(contributor.hasUnprocessedImports(ImportPhase.BEFORE_PROFILE_ACTIVATION)).isTrue();
|
assertThat(contributor.hasUnprocessedImports(ImportPhase.BEFORE_PROFILE_ACTIVATION)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,11 +141,9 @@ class ConfigDataEnvironmentContributorTests {
|
||||||
MockPropertySource propertySource = new MockPropertySource();
|
MockPropertySource propertySource = new MockPropertySource();
|
||||||
propertySource.setProperty("spring.config.import", "springboot");
|
propertySource.setProperty("spring.config.import", "springboot");
|
||||||
ConfigData configData = new ConfigData(Collections.singleton(propertySource));
|
ConfigData configData = new ConfigData(Collections.singleton(propertySource));
|
||||||
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofImported(null, configData, 0,
|
ConfigDataEnvironmentContributor contributor = createBoundContributor(null, configData, 0);
|
||||||
this.activationContext);
|
|
||||||
ConfigData childConfigData = new ConfigData(Collections.singleton(new MockPropertySource()));
|
ConfigData childConfigData = new ConfigData(Collections.singleton(new MockPropertySource()));
|
||||||
ConfigDataEnvironmentContributor childContributor = ConfigDataEnvironmentContributor.ofImported(null,
|
ConfigDataEnvironmentContributor childContributor = createBoundContributor(null, childConfigData, 0);
|
||||||
childConfigData, 0, this.activationContext);
|
|
||||||
ConfigDataEnvironmentContributor withChildren = contributor.withChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION,
|
ConfigDataEnvironmentContributor withChildren = contributor.withChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION,
|
||||||
Collections.singletonList(childContributor));
|
Collections.singletonList(childContributor));
|
||||||
assertThat(withChildren.hasUnprocessedImports(ImportPhase.BEFORE_PROFILE_ACTIVATION)).isFalse();
|
assertThat(withChildren.hasUnprocessedImports(ImportPhase.BEFORE_PROFILE_ACTIVATION)).isFalse();
|
||||||
|
@ -160,8 +153,7 @@ class ConfigDataEnvironmentContributorTests {
|
||||||
@Test
|
@Test
|
||||||
void getChildrenWhenHasNoChildrenReturnsEmptyList() {
|
void getChildrenWhenHasNoChildrenReturnsEmptyList() {
|
||||||
ConfigData configData = new ConfigData(Collections.singleton(new MockPropertySource()));
|
ConfigData configData = new ConfigData(Collections.singleton(new MockPropertySource()));
|
||||||
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofImported(null, configData, 0,
|
ConfigDataEnvironmentContributor contributor = createBoundContributor(null, configData, 0);
|
||||||
this.activationContext);
|
|
||||||
assertThat(contributor.getChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION)).isEmpty();
|
assertThat(contributor.getChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION)).isEmpty();
|
||||||
assertThat(contributor.getChildren(ImportPhase.AFTER_PROFILE_ACTIVATION)).isEmpty();
|
assertThat(contributor.getChildren(ImportPhase.AFTER_PROFILE_ACTIVATION)).isEmpty();
|
||||||
}
|
}
|
||||||
|
@ -171,11 +163,9 @@ class ConfigDataEnvironmentContributorTests {
|
||||||
MockPropertySource propertySource = new MockPropertySource();
|
MockPropertySource propertySource = new MockPropertySource();
|
||||||
propertySource.setProperty("spring.config.import", "springboot");
|
propertySource.setProperty("spring.config.import", "springboot");
|
||||||
ConfigData configData = new ConfigData(Collections.singleton(propertySource));
|
ConfigData configData = new ConfigData(Collections.singleton(propertySource));
|
||||||
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofImported(null, configData, 0,
|
ConfigDataEnvironmentContributor contributor = createBoundContributor(null, configData, 0);
|
||||||
this.activationContext);
|
|
||||||
ConfigData childConfigData = new ConfigData(Collections.singleton(new MockPropertySource()));
|
ConfigData childConfigData = new ConfigData(Collections.singleton(new MockPropertySource()));
|
||||||
ConfigDataEnvironmentContributor childContributor = ConfigDataEnvironmentContributor.ofImported(null,
|
ConfigDataEnvironmentContributor childContributor = createBoundContributor(null, childConfigData, 0);
|
||||||
childConfigData, 0, this.activationContext);
|
|
||||||
ConfigDataEnvironmentContributor withChildren = contributor.withChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION,
|
ConfigDataEnvironmentContributor withChildren = contributor.withChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION,
|
||||||
Collections.singletonList(childContributor));
|
Collections.singletonList(childContributor));
|
||||||
assertThat(withChildren.getChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION)).containsExactly(childContributor);
|
assertThat(withChildren.getChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION)).containsExactly(childContributor);
|
||||||
|
@ -184,35 +174,36 @@ class ConfigDataEnvironmentContributorTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void streamReturnsStream() {
|
void streamReturnsStream() {
|
||||||
ConfigDataEnvironmentContributor contributor = createContributor("a");
|
ConfigDataEnvironmentContributor contributor = createBoundContributor("a");
|
||||||
Stream<String> stream = contributor.stream().map(this::getLocationName);
|
Stream<String> stream = contributor.stream().map(this::getLocationName);
|
||||||
assertThat(stream).containsExactly("a");
|
assertThat(stream).containsExactly("a");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void iteratorWhenSingleContributorReturnsSingletonIterator() {
|
void iteratorWhenSingleContributorReturnsSingletonIterator() {
|
||||||
ConfigDataEnvironmentContributor contributor = createContributor("a");
|
ConfigDataEnvironmentContributor contributor = createBoundContributor("a");
|
||||||
assertThat(asLocationsList(contributor.iterator())).containsExactly("a");
|
assertThat(asLocationsList(contributor.iterator())).containsExactly("a");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void iteratorWhenTypicalStructureReturnsCorrectlyOrderedIterator() {
|
void iteratorWhenTypicalStructureReturnsCorrectlyOrderedIterator() {
|
||||||
ConfigDataEnvironmentContributor fileApplication = createContributor("file:application.properties");
|
ConfigDataEnvironmentContributor fileApplication = createBoundContributor("file:application.properties");
|
||||||
ConfigDataEnvironmentContributor fileProfile = createContributor("file:application-profile.properties");
|
ConfigDataEnvironmentContributor fileProfile = createBoundContributor("file:application-profile.properties");
|
||||||
ConfigDataEnvironmentContributor fileImports = createContributor("file:./");
|
ConfigDataEnvironmentContributor fileImports = createBoundContributor("file:./");
|
||||||
fileImports = fileImports.withChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION,
|
fileImports = fileImports.withChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION,
|
||||||
Collections.singletonList(fileApplication));
|
Collections.singletonList(fileApplication));
|
||||||
fileImports = fileImports.withChildren(ImportPhase.AFTER_PROFILE_ACTIVATION,
|
fileImports = fileImports.withChildren(ImportPhase.AFTER_PROFILE_ACTIVATION,
|
||||||
Collections.singletonList(fileProfile));
|
Collections.singletonList(fileProfile));
|
||||||
ConfigDataEnvironmentContributor classpathApplication = createContributor("classpath:application.properties");
|
ConfigDataEnvironmentContributor classpathApplication = createBoundContributor(
|
||||||
ConfigDataEnvironmentContributor classpathProfile = createContributor(
|
"classpath:application.properties");
|
||||||
|
ConfigDataEnvironmentContributor classpathProfile = createBoundContributor(
|
||||||
"classpath:application-profile.properties");
|
"classpath:application-profile.properties");
|
||||||
ConfigDataEnvironmentContributor classpathImports = createContributor("classpath:/");
|
ConfigDataEnvironmentContributor classpathImports = createBoundContributor("classpath:/");
|
||||||
classpathImports = classpathImports.withChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION,
|
classpathImports = classpathImports.withChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION,
|
||||||
Arrays.asList(classpathApplication));
|
Arrays.asList(classpathApplication));
|
||||||
classpathImports = classpathImports.withChildren(ImportPhase.AFTER_PROFILE_ACTIVATION,
|
classpathImports = classpathImports.withChildren(ImportPhase.AFTER_PROFILE_ACTIVATION,
|
||||||
Arrays.asList(classpathProfile));
|
Arrays.asList(classpathProfile));
|
||||||
ConfigDataEnvironmentContributor root = createContributor("root");
|
ConfigDataEnvironmentContributor root = createBoundContributor("root");
|
||||||
root = root.withChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION, Arrays.asList(fileImports, classpathImports));
|
root = root.withChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION, Arrays.asList(fileImports, classpathImports));
|
||||||
assertThat(asLocationsList(root.iterator())).containsExactly("file:application-profile.properties",
|
assertThat(asLocationsList(root.iterator())).containsExactly("file:application-profile.properties",
|
||||||
"file:application.properties", "file:./", "classpath:application-profile.properties",
|
"file:application.properties", "file:./", "classpath:application-profile.properties",
|
||||||
|
@ -221,8 +212,8 @@ class ConfigDataEnvironmentContributorTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void withChildrenReturnsNewInstanceWithChildren() {
|
void withChildrenReturnsNewInstanceWithChildren() {
|
||||||
ConfigDataEnvironmentContributor root = createContributor("root");
|
ConfigDataEnvironmentContributor root = createBoundContributor("root");
|
||||||
ConfigDataEnvironmentContributor child = createContributor("child");
|
ConfigDataEnvironmentContributor child = createBoundContributor("child");
|
||||||
ConfigDataEnvironmentContributor withChildren = root.withChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION,
|
ConfigDataEnvironmentContributor withChildren = root.withChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION,
|
||||||
Collections.singletonList(child));
|
Collections.singletonList(child));
|
||||||
assertThat(root.getChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION)).isEmpty();
|
assertThat(root.getChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION)).isEmpty();
|
||||||
|
@ -231,12 +222,12 @@ class ConfigDataEnvironmentContributorTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void withReplacementReplacesChild() {
|
void withReplacementReplacesChild() {
|
||||||
ConfigDataEnvironmentContributor root = createContributor("root");
|
ConfigDataEnvironmentContributor root = createBoundContributor("root");
|
||||||
ConfigDataEnvironmentContributor child = createContributor("child");
|
ConfigDataEnvironmentContributor child = createBoundContributor("child");
|
||||||
ConfigDataEnvironmentContributor grandchild = createContributor("grandchild");
|
ConfigDataEnvironmentContributor grandchild = createBoundContributor("grandchild");
|
||||||
child = child.withChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION, Collections.singletonList(grandchild));
|
child = child.withChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION, Collections.singletonList(grandchild));
|
||||||
root = root.withChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION, Collections.singletonList(child));
|
root = root.withChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION, Collections.singletonList(child));
|
||||||
ConfigDataEnvironmentContributor updated = createContributor("updated");
|
ConfigDataEnvironmentContributor updated = createBoundContributor("updated");
|
||||||
ConfigDataEnvironmentContributor withReplacement = root.withReplacement(grandchild, updated);
|
ConfigDataEnvironmentContributor withReplacement = root.withReplacement(grandchild, updated);
|
||||||
assertThat(asLocationsList(root.iterator())).containsExactly("grandchild", "child", "root");
|
assertThat(asLocationsList(root.iterator())).containsExactly("grandchild", "child", "root");
|
||||||
assertThat(asLocationsList(withReplacement.iterator())).containsExactly("updated", "child", "root");
|
assertThat(asLocationsList(withReplacement.iterator())).containsExactly("updated", "child", "root");
|
||||||
|
@ -244,8 +235,8 @@ class ConfigDataEnvironmentContributorTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void ofCreatesRootContributor() {
|
void ofCreatesRootContributor() {
|
||||||
ConfigDataEnvironmentContributor one = createContributor("one");
|
ConfigDataEnvironmentContributor one = createBoundContributor("one");
|
||||||
ConfigDataEnvironmentContributor two = createContributor("two");
|
ConfigDataEnvironmentContributor two = createBoundContributor("two");
|
||||||
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.of(Arrays.asList(one, two));
|
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.of(Arrays.asList(one, two));
|
||||||
assertThat(contributor.getKind()).isEqualTo(Kind.ROOT);
|
assertThat(contributor.getKind()).isEqualTo(Kind.ROOT);
|
||||||
assertThat(contributor.getLocation()).isNull();
|
assertThat(contributor.getLocation()).isNull();
|
||||||
|
@ -284,31 +275,14 @@ class ConfigDataEnvironmentContributorTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void ofImportedCreatesImportedContributor() {
|
void ofUnboundImportCreatesImportedContributor() {
|
||||||
TestLocation location = new TestLocation("test");
|
TestLocation location = new TestLocation("test");
|
||||||
MockPropertySource propertySource = new MockPropertySource();
|
MockPropertySource propertySource = new MockPropertySource();
|
||||||
propertySource.setProperty("spring.config.import", "test");
|
propertySource.setProperty("spring.config.import", "test");
|
||||||
ConfigData configData = new ConfigData(Collections.singleton(propertySource));
|
ConfigData configData = new ConfigData(Collections.singleton(propertySource));
|
||||||
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofImported(location, configData,
|
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofUnboundImport(location,
|
||||||
0, this.activationContext);
|
configData, 0);
|
||||||
assertThat(contributor.getKind()).isEqualTo(Kind.IMPORTED);
|
assertThat(contributor.getKind()).isEqualTo(Kind.UNBOUND_IMPORT);
|
||||||
assertThat(contributor.getLocation()).isSameAs(location);
|
|
||||||
assertThat(contributor.getImports()).containsExactly("test");
|
|
||||||
assertThat(contributor.isActive(this.activationContext)).isTrue();
|
|
||||||
assertThat(contributor.getPropertySource()).isEqualTo(propertySource);
|
|
||||||
assertThat(contributor.getConfigurationPropertySource()).isNotNull();
|
|
||||||
assertThat(contributor.getChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION)).isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void ofImportedWhenConfigDataHasIgnoreImportsOptionsCreatesImportedContributorWithoutImports() {
|
|
||||||
TestLocation location = new TestLocation("test");
|
|
||||||
MockPropertySource propertySource = new MockPropertySource();
|
|
||||||
propertySource.setProperty("spring.config.import", "test");
|
|
||||||
ConfigData configData = new ConfigData(Collections.singleton(propertySource), ConfigData.Option.IGNORE_IMPORTS);
|
|
||||||
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofImported(location, configData,
|
|
||||||
0, this.activationContext);
|
|
||||||
assertThat(contributor.getKind()).isEqualTo(Kind.IMPORTED);
|
|
||||||
assertThat(contributor.getLocation()).isSameAs(location);
|
assertThat(contributor.getLocation()).isSameAs(location);
|
||||||
assertThat(contributor.getImports()).isEmpty();
|
assertThat(contributor.getImports()).isEmpty();
|
||||||
assertThat(contributor.isActive(this.activationContext)).isTrue();
|
assertThat(contributor.isActive(this.activationContext)).isTrue();
|
||||||
|
@ -318,17 +292,56 @@ class ConfigDataEnvironmentContributorTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void ofImportedWhenHasUseLegacyPropertyThrowsException() {
|
void bindCreatesImportedContributor() {
|
||||||
|
TestLocation location = new TestLocation("test");
|
||||||
MockPropertySource propertySource = new MockPropertySource();
|
MockPropertySource propertySource = new MockPropertySource();
|
||||||
propertySource.setProperty("spring.config.use-legacy-processing", "true");
|
propertySource.setProperty("spring.config.import", "test");
|
||||||
assertThatExceptionOfType(UseLegacyConfigProcessingException.class)
|
ConfigData configData = new ConfigData(Collections.singleton(propertySource));
|
||||||
.isThrownBy(() -> ConfigDataEnvironmentContributor.ofImported(null,
|
ConfigDataEnvironmentContributor contributor = createBoundContributor(location, configData, 0);
|
||||||
new ConfigData(Collections.singleton(propertySource)), 0, this.activationContext));
|
assertThat(contributor.getKind()).isEqualTo(Kind.BOUND_IMPORT);
|
||||||
|
assertThat(contributor.getLocation()).isSameAs(location);
|
||||||
|
assertThat(contributor.getImports()).containsExactly("test");
|
||||||
|
assertThat(contributor.isActive(this.activationContext)).isTrue();
|
||||||
|
assertThat(contributor.getPropertySource()).isEqualTo(propertySource);
|
||||||
|
assertThat(contributor.getConfigurationPropertySource()).isNotNull();
|
||||||
|
assertThat(contributor.getChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION)).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConfigDataEnvironmentContributor createContributor(String location) {
|
@Test
|
||||||
return ConfigDataEnvironmentContributor.ofImported(new TestLocation(location),
|
void bindWhenConfigDataHasIgnoreImportsOptionsCreatesImportedContributorWithoutImports() {
|
||||||
new ConfigData(Collections.singleton(new MockPropertySource())), 0, this.activationContext);
|
TestLocation location = new TestLocation("test");
|
||||||
|
MockPropertySource propertySource = new MockPropertySource();
|
||||||
|
propertySource.setProperty("spring.config.import", "test");
|
||||||
|
ConfigData configData = new ConfigData(Collections.singleton(propertySource), ConfigData.Option.IGNORE_IMPORTS);
|
||||||
|
ConfigDataEnvironmentContributor contributor = createBoundContributor(location, configData, 0);
|
||||||
|
assertThat(contributor.getKind()).isEqualTo(Kind.BOUND_IMPORT);
|
||||||
|
assertThat(contributor.getLocation()).isSameAs(location);
|
||||||
|
assertThat(contributor.getImports()).isEmpty();
|
||||||
|
assertThat(contributor.isActive(this.activationContext)).isTrue();
|
||||||
|
assertThat(contributor.getPropertySource()).isEqualTo(propertySource);
|
||||||
|
assertThat(contributor.getConfigurationPropertySource()).isNotNull();
|
||||||
|
assertThat(contributor.getChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION)).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void bindWhenHasUseLegacyPropertyThrowsException() {
|
||||||
|
MockPropertySource propertySource = new MockPropertySource();
|
||||||
|
propertySource.setProperty("spring.config.use-legacy-processing", "true");
|
||||||
|
assertThatExceptionOfType(UseLegacyConfigProcessingException.class).isThrownBy(
|
||||||
|
() -> createBoundContributor(null, new ConfigData(Collections.singleton(propertySource)), 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ConfigDataEnvironmentContributor createBoundContributor(String location) {
|
||||||
|
return createBoundContributor(new TestLocation(location),
|
||||||
|
new ConfigData(Collections.singleton(new MockPropertySource())), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ConfigDataEnvironmentContributor createBoundContributor(ConfigDataLocation location, ConfigData configData,
|
||||||
|
int propertySourceIndex) {
|
||||||
|
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofUnboundImport(location,
|
||||||
|
configData, propertySourceIndex);
|
||||||
|
Binder binder = new Binder(contributor.getConfigurationPropertySource());
|
||||||
|
return contributor.withBoundProperties(binder);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> asLocationsList(Iterator<ConfigDataEnvironmentContributor> iterator) {
|
private List<String> asLocationsList(Iterator<ConfigDataEnvironmentContributor> iterator) {
|
||||||
|
|
|
@ -268,10 +268,8 @@ class ConfigDataEnvironmentContributorsTests {
|
||||||
MockPropertySource secondPropertySource = new MockPropertySource();
|
MockPropertySource secondPropertySource = new MockPropertySource();
|
||||||
secondPropertySource.setProperty("test", "two");
|
secondPropertySource.setProperty("test", "two");
|
||||||
ConfigData configData = new ConfigData(Arrays.asList(firstPropertySource, secondPropertySource));
|
ConfigData configData = new ConfigData(Arrays.asList(firstPropertySource, secondPropertySource));
|
||||||
ConfigDataEnvironmentContributor firstContributor = ConfigDataEnvironmentContributor.ofImported(null,
|
ConfigDataEnvironmentContributor firstContributor = createBoundImportContributor(configData, 0);
|
||||||
configData, 0, this.activationContext);
|
ConfigDataEnvironmentContributor secondContributor = createBoundImportContributor(configData, 1);
|
||||||
ConfigDataEnvironmentContributor secondContributor = ConfigDataEnvironmentContributor.ofImported(null,
|
|
||||||
configData, 1, this.activationContext);
|
|
||||||
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
||||||
this.bootstrapRegistry, Arrays.asList(firstContributor, secondContributor));
|
this.bootstrapRegistry, Arrays.asList(firstContributor, secondContributor));
|
||||||
Binder binder = contributors.getBinder(this.activationContext);
|
Binder binder = contributors.getBinder(this.activationContext);
|
||||||
|
@ -286,10 +284,8 @@ class ConfigDataEnvironmentContributorsTests {
|
||||||
MockPropertySource secondPropertySource = new MockPropertySource();
|
MockPropertySource secondPropertySource = new MockPropertySource();
|
||||||
secondPropertySource.setProperty("test", "two");
|
secondPropertySource.setProperty("test", "two");
|
||||||
ConfigData configData = new ConfigData(Arrays.asList(firstPropertySource, secondPropertySource));
|
ConfigData configData = new ConfigData(Arrays.asList(firstPropertySource, secondPropertySource));
|
||||||
ConfigDataEnvironmentContributor firstContributor = ConfigDataEnvironmentContributor.ofImported(null,
|
ConfigDataEnvironmentContributor firstContributor = createBoundImportContributor(configData, 0);
|
||||||
configData, 0, this.activationContext);
|
ConfigDataEnvironmentContributor secondContributor = createBoundImportContributor(configData, 1);
|
||||||
ConfigDataEnvironmentContributor secondContributor = ConfigDataEnvironmentContributor.ofImported(null,
|
|
||||||
configData, 1, this.activationContext);
|
|
||||||
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
||||||
this.bootstrapRegistry, Arrays.asList(firstContributor, secondContributor));
|
this.bootstrapRegistry, Arrays.asList(firstContributor, secondContributor));
|
||||||
Binder binder = contributors.getBinder(this.activationContext);
|
Binder binder = contributors.getBinder(this.activationContext);
|
||||||
|
@ -317,10 +313,8 @@ class ConfigDataEnvironmentContributorsTests {
|
||||||
secondPropertySource.setProperty("other", "two");
|
secondPropertySource.setProperty("other", "two");
|
||||||
secondPropertySource.setProperty("test", "${other}");
|
secondPropertySource.setProperty("test", "${other}");
|
||||||
ConfigData configData = new ConfigData(Arrays.asList(firstPropertySource, secondPropertySource));
|
ConfigData configData = new ConfigData(Arrays.asList(firstPropertySource, secondPropertySource));
|
||||||
ConfigDataEnvironmentContributor firstContributor = ConfigDataEnvironmentContributor.ofImported(null,
|
ConfigDataEnvironmentContributor firstContributor = createBoundImportContributor(configData, 0);
|
||||||
configData, 0, this.activationContext);
|
ConfigDataEnvironmentContributor secondContributor = createBoundImportContributor(configData, 1);
|
||||||
ConfigDataEnvironmentContributor secondContributor = ConfigDataEnvironmentContributor.ofImported(null,
|
|
||||||
configData, 1, this.activationContext);
|
|
||||||
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
||||||
this.bootstrapRegistry, Arrays.asList(firstContributor, secondContributor));
|
this.bootstrapRegistry, Arrays.asList(firstContributor, secondContributor));
|
||||||
Binder binder = contributors.getBinder(this.activationContext);
|
Binder binder = contributors.getBinder(this.activationContext);
|
||||||
|
@ -335,10 +329,8 @@ class ConfigDataEnvironmentContributorsTests {
|
||||||
MockPropertySource secondPropertySource = new MockPropertySource();
|
MockPropertySource secondPropertySource = new MockPropertySource();
|
||||||
secondPropertySource.setProperty("test", "two");
|
secondPropertySource.setProperty("test", "two");
|
||||||
ConfigData configData = new ConfigData(Arrays.asList(firstPropertySource, secondPropertySource));
|
ConfigData configData = new ConfigData(Arrays.asList(firstPropertySource, secondPropertySource));
|
||||||
ConfigDataEnvironmentContributor firstContributor = ConfigDataEnvironmentContributor.ofImported(null,
|
ConfigDataEnvironmentContributor firstContributor = createBoundImportContributor(configData, 0);
|
||||||
configData, 0, this.activationContext);
|
ConfigDataEnvironmentContributor secondContributor = createBoundImportContributor(configData, 1);
|
||||||
ConfigDataEnvironmentContributor secondContributor = ConfigDataEnvironmentContributor.ofImported(null,
|
|
||||||
configData, 1, this.activationContext);
|
|
||||||
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
||||||
this.bootstrapRegistry, Arrays.asList(firstContributor, secondContributor));
|
this.bootstrapRegistry, Arrays.asList(firstContributor, secondContributor));
|
||||||
Binder binder = contributors.getBinder(this.activationContext, BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE);
|
Binder binder = contributors.getBinder(this.activationContext, BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE);
|
||||||
|
@ -354,10 +346,8 @@ class ConfigDataEnvironmentContributorsTests {
|
||||||
secondPropertySource.setProperty("spring.config.activate.on-profile", "production");
|
secondPropertySource.setProperty("spring.config.activate.on-profile", "production");
|
||||||
secondPropertySource.setProperty("test", "two");
|
secondPropertySource.setProperty("test", "two");
|
||||||
ConfigData configData = new ConfigData(Arrays.asList(firstPropertySource, secondPropertySource));
|
ConfigData configData = new ConfigData(Arrays.asList(firstPropertySource, secondPropertySource));
|
||||||
ConfigDataEnvironmentContributor firstContributor = ConfigDataEnvironmentContributor.ofImported(null,
|
ConfigDataEnvironmentContributor firstContributor = createBoundImportContributor(configData, 0);
|
||||||
configData, 0, this.activationContext);
|
ConfigDataEnvironmentContributor secondContributor = createBoundImportContributor(configData, 1);
|
||||||
ConfigDataEnvironmentContributor secondContributor = ConfigDataEnvironmentContributor.ofImported(null,
|
|
||||||
configData, 1, this.activationContext);
|
|
||||||
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
||||||
this.bootstrapRegistry, Arrays.asList(firstContributor, secondContributor));
|
this.bootstrapRegistry, Arrays.asList(firstContributor, secondContributor));
|
||||||
Binder binder = contributors.getBinder(this.activationContext, BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE);
|
Binder binder = contributors.getBinder(this.activationContext, BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE);
|
||||||
|
@ -374,10 +364,8 @@ class ConfigDataEnvironmentContributorsTests {
|
||||||
secondPropertySource.setProperty("test", "${other}");
|
secondPropertySource.setProperty("test", "${other}");
|
||||||
secondPropertySource.setProperty("other", "one");
|
secondPropertySource.setProperty("other", "one");
|
||||||
ConfigData configData = new ConfigData(Arrays.asList(firstPropertySource, secondPropertySource));
|
ConfigData configData = new ConfigData(Arrays.asList(firstPropertySource, secondPropertySource));
|
||||||
ConfigDataEnvironmentContributor firstContributor = ConfigDataEnvironmentContributor.ofImported(null,
|
ConfigDataEnvironmentContributor firstContributor = createBoundImportContributor(configData, 0);
|
||||||
configData, 0, this.activationContext);
|
ConfigDataEnvironmentContributor secondContributor = createBoundImportContributor(configData, 1);
|
||||||
ConfigDataEnvironmentContributor secondContributor = ConfigDataEnvironmentContributor.ofImported(null,
|
|
||||||
configData, 1, this.activationContext);
|
|
||||||
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
||||||
this.bootstrapRegistry, Arrays.asList(firstContributor, secondContributor));
|
this.bootstrapRegistry, Arrays.asList(firstContributor, secondContributor));
|
||||||
Binder binder = contributors.getBinder(this.activationContext, BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE);
|
Binder binder = contributors.getBinder(this.activationContext, BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE);
|
||||||
|
@ -385,6 +373,14 @@ class ConfigDataEnvironmentContributorsTests {
|
||||||
.satisfies((ex) -> assertThat(ex.getCause()).isInstanceOf(InactiveConfigDataAccessException.class));
|
.satisfies((ex) -> assertThat(ex.getCause()).isInstanceOf(InactiveConfigDataAccessException.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ConfigDataEnvironmentContributor createBoundImportContributor(ConfigData configData,
|
||||||
|
int propertySourceIndex) {
|
||||||
|
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofUnboundImport(null,
|
||||||
|
configData, propertySourceIndex);
|
||||||
|
Binder binder = new Binder(contributor.getConfigurationPropertySource());
|
||||||
|
return contributor.withBoundProperties(binder);
|
||||||
|
}
|
||||||
|
|
||||||
private static class TestConfigDataLocation extends ConfigDataLocation {
|
private static class TestConfigDataLocation extends ConfigDataLocation {
|
||||||
|
|
||||||
private final String value;
|
private final String value;
|
||||||
|
|
|
@ -35,6 +35,7 @@ import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.WebApplicationType;
|
import org.springframework.boot.WebApplicationType;
|
||||||
|
import org.springframework.boot.context.properties.bind.BindException;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.core.env.ConfigurableEnvironment;
|
import org.springframework.core.env.ConfigurableEnvironment;
|
||||||
|
@ -514,6 +515,27 @@ class ConfigDataEnvironmentPostProcessorIntegrationTests {
|
||||||
() -> this.application.run("--spring.config.location=classpath:invalidproperty.properties"));
|
() -> this.application.run("--spring.config.location=classpath:invalidproperty.properties"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void runWhenImportUsesPlaceholder() {
|
||||||
|
ConfigurableApplicationContext context = this.application
|
||||||
|
.run("--spring.config.location=classpath:application-import-with-placeholder.properties");
|
||||||
|
assertThat(context.getEnvironment().getProperty("my.value")).isEqualTo("iwasimported");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void runWhenImportFromEarlierDocumentUsesPlaceholder() {
|
||||||
|
ConfigurableApplicationContext context = this.application
|
||||||
|
.run("--spring.config.location=classpath:application-import-with-placeholder-in-document.properties");
|
||||||
|
assertThat(context.getEnvironment().getProperty("my.value")).isEqualTo("iwasimported");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void runWhenHasPropertyInProfileDocumentThrowsException() {
|
||||||
|
assertThatExceptionOfType(BindException.class).isThrownBy(() -> this.application.run(
|
||||||
|
"--spring.config.location=classpath:application-import-with-placeholder-in-profile-document.properties"))
|
||||||
|
.withCauseInstanceOf(InactiveConfigDataAccessException.class);
|
||||||
|
}
|
||||||
|
|
||||||
private Condition<ConfigurableEnvironment> matchingPropertySource(final String sourceName) {
|
private Condition<ConfigurableEnvironment> matchingPropertySource(final String sourceName) {
|
||||||
return new Condition<ConfigurableEnvironment>("environment containing property source " + sourceName) {
|
return new Condition<ConfigurableEnvironment>("environment containing property source " + sourceName) {
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
my.value=iwasimported
|
|
@ -0,0 +1,3 @@
|
||||||
|
my.import=application-import-with-placeholder-imported
|
||||||
|
#---
|
||||||
|
spring.config.import=classpath:${my.import}.properties
|
|
@ -0,0 +1,6 @@
|
||||||
|
my.import=application-import-with-placeholder-imported
|
||||||
|
#---
|
||||||
|
spring.config.import=classpath:${my.import}.properties
|
||||||
|
#---
|
||||||
|
my.import=badbadbad
|
||||||
|
spring.config.activate.on-profile=missing
|
|
@ -0,0 +1,2 @@
|
||||||
|
my.import=application-import-with-placeholder-imported
|
||||||
|
spring.config.import=classpath:${my.import}.properties
|
Loading…
Reference in New Issue