Merge branch '2.4.x'

Closes gh-24793
pull/24817/head
Phillip Webb 4 years ago
commit 48e00fc7f4

@ -34,7 +34,6 @@ import org.springframework.boot.context.properties.bind.BindException;
import org.springframework.boot.context.properties.bind.Bindable; import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder; import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.bind.PlaceholdersResolver; import org.springframework.boot.context.properties.bind.PlaceholdersResolver;
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource; import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.logging.DeferredLogFactory; import org.springframework.boot.logging.DeferredLogFactory;
import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.ConfigurableEnvironment;
@ -98,9 +97,6 @@ class ConfigDataEnvironment {
private static final ConfigDataLocation[] EMPTY_LOCATIONS = new ConfigDataLocation[0]; private static final ConfigDataLocation[] EMPTY_LOCATIONS = new ConfigDataLocation[0];
private static final ConfigurationPropertyName INCLUDE_PROFILES = ConfigurationPropertyName
.of(Profiles.INCLUDE_PROFILES_PROPERTY_NAME);
private static final Bindable<ConfigDataLocation[]> CONFIG_DATA_LOCATION_ARRAY = Bindable private static final Bindable<ConfigDataLocation[]> CONFIG_DATA_LOCATION_ARRAY = Bindable
.of(ConfigDataLocation[].class); .of(ConfigDataLocation[].class);
@ -293,9 +289,9 @@ class ConfigDataEnvironment {
continue; continue;
} }
Binder binder = new Binder(Collections.singleton(source), placeholdersResolver); Binder binder = new Binder(Collections.singleton(source), placeholdersResolver);
binder.bind(INCLUDE_PROFILES, STRING_LIST).ifBound((includes) -> { binder.bind(Profiles.INCLUDE_PROFILES, STRING_LIST).ifBound((includes) -> {
if (!contributor.isActive(activationContext)) { if (!contributor.isActive(activationContext)) {
InactiveConfigDataAccessException.throwIfPropertyFound(contributor, INCLUDE_PROFILES); InactiveConfigDataAccessException.throwIfPropertyFound(contributor, Profiles.INCLUDE_PROFILES);
} }
result.addAll(includes); result.addAll(includes);
}); });

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2020 the original author or authors. * Copyright 2012-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -55,6 +55,8 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
private final ConfigDataResource resource; private final ConfigDataResource resource;
private final boolean profileSpecific;
private final PropertySource<?> propertySource; private final PropertySource<?> propertySource;
private final ConfigurationPropertySource configurationPropertySource; private final ConfigurationPropertySource configurationPropertySource;
@ -72,6 +74,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
* @param kind the contributor kind * @param kind the contributor kind
* @param location the location of this contributor * @param location the location of this contributor
* @param resource the resource that contributed the data or {@code null} * @param resource the resource that contributed the data or {@code null}
* @param profileSpecific if the contributor is from a profile specific import
* @param propertySource the property source for the data or {@code null} * @param propertySource the property source for the data or {@code null}
* @param configurationPropertySource the configuration property source for the data * @param configurationPropertySource the configuration property source for the data
* or {@code null} * or {@code null}
@ -80,12 +83,13 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
* @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, ConfigDataResource resource, ConfigDataEnvironmentContributor(Kind kind, ConfigDataLocation location, ConfigDataResource resource,
PropertySource<?> propertySource, ConfigurationPropertySource configurationPropertySource, boolean profileSpecific, PropertySource<?> propertySource,
ConfigDataProperties properties, boolean ignoreImports, 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.resource = resource; this.resource = resource;
this.profileSpecific = profileSpecific;
this.properties = properties; this.properties = properties;
this.propertySource = propertySource; this.propertySource = propertySource;
this.configurationPropertySource = configurationPropertySource; this.configurationPropertySource = configurationPropertySource;
@ -122,6 +126,14 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
return this.resource; return this.resource;
} }
/**
* Return if the contributor is from a profile specific import.
* @return if the contributor is profile specific
*/
boolean isProfileSpecific() {
return this.profileSpecific;
}
/** /**
* Return the property source for this contributor. * Return the property source for this contributor.
* @return the property source or {@code null} * @return the property source or {@code null}
@ -201,7 +213,8 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
properties = properties.withoutImports(); properties = properties.withoutImports();
} }
return new ConfigDataEnvironmentContributor(Kind.BOUND_IMPORT, this.location, this.resource, return new ConfigDataEnvironmentContributor(Kind.BOUND_IMPORT, this.location, this.resource,
this.propertySource, this.configurationPropertySource, properties, this.ignoreImports, null); this.profileSpecific, this.propertySource, this.configurationPropertySource, properties,
this.ignoreImports, null);
} }
/** /**
@ -215,8 +228,9 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
List<ConfigDataEnvironmentContributor> children) { List<ConfigDataEnvironmentContributor> children) {
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.resource, this.propertySource, return new ConfigDataEnvironmentContributor(this.kind, this.location, this.resource, this.profileSpecific,
this.configurationPropertySource, this.properties, this.ignoreImports, updatedChildren); this.propertySource, this.configurationPropertySource, this.properties, this.ignoreImports,
updatedChildren);
} }
/** /**
@ -240,8 +254,9 @@ 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.resource, this.propertySource, return new ConfigDataEnvironmentContributor(this.kind, this.location, this.resource, this.profileSpecific,
this.configurationPropertySource, this.properties, this.ignoreImports, updatedChildren); this.propertySource, this.configurationPropertySource, this.properties, this.ignoreImports,
updatedChildren);
} }
/** /**
@ -252,7 +267,7 @@ 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, null, false, children); return new ConfigDataEnvironmentContributor(Kind.ROOT, null, null, false, null, null, null, false, children);
} }
/** /**
@ -265,8 +280,8 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
static ConfigDataEnvironmentContributor ofInitialImport(ConfigDataLocation initialImport) { static ConfigDataEnvironmentContributor ofInitialImport(ConfigDataLocation initialImport) {
List<ConfigDataLocation> imports = Collections.singletonList(initialImport); List<ConfigDataLocation> imports = Collections.singletonList(initialImport);
ConfigDataProperties properties = new ConfigDataProperties(imports, null); ConfigDataProperties properties = new ConfigDataProperties(imports, null);
return new ConfigDataEnvironmentContributor(Kind.INITIAL_IMPORT, null, null, null, null, properties, false, return new ConfigDataEnvironmentContributor(Kind.INITIAL_IMPORT, null, null, false, null, null, properties,
null); false, null);
} }
/** /**
@ -277,7 +292,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
* @return a new {@link ConfigDataEnvironmentContributor} instance * @return a new {@link ConfigDataEnvironmentContributor} instance
*/ */
static ConfigDataEnvironmentContributor ofExisting(PropertySource<?> propertySource) { static ConfigDataEnvironmentContributor ofExisting(PropertySource<?> propertySource) {
return new ConfigDataEnvironmentContributor(Kind.EXISTING, null, null, propertySource, return new ConfigDataEnvironmentContributor(Kind.EXISTING, null, null, false, propertySource,
ConfigurationPropertySource.from(propertySource), null, false, null); ConfigurationPropertySource.from(propertySource), null, false, null);
} }
@ -287,26 +302,29 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
* import further contributors later. * import further contributors later.
* @param location the location of this contributor * @param location the location of this contributor
* @param resource the config data resource * @param resource the config data resource
* @param profileSpecific if the contributor is from a profile specific import
* @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
* @return a new {@link ConfigDataEnvironmentContributor} instance * @return a new {@link ConfigDataEnvironmentContributor} instance
*/ */
static ConfigDataEnvironmentContributor ofUnboundImport(ConfigDataLocation location, ConfigDataResource resource, static ConfigDataEnvironmentContributor ofUnboundImport(ConfigDataLocation location, ConfigDataResource resource,
ConfigData configData, int propertySourceIndex) { boolean profileSpecific, ConfigData configData, int propertySourceIndex) {
PropertySource<?> propertySource = configData.getPropertySources().get(propertySourceIndex); PropertySource<?> propertySource = configData.getPropertySources().get(propertySourceIndex);
ConfigurationPropertySource configurationPropertySource = ConfigurationPropertySource.from(propertySource); ConfigurationPropertySource configurationPropertySource = ConfigurationPropertySource.from(propertySource);
boolean ignoreImports = configData.getOptions().contains(ConfigData.Option.IGNORE_IMPORTS); boolean ignoreImports = configData.getOptions().contains(ConfigData.Option.IGNORE_IMPORTS);
return new ConfigDataEnvironmentContributor(Kind.UNBOUND_IMPORT, location, resource, propertySource, return new ConfigDataEnvironmentContributor(Kind.UNBOUND_IMPORT, location, resource, profileSpecific,
configurationPropertySource, null, ignoreImports, null); propertySource, configurationPropertySource, null, ignoreImports, null);
} }
/** /**
* Factory method to create an {@link Kind#EMPTY_LOCATION empty location} contributor. * Factory method to create an {@link Kind#EMPTY_LOCATION empty location} contributor.
* @param location the location of this contributor * @param location the location of this contributor
* @param profileSpecific if the contributor is from a profile specific import
* @return a new {@link ConfigDataEnvironmentContributor} instance * @return a new {@link ConfigDataEnvironmentContributor} instance
*/ */
static ConfigDataEnvironmentContributor ofEmptyLocation(ConfigDataLocation location) { static ConfigDataEnvironmentContributor ofEmptyLocation(ConfigDataLocation location, boolean profileSpecific) {
return new ConfigDataEnvironmentContributor(Kind.EMPTY_LOCATION, location, null, null, null, null, true, null); return new ConfigDataEnvironmentContributor(Kind.EMPTY_LOCATION, location, null, profileSpecific, null, null,
null, true, null);
} }
/** /**

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2020 the original author or authors. * Copyright 2012-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -163,12 +163,14 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen
imported.forEach((resolutionResult, data) -> { imported.forEach((resolutionResult, data) -> {
ConfigDataLocation location = resolutionResult.getLocation(); ConfigDataLocation location = resolutionResult.getLocation();
ConfigDataResource resource = resolutionResult.getResource(); ConfigDataResource resource = resolutionResult.getResource();
boolean profileSpecific = resolutionResult.isProfileSpecific();
if (data.getPropertySources().isEmpty()) { if (data.getPropertySources().isEmpty()) {
contributors.add(ConfigDataEnvironmentContributor.ofEmptyLocation(location)); contributors.add(ConfigDataEnvironmentContributor.ofEmptyLocation(location, profileSpecific));
} }
else { else {
for (int i = data.getPropertySources().size() - 1; i >= 0; i--) { for (int i = data.getPropertySources().size() - 1; i >= 0; i--) {
contributors.add(ConfigDataEnvironmentContributor.ofUnboundImport(location, resource, data, i)); contributors.add(ConfigDataEnvironmentContributor.ofUnboundImport(location, resource,
profileSpecific, data, i));
} }
} }
}); });

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2020 the original author or authors. * Copyright 2012-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -111,21 +111,21 @@ class ConfigDataLocationResolvers {
private List<ConfigDataResolutionResult> resolve(ConfigDataLocationResolver<?> resolver, private List<ConfigDataResolutionResult> resolve(ConfigDataLocationResolver<?> resolver,
ConfigDataLocationResolverContext context, ConfigDataLocation location, Profiles profiles) { ConfigDataLocationResolverContext context, ConfigDataLocation location, Profiles profiles) {
List<ConfigDataResolutionResult> resolved = resolve(location, () -> resolver.resolve(context, location)); List<ConfigDataResolutionResult> resolved = resolve(location, false, () -> resolver.resolve(context, location));
if (profiles == null) { if (profiles == null) {
return resolved; return resolved;
} }
List<ConfigDataResolutionResult> profileSpecific = resolve(location, List<ConfigDataResolutionResult> profileSpecific = resolve(location, true,
() -> resolver.resolveProfileSpecific(context, location, profiles)); () -> resolver.resolveProfileSpecific(context, location, profiles));
return merge(resolved, profileSpecific); return merge(resolved, profileSpecific);
} }
private List<ConfigDataResolutionResult> resolve(ConfigDataLocation location, private List<ConfigDataResolutionResult> resolve(ConfigDataLocation location, boolean profileSpecific,
Supplier<List<? extends ConfigDataResource>> resolveAction) { Supplier<List<? extends ConfigDataResource>> resolveAction) {
List<ConfigDataResource> resources = nonNullList(resolveAction.get()); List<ConfigDataResource> resources = nonNullList(resolveAction.get());
List<ConfigDataResolutionResult> resolved = new ArrayList<>(resources.size()); List<ConfigDataResolutionResult> resolved = new ArrayList<>(resources.size());
for (ConfigDataResource resource : resources) { for (ConfigDataResource resource : resources) {
resolved.add(new ConfigDataResolutionResult(location, resource)); resolved.add(new ConfigDataResolutionResult(location, resource, profileSpecific));
} }
return resolved; return resolved;
} }

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2020 the original author or authors. * Copyright 2012-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -94,7 +94,7 @@ class ConfigDataProperties {
ConfigDataProperties withLegacyProfiles(String[] legacyProfiles, ConfigurationProperty property) { ConfigDataProperties withLegacyProfiles(String[] legacyProfiles, ConfigurationProperty property) {
if (this.activate != null && !ObjectUtils.isEmpty(this.activate.onProfile)) { if (this.activate != null && !ObjectUtils.isEmpty(this.activate.onProfile)) {
throw new InvalidConfigDataPropertyException(property, NAME.append("activate.on-profile"), null); throw new InvalidConfigDataPropertyException(property, false, NAME.append("activate.on-profile"), null);
} }
return new ConfigDataProperties(this.imports, new Activate(this.activate.onCloudPlatform, legacyProfiles)); return new ConfigDataProperties(this.imports, new Activate(this.activate.onCloudPlatform, legacyProfiles));
} }

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2020 the original author or authors. * Copyright 2012-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -28,9 +28,12 @@ class ConfigDataResolutionResult {
private final ConfigDataResource resource; private final ConfigDataResource resource;
ConfigDataResolutionResult(ConfigDataLocation location, ConfigDataResource resource) { private final boolean profileSpecific;
ConfigDataResolutionResult(ConfigDataLocation location, ConfigDataResource resource, boolean profileSpecific) {
this.location = location; this.location = location;
this.resource = resource; this.resource = resource;
this.profileSpecific = profileSpecific;
} }
ConfigDataLocation getLocation() { ConfigDataLocation getLocation() {
@ -41,4 +44,8 @@ class ConfigDataResolutionResult {
return this.resource; return this.resource;
} }
boolean isProfileSpecific() {
return this.profileSpecific;
}
} }

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2020 the original author or authors. * Copyright 2012-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,13 +18,16 @@ package org.springframework.boot.context.config;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map; import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.springframework.boot.context.properties.source.ConfigurationProperty; import org.springframework.boot.context.properties.source.ConfigurationProperty;
import org.springframework.boot.context.properties.source.ConfigurationPropertyName; import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource; import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.core.env.AbstractEnvironment;
/** /**
* Exception thrown if an invalid property is found when processing config data. * Exception thrown if an invalid property is found when processing config data.
@ -35,12 +38,23 @@ import org.springframework.boot.context.properties.source.ConfigurationPropertyS
*/ */
public class InvalidConfigDataPropertyException extends ConfigDataException { public class InvalidConfigDataPropertyException extends ConfigDataException {
private static final Map<ConfigurationPropertyName, ConfigurationPropertyName> WARNING; private static final Map<ConfigurationPropertyName, ConfigurationPropertyName> WARNINGS;
static { static {
Map<ConfigurationPropertyName, ConfigurationPropertyName> warning = new LinkedHashMap<>(); Map<ConfigurationPropertyName, ConfigurationPropertyName> warnings = new LinkedHashMap<>();
warning.put(ConfigurationPropertyName.of("spring.profiles"), warnings.put(ConfigurationPropertyName.of("spring.profiles"),
ConfigurationPropertyName.of("spring.config.activate.on-profile")); ConfigurationPropertyName.of("spring.config.activate.on-profile"));
WARNING = Collections.unmodifiableMap(warning); WARNINGS = Collections.unmodifiableMap(warnings);
}
private static final Set<ConfigurationPropertyName> PROFILE_SPECIFIC_ERRORS;
static {
Set<ConfigurationPropertyName> errors = new LinkedHashSet<>();
errors.add(Profiles.INCLUDE_PROFILES);
errors.add(ConfigurationPropertyName.of(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME));
errors.add(ConfigurationPropertyName.of(AbstractEnvironment.DEFAULT_PROFILES_PROPERTY_NAME));
errors.add(ConfigurationPropertyName.of("spring.config.activate.on-profile"));
errors.add(ConfigurationPropertyName.of("spring.profiles"));
PROFILE_SPECIFIC_ERRORS = Collections.unmodifiableSet(errors);
} }
private final ConfigurationProperty property; private final ConfigurationProperty property;
@ -49,9 +63,9 @@ public class InvalidConfigDataPropertyException extends ConfigDataException {
private final ConfigDataResource location; private final ConfigDataResource location;
InvalidConfigDataPropertyException(ConfigurationProperty property, ConfigurationPropertyName replacement, InvalidConfigDataPropertyException(ConfigurationProperty property, boolean profileSpecific,
ConfigDataResource location) { ConfigurationPropertyName replacement, ConfigDataResource location) {
super(getMessage(property, replacement, location), null); super(getMessage(property, profileSpecific, replacement, location), null);
this.property = property; this.property = property;
this.replacement = replacement; this.replacement = replacement;
this.location = location; this.location = location;
@ -94,17 +108,25 @@ public class InvalidConfigDataPropertyException extends ConfigDataException {
static void throwOrWarn(Log logger, ConfigDataEnvironmentContributor contributor) { static void throwOrWarn(Log logger, ConfigDataEnvironmentContributor contributor) {
ConfigurationPropertySource propertySource = contributor.getConfigurationPropertySource(); ConfigurationPropertySource propertySource = contributor.getConfigurationPropertySource();
if (propertySource != null) { if (propertySource != null) {
WARNING.forEach((invalid, replacement) -> { WARNINGS.forEach((name, replacement) -> {
ConfigurationProperty property = propertySource.getConfigurationProperty(invalid); ConfigurationProperty property = propertySource.getConfigurationProperty(name);
if (property != null) { if (property != null) {
logger.warn(getMessage(property, replacement, contributor.getResource())); logger.warn(getMessage(property, false, replacement, contributor.getResource()));
} }
}); });
if (contributor.isProfileSpecific()) {
PROFILE_SPECIFIC_ERRORS.forEach((name) -> {
ConfigurationProperty property = propertySource.getConfigurationProperty(name);
if (property != null) {
throw new InvalidConfigDataPropertyException(property, true, null, contributor.getResource());
}
});
}
} }
} }
private static String getMessage(ConfigurationProperty property, ConfigurationPropertyName replacement, private static String getMessage(ConfigurationProperty property, boolean profileSpecific,
ConfigDataResource location) { ConfigurationPropertyName replacement, ConfigDataResource location) {
StringBuilder message = new StringBuilder("Property '"); StringBuilder message = new StringBuilder("Property '");
message.append(property.getName()); message.append(property.getName());
if (location != null) { if (location != null) {
@ -112,6 +134,9 @@ public class InvalidConfigDataPropertyException extends ConfigDataException {
message.append(location); message.append(location);
} }
message.append("' is invalid"); message.append("' is invalid");
if (profileSpecific) {
message.append(" in a profile specific resource");
}
if (replacement != null) { if (replacement != null) {
message.append(" and should be replaced with '"); message.append(" and should be replaced with '");
message.append(replacement); message.append(replacement);

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2020 the original author or authors. * Copyright 2012-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -30,6 +30,7 @@ import java.util.function.Supplier;
import org.springframework.boot.context.properties.bind.Bindable; import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder; import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
import org.springframework.core.ResolvableType; import org.springframework.core.ResolvableType;
import org.springframework.core.env.AbstractEnvironment; import org.springframework.core.env.AbstractEnvironment;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
@ -54,6 +55,9 @@ public class Profiles implements Iterable<String> {
*/ */
public static final String INCLUDE_PROFILES_PROPERTY_NAME = "spring.profiles.include"; public static final String INCLUDE_PROFILES_PROPERTY_NAME = "spring.profiles.include";
static final ConfigurationPropertyName INCLUDE_PROFILES = ConfigurationPropertyName
.of(Profiles.INCLUDE_PROFILES_PROPERTY_NAME);
private static final Bindable<MultiValueMap<String, String>> STRING_STRINGS_MAP = Bindable private static final Bindable<MultiValueMap<String, String>> STRING_STRINGS_MAP = Bindable
.of(ResolvableType.forClassWithGenerics(MultiValueMap.class, String.class, String.class)); .of(ResolvableType.forClassWithGenerics(MultiValueMap.class, String.class, String.class));

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2020 the original author or authors. * Copyright 2012-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -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, null, propertySource, null, null, false, null); super(Kind.ROOT, null, null, false, propertySource, null, null, false, null);
this.active = active; this.active = active;
} }

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2020 the original author or authors. * Copyright 2012-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -84,7 +84,7 @@ class ConfigDataEnvironmentContributorTests {
ConfigData configData = new ConfigData(Collections.singleton(new MockPropertySource())); ConfigData configData = new ConfigData(Collections.singleton(new MockPropertySource()));
ConfigDataResource resource = mock(ConfigDataResource.class); ConfigDataResource resource = mock(ConfigDataResource.class);
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofUnboundImport(TEST_LOCATION, ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofUnboundImport(TEST_LOCATION,
resource, configData, 0); resource, false, configData, 0);
assertThat(contributor.getResource()).isSameAs(resource); assertThat(contributor.getResource()).isSameAs(resource);
} }
@ -101,7 +101,7 @@ class ConfigDataEnvironmentContributorTests {
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.ofUnboundImport(null, null, ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofUnboundImport(null, null,
configData, 0); false, configData, 0);
assertThat(contributor.getConfigurationPropertySource() assertThat(contributor.getConfigurationPropertySource()
.getConfigurationProperty(ConfigurationPropertyName.of("spring")).getValue()).isEqualTo("boot"); .getConfigurationProperty(ConfigurationPropertyName.of("spring")).getValue()).isEqualTo("boot");
} }
@ -284,7 +284,7 @@ class ConfigDataEnvironmentContributorTests {
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.ofUnboundImport(TEST_LOCATION, ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofUnboundImport(TEST_LOCATION,
resource, configData, 0); resource, false, configData, 0);
assertThat(contributor.getKind()).isEqualTo(Kind.UNBOUND_IMPORT); assertThat(contributor.getKind()).isEqualTo(Kind.UNBOUND_IMPORT);
assertThat(contributor.getResource()).isSameAs(resource); assertThat(contributor.getResource()).isSameAs(resource);
assertThat(contributor.getImports()).isEmpty(); assertThat(contributor.getImports()).isEmpty();
@ -342,7 +342,7 @@ class ConfigDataEnvironmentContributorTests {
private ConfigDataEnvironmentContributor createBoundContributor(ConfigDataResource resource, ConfigData configData, private ConfigDataEnvironmentContributor createBoundContributor(ConfigDataResource resource, ConfigData configData,
int propertySourceIndex) { int propertySourceIndex) {
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofUnboundImport(TEST_LOCATION, ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofUnboundImport(TEST_LOCATION,
resource, configData, propertySourceIndex); resource, false, configData, propertySourceIndex);
Binder binder = new Binder(contributor.getConfigurationPropertySource()); Binder binder = new Binder(contributor.getConfigurationPropertySource());
return contributor.withBoundProperties(binder); return contributor.withBoundProperties(binder);
} }

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2020 the original author or authors. * Copyright 2012-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -117,7 +117,7 @@ class ConfigDataEnvironmentContributorsTests {
List<ConfigDataLocation> locations = Arrays.asList(LOCATION_1); List<ConfigDataLocation> locations = Arrays.asList(LOCATION_1);
MockPropertySource propertySource = new MockPropertySource(); MockPropertySource propertySource = new MockPropertySource();
Map<ConfigDataResolutionResult, ConfigData> imported = new LinkedHashMap<>(); Map<ConfigDataResolutionResult, ConfigData> imported = new LinkedHashMap<>();
imported.put(new ConfigDataResolutionResult(LOCATION_1, new TestConfigDataResource("a")), imported.put(new ConfigDataResolutionResult(LOCATION_1, new TestConfigDataResource("a"), false),
new ConfigData(Arrays.asList(propertySource))); new ConfigData(Arrays.asList(propertySource)));
given(this.importer.resolveAndLoad(eq(this.activationContext), any(), any(), eq(locations))) given(this.importer.resolveAndLoad(eq(this.activationContext), any(), any(), eq(locations)))
.willReturn(imported); .willReturn(imported);
@ -140,14 +140,14 @@ class ConfigDataEnvironmentContributorsTests {
MockPropertySource initialPropertySource = new MockPropertySource(); MockPropertySource initialPropertySource = new MockPropertySource();
initialPropertySource.setProperty("spring.config.import", "location2"); initialPropertySource.setProperty("spring.config.import", "location2");
Map<ConfigDataResolutionResult, ConfigData> initialImported = new LinkedHashMap<>(); Map<ConfigDataResolutionResult, ConfigData> initialImported = new LinkedHashMap<>();
initialImported.put(new ConfigDataResolutionResult(LOCATION_1, new TestConfigDataResource("a")), initialImported.put(new ConfigDataResolutionResult(LOCATION_1, new TestConfigDataResource("a"), false),
new ConfigData(Arrays.asList(initialPropertySource))); new ConfigData(Arrays.asList(initialPropertySource)));
given(this.importer.resolveAndLoad(eq(this.activationContext), any(), any(), eq(initialLocations))) given(this.importer.resolveAndLoad(eq(this.activationContext), any(), any(), eq(initialLocations)))
.willReturn(initialImported); .willReturn(initialImported);
List<ConfigDataLocation> secondLocations = Arrays.asList(LOCATION_2); List<ConfigDataLocation> secondLocations = Arrays.asList(LOCATION_2);
MockPropertySource secondPropertySource = new MockPropertySource(); MockPropertySource secondPropertySource = new MockPropertySource();
Map<ConfigDataResolutionResult, ConfigData> secondImported = new LinkedHashMap<>(); Map<ConfigDataResolutionResult, ConfigData> secondImported = new LinkedHashMap<>();
secondImported.put(new ConfigDataResolutionResult(LOCATION_2, new TestConfigDataResource("b")), secondImported.put(new ConfigDataResolutionResult(LOCATION_2, new TestConfigDataResource("b"), false),
new ConfigData(Arrays.asList(secondPropertySource))); new ConfigData(Arrays.asList(secondPropertySource)));
given(this.importer.resolveAndLoad(eq(this.activationContext), any(), any(), eq(secondLocations))) given(this.importer.resolveAndLoad(eq(this.activationContext), any(), any(), eq(secondLocations)))
.willReturn(secondImported); .willReturn(secondImported);
@ -174,7 +174,7 @@ class ConfigDataEnvironmentContributorsTests {
List<ConfigDataLocation> locations = Arrays.asList(LOCATION_1); List<ConfigDataLocation> locations = Arrays.asList(LOCATION_1);
MockPropertySource propertySource = new MockPropertySource(); MockPropertySource propertySource = new MockPropertySource();
Map<ConfigDataResolutionResult, ConfigData> imported = new LinkedHashMap<>(); Map<ConfigDataResolutionResult, ConfigData> imported = new LinkedHashMap<>();
imported.put(new ConfigDataResolutionResult(LOCATION_1, new TestConfigDataResource("a'")), imported.put(new ConfigDataResolutionResult(LOCATION_1, new TestConfigDataResource("a'"), false),
new ConfigData(Arrays.asList(propertySource))); new ConfigData(Arrays.asList(propertySource)));
given(this.importer.resolveAndLoad(eq(this.activationContext), any(), any(), eq(locations))) given(this.importer.resolveAndLoad(eq(this.activationContext), any(), any(), eq(locations)))
.willReturn(imported); .willReturn(imported);
@ -194,14 +194,14 @@ class ConfigDataEnvironmentContributorsTests {
MockPropertySource initialPropertySource = new MockPropertySource(); MockPropertySource initialPropertySource = new MockPropertySource();
initialPropertySource.setProperty("spring.config.import", "location2"); initialPropertySource.setProperty("spring.config.import", "location2");
Map<ConfigDataResolutionResult, ConfigData> initialImported = new LinkedHashMap<>(); Map<ConfigDataResolutionResult, ConfigData> initialImported = new LinkedHashMap<>();
initialImported.put(new ConfigDataResolutionResult(LOCATION_1, new TestConfigDataResource("a")), initialImported.put(new ConfigDataResolutionResult(LOCATION_1, new TestConfigDataResource("a"), false),
new ConfigData(Arrays.asList(initialPropertySource))); new ConfigData(Arrays.asList(initialPropertySource)));
given(this.importer.resolveAndLoad(eq(this.activationContext), any(), any(), eq(initialLocations))) given(this.importer.resolveAndLoad(eq(this.activationContext), any(), any(), eq(initialLocations)))
.willReturn(initialImported); .willReturn(initialImported);
List<ConfigDataLocation> secondLocations = Arrays.asList(LOCATION_2); List<ConfigDataLocation> secondLocations = Arrays.asList(LOCATION_2);
MockPropertySource secondPropertySource = new MockPropertySource(); MockPropertySource secondPropertySource = new MockPropertySource();
Map<ConfigDataResolutionResult, ConfigData> secondImported = new LinkedHashMap<>(); Map<ConfigDataResolutionResult, ConfigData> secondImported = new LinkedHashMap<>();
secondImported.put(new ConfigDataResolutionResult(LOCATION_2, new TestConfigDataResource("b")), secondImported.put(new ConfigDataResolutionResult(LOCATION_2, new TestConfigDataResource("b"), false),
new ConfigData(Arrays.asList(secondPropertySource))); new ConfigData(Arrays.asList(secondPropertySource)));
given(this.importer.resolveAndLoad(eq(this.activationContext), any(), any(), eq(secondLocations))) given(this.importer.resolveAndLoad(eq(this.activationContext), any(), any(), eq(secondLocations)))
.willReturn(secondImported); .willReturn(secondImported);
@ -224,7 +224,7 @@ class ConfigDataEnvironmentContributorsTests {
List<ConfigDataLocation> locations = Arrays.asList(LOCATION_1); List<ConfigDataLocation> locations = Arrays.asList(LOCATION_1);
MockPropertySource propertySource = new MockPropertySource(); MockPropertySource propertySource = new MockPropertySource();
Map<ConfigDataResolutionResult, ConfigData> imported = new LinkedHashMap<>(); Map<ConfigDataResolutionResult, ConfigData> imported = new LinkedHashMap<>();
imported.put(new ConfigDataResolutionResult(LOCATION_1, new TestConfigDataResource("a'")), imported.put(new ConfigDataResolutionResult(LOCATION_1, new TestConfigDataResource("a'"), false),
new ConfigData(Arrays.asList(propertySource))); new ConfigData(Arrays.asList(propertySource)));
given(this.importer.resolveAndLoad(eq(this.activationContext), any(), any(), eq(locations))) given(this.importer.resolveAndLoad(eq(this.activationContext), any(), any(), eq(locations)))
.willReturn(imported); .willReturn(imported);
@ -247,7 +247,7 @@ class ConfigDataEnvironmentContributorsTests {
List<ConfigDataLocation> locations = Arrays.asList(LOCATION_1); List<ConfigDataLocation> locations = Arrays.asList(LOCATION_1);
MockPropertySource propertySource = new MockPropertySource(); MockPropertySource propertySource = new MockPropertySource();
Map<ConfigDataResolutionResult, ConfigData> imported = new LinkedHashMap<>(); Map<ConfigDataResolutionResult, ConfigData> imported = new LinkedHashMap<>();
imported.put(new ConfigDataResolutionResult(LOCATION_1, new TestConfigDataResource("a'")), imported.put(new ConfigDataResolutionResult(LOCATION_1, new TestConfigDataResource("a'"), false),
new ConfigData(Arrays.asList(propertySource))); new ConfigData(Arrays.asList(propertySource)));
given(this.importer.resolveAndLoad(eq(this.activationContext), any(), any(), eq(locations))) given(this.importer.resolveAndLoad(eq(this.activationContext), any(), any(), eq(locations)))
.willReturn(imported); .willReturn(imported);
@ -386,7 +386,7 @@ class ConfigDataEnvironmentContributorsTests {
private ConfigDataEnvironmentContributor createBoundImportContributor(ConfigData configData, private ConfigDataEnvironmentContributor createBoundImportContributor(ConfigData configData,
int propertySourceIndex) { int propertySourceIndex) {
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofUnboundImport(null, null, ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofUnboundImport(null, null,
configData, propertySourceIndex); false, configData, propertySourceIndex);
Binder binder = new Binder(contributor.getConfigurationPropertySource()); Binder binder = new Binder(contributor.getConfigurationPropertySource());
return contributor.withBoundProperties(binder); return contributor.withBoundProperties(binder);
} }

@ -636,8 +636,8 @@ class ConfigDataEnvironmentPostProcessorIntegrationTests {
@Test @Test
void runWhenHasIncludedProfilesWithProfileSpecificFileThrowsException() { void runWhenHasIncludedProfilesWithProfileSpecificFileThrowsException() {
assertThatExceptionOfType(InactiveConfigDataAccessException.class).isThrownBy(() -> this.application assertThatExceptionOfType(InvalidConfigDataPropertyException.class).isThrownBy(() -> this.application
.run("--spring.config.name=application-include-profiles-in-profile-specific-document")); .run("--spring.config.name=application-include-profiles-in-profile-specific-file"));
} }
@Test @Test

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2020 the original author or authors. * Copyright 2012-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -81,9 +81,9 @@ class ConfigDataImporterTests {
ConfigData configData1 = new ConfigData(Collections.singleton(new MockPropertySource())); ConfigData configData1 = new ConfigData(Collections.singleton(new MockPropertySource()));
ConfigData configData2 = new ConfigData(Collections.singleton(new MockPropertySource())); ConfigData configData2 = new ConfigData(Collections.singleton(new MockPropertySource()));
given(this.resolvers.resolve(this.locationResolverContext, location1, this.profiles)) given(this.resolvers.resolve(this.locationResolverContext, location1, this.profiles))
.willReturn(Collections.singletonList(new ConfigDataResolutionResult(location1, resource1))); .willReturn(Collections.singletonList(new ConfigDataResolutionResult(location1, resource1, false)));
given(this.resolvers.resolve(this.locationResolverContext, location2, this.profiles)) given(this.resolvers.resolve(this.locationResolverContext, location2, this.profiles))
.willReturn(Collections.singletonList(new ConfigDataResolutionResult(location2, resource2))); .willReturn(Collections.singletonList(new ConfigDataResolutionResult(location2, resource2, false)));
given(this.loaders.load(this.loaderContext, resource1)).willReturn(configData1); given(this.loaders.load(this.loaderContext, resource1)).willReturn(configData1);
given(this.loaders.load(this.loaderContext, resource2)).willReturn(configData2); given(this.loaders.load(this.loaderContext, resource2)).willReturn(configData2);
ConfigDataImporter importer = new ConfigDataImporter(this.logFactory, ConfigDataNotFoundAction.FAIL, ConfigDataImporter importer = new ConfigDataImporter(this.logFactory, ConfigDataNotFoundAction.FAIL,
@ -107,11 +107,11 @@ class ConfigDataImporterTests {
ConfigData configData2 = new ConfigData(Collections.singleton(new MockPropertySource())); ConfigData configData2 = new ConfigData(Collections.singleton(new MockPropertySource()));
ConfigData configData3 = new ConfigData(Collections.singleton(new MockPropertySource())); ConfigData configData3 = new ConfigData(Collections.singleton(new MockPropertySource()));
given(this.resolvers.resolve(this.locationResolverContext, location1, this.profiles)) given(this.resolvers.resolve(this.locationResolverContext, location1, this.profiles))
.willReturn(Collections.singletonList(new ConfigDataResolutionResult(location1, resource1))); .willReturn(Collections.singletonList(new ConfigDataResolutionResult(location1, resource1, false)));
given(this.resolvers.resolve(this.locationResolverContext, location2, this.profiles)) given(this.resolvers.resolve(this.locationResolverContext, location2, this.profiles))
.willReturn(Collections.singletonList(new ConfigDataResolutionResult(location2, resource2))); .willReturn(Collections.singletonList(new ConfigDataResolutionResult(location2, resource2, false)));
given(this.resolvers.resolve(this.locationResolverContext, location3, this.profiles)) given(this.resolvers.resolve(this.locationResolverContext, location3, this.profiles))
.willReturn(Collections.singletonList(new ConfigDataResolutionResult(location3, resource3))); .willReturn(Collections.singletonList(new ConfigDataResolutionResult(location3, resource3, false)));
given(this.loaders.load(this.loaderContext, resource1)).willReturn(configData1); given(this.loaders.load(this.loaderContext, resource1)).willReturn(configData1);
given(this.loaders.load(this.loaderContext, resource2)).willReturn(configData2); given(this.loaders.load(this.loaderContext, resource2)).willReturn(configData2);
given(this.loaders.load(this.loaderContext, resource3)).willReturn(configData3); given(this.loaders.load(this.loaderContext, resource3)).willReturn(configData3);

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2020 the original author or authors. * Copyright 2012-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -20,8 +20,10 @@ import org.apache.commons.logging.Log;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.context.config.ConfigDataEnvironmentContributor.Kind;
import org.springframework.boot.context.properties.source.ConfigurationProperty; import org.springframework.boot.context.properties.source.ConfigurationProperty;
import org.springframework.boot.context.properties.source.ConfigurationPropertyName; import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.origin.MockOrigin; import org.springframework.boot.origin.MockOrigin;
import org.springframework.mock.env.MockPropertySource; import org.springframework.mock.env.MockPropertySource;
@ -50,46 +52,54 @@ class InvalidConfigDataPropertyExceptionTests {
@Test @Test
void createHasCorrectMessage() { void createHasCorrectMessage() {
assertThat(new InvalidConfigDataPropertyException(this.property, this.replacement, this.resource)).hasMessage( assertThat(new InvalidConfigDataPropertyException(this.property, false, this.replacement, this.resource))
"Property 'invalid' imported from location 'test' is invalid and should be replaced with 'replacement' [origin: origin]"); .hasMessage(
"Property 'invalid' imported from location 'test' is invalid and should be replaced with 'replacement' [origin: origin]");
} }
@Test @Test
void createWhenNoLocationHasCorrectMessage() { void createWhenNoLocationHasCorrectMessage() {
assertThat(new InvalidConfigDataPropertyException(this.property, this.replacement, null)) assertThat(new InvalidConfigDataPropertyException(this.property, false, this.replacement, null))
.hasMessage("Property 'invalid' is invalid and should be replaced with 'replacement' [origin: origin]"); .hasMessage("Property 'invalid' is invalid and should be replaced with 'replacement' [origin: origin]");
} }
@Test @Test
void createWhenNoReplacementHasCorrectMessage() { void createWhenNoReplacementHasCorrectMessage() {
assertThat(new InvalidConfigDataPropertyException(this.property, null, this.resource)) assertThat(new InvalidConfigDataPropertyException(this.property, false, null, this.resource))
.hasMessage("Property 'invalid' imported from location 'test' is invalid [origin: origin]"); .hasMessage("Property 'invalid' imported from location 'test' is invalid [origin: origin]");
} }
@Test @Test
void createWhenNoOriginHasCorrectMessage() { void createWhenNoOriginHasCorrectMessage() {
ConfigurationProperty property = new ConfigurationProperty(this.invalid, "bad", null); ConfigurationProperty property = new ConfigurationProperty(this.invalid, "bad", null);
assertThat(new InvalidConfigDataPropertyException(property, this.replacement, this.resource)).hasMessage( assertThat(new InvalidConfigDataPropertyException(property, false, this.replacement, this.resource)).hasMessage(
"Property 'invalid' imported from location 'test' is invalid and should be replaced with 'replacement'"); "Property 'invalid' imported from location 'test' is invalid and should be replaced with 'replacement'");
} }
@Test
void createWhenProfileSpecificHasCorrectMessage() {
ConfigurationProperty property = new ConfigurationProperty(this.invalid, "bad", null);
assertThat(new InvalidConfigDataPropertyException(property, true, null, this.resource)).hasMessage(
"Property 'invalid' imported from location 'test' is invalid in a profile specific resource");
}
@Test @Test
void getPropertyReturnsProperty() { void getPropertyReturnsProperty() {
InvalidConfigDataPropertyException exception = new InvalidConfigDataPropertyException(this.property, InvalidConfigDataPropertyException exception = new InvalidConfigDataPropertyException(this.property, false,
this.replacement, this.resource); this.replacement, this.resource);
assertThat(exception.getProperty()).isEqualTo(this.property); assertThat(exception.getProperty()).isEqualTo(this.property);
} }
@Test @Test
void getLocationReturnsLocation() { void getLocationReturnsLocation() {
InvalidConfigDataPropertyException exception = new InvalidConfigDataPropertyException(this.property, InvalidConfigDataPropertyException exception = new InvalidConfigDataPropertyException(this.property, false,
this.replacement, this.resource); this.replacement, this.resource);
assertThat(exception.getLocation()).isEqualTo(this.resource); assertThat(exception.getLocation()).isEqualTo(this.resource);
} }
@Test @Test
void getReplacementReturnsReplacement() { void getReplacementReturnsReplacement() {
InvalidConfigDataPropertyException exception = new InvalidConfigDataPropertyException(this.property, InvalidConfigDataPropertyException exception = new InvalidConfigDataPropertyException(this.property, false,
this.replacement, this.resource); this.replacement, this.resource);
assertThat(exception.getReplacement()).isEqualTo(this.replacement); assertThat(exception.getReplacement()).isEqualTo(this.replacement);
} }
@ -106,6 +116,25 @@ class InvalidConfigDataPropertyExceptionTests {
+ "'spring.config.activate.on-profile'"); + "'spring.config.activate.on-profile'");
} }
@Test
void throwOrWarnWhenWhenHasInvalidProfileSpecificPropertyThrowsException() {
throwOrWarnWhenWhenHasInvalidProfileSpecificPropertyThrowsException("spring.profiles.include");
throwOrWarnWhenWhenHasInvalidProfileSpecificPropertyThrowsException("spring.profiles.active");
throwOrWarnWhenWhenHasInvalidProfileSpecificPropertyThrowsException("spring.profiles.default");
throwOrWarnWhenWhenHasInvalidProfileSpecificPropertyThrowsException("spring.config.activate.on-profile");
throwOrWarnWhenWhenHasInvalidProfileSpecificPropertyThrowsException("spring.profiles");
}
private void throwOrWarnWhenWhenHasInvalidProfileSpecificPropertyThrowsException(String name) {
MockPropertySource propertySource = new MockPropertySource();
propertySource.setProperty(name, "a");
ConfigDataEnvironmentContributor contributor = new ConfigDataEnvironmentContributor(Kind.BOUND_IMPORT, null,
null, true, propertySource, ConfigurationPropertySource.from(propertySource), null, false, null);
assertThatExceptionOfType(InvalidConfigDataPropertyException.class)
.isThrownBy(() -> InvalidConfigDataPropertyException.throwOrWarn(this.logger, contributor))
.withMessageStartingWith("Property '" + name + "' is invalid in a profile specific resource");
}
@Test @Test
void throwOrWarnWhenHasNoInvalidPropertyDoesNothing() { void throwOrWarnWhenHasNoInvalidPropertyDoesNothing() {
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor

Loading…
Cancel
Save