Prevent nested profile-specific resolution

Update the `ConfigDataEnvironment` so that the `resolveProfileSpecific`
method of `ConfigDataLocationResolver` is no longer called when
resolving imports declared in a profile-specific file.

Fixes gh-26753
pull/26775/head
Phillip Webb 4 years ago
parent d1b256a169
commit 0da0d2d469

@ -328,6 +328,18 @@ class ConfigDataEnvironment {
checkForInvalidProperties(contributors); checkForInvalidProperties(contributors);
checkMandatoryLocations(contributors, activationContext, loadedLocations, optionalLocations); checkMandatoryLocations(contributors, activationContext, loadedLocations, optionalLocations);
MutablePropertySources propertySources = this.environment.getPropertySources(); MutablePropertySources propertySources = this.environment.getPropertySources();
applyContributor(contributors, activationContext, propertySources);
DefaultPropertiesPropertySource.moveToEnd(propertySources);
Profiles profiles = activationContext.getProfiles();
this.logger.trace(LogMessage.format("Setting default profiles: %s", profiles.getDefault()));
this.environment.setDefaultProfiles(StringUtils.toStringArray(profiles.getDefault()));
this.logger.trace(LogMessage.format("Setting active profiles: %s", profiles.getActive()));
this.environment.setActiveProfiles(StringUtils.toStringArray(profiles.getActive()));
this.environmentUpdateListener.onSetProfiles(profiles);
}
private void applyContributor(ConfigDataEnvironmentContributors contributors,
ConfigDataActivationContext activationContext, MutablePropertySources propertySources) {
this.logger.trace("Applying config data environment contributions"); this.logger.trace("Applying config data environment contributions");
for (ConfigDataEnvironmentContributor contributor : contributors) { for (ConfigDataEnvironmentContributor contributor : contributors) {
PropertySource<?> propertySource = contributor.getPropertySource(); PropertySource<?> propertySource = contributor.getPropertySource();
@ -345,13 +357,6 @@ class ConfigDataEnvironment {
} }
} }
} }
DefaultPropertiesPropertySource.moveToEnd(propertySources);
Profiles profiles = activationContext.getProfiles();
this.logger.trace(LogMessage.format("Setting default profiles: %s", profiles.getDefault()));
this.environment.setDefaultProfiles(StringUtils.toStringArray(profiles.getDefault()));
this.logger.trace(LogMessage.format("Setting active profiles: %s", profiles.getActive()));
this.environment.setActiveProfiles(StringUtils.toStringArray(profiles.getActive()));
this.environmentUpdateListener.onSetProfiles(profiles);
} }
private void checkForInvalidProperties(ConfigDataEnvironmentContributors contributors) { private void checkForInvalidProperties(ConfigDataEnvironmentContributors contributors) {

@ -117,9 +117,10 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen
result, contributor, activationContext); result, contributor, activationContext);
ConfigDataLoaderContext loaderContext = new ContributorDataLoaderContext(this); ConfigDataLoaderContext loaderContext = new ContributorDataLoaderContext(this);
List<ConfigDataLocation> imports = contributor.getImports(); List<ConfigDataLocation> imports = contributor.getImports();
boolean resolveProfileSpecific = !contributor.isFromProfileSpecificImport();
this.logger.trace(LogMessage.format("Processing imports %s", imports)); this.logger.trace(LogMessage.format("Processing imports %s", imports));
Map<ConfigDataResolutionResult, ConfigData> imported = importer.resolveAndLoad(activationContext, Map<ConfigDataResolutionResult, ConfigData> imported = importer.resolveAndLoad(activationContext,
locationResolverContext, loaderContext, imports); locationResolverContext, loaderContext, imports, resolveProfileSpecific);
this.logger.trace(LogMessage.of(() -> getImportedMessage(imported.keySet()))); this.logger.trace(LogMessage.of(() -> getImportedMessage(imported.keySet())));
ConfigDataEnvironmentContributor contributorAndChildren = contributor.withChildren(importPhase, ConfigDataEnvironmentContributor contributorAndChildren = contributor.withChildren(importPhase,
asContributors(imported)); asContributors(imported));

@ -75,14 +75,16 @@ class ConfigDataImporter {
* @param locationResolverContext the location resolver context * @param locationResolverContext the location resolver context
* @param loaderContext the loader context * @param loaderContext the loader context
* @param locations the locations to resolve * @param locations the locations to resolve
* @param resolveProfileSpecific if profile specific resolution should be attempted
* @return a map of the loaded locations and data * @return a map of the loaded locations and data
*/ */
Map<ConfigDataResolutionResult, ConfigData> resolveAndLoad(ConfigDataActivationContext activationContext, Map<ConfigDataResolutionResult, ConfigData> resolveAndLoad(ConfigDataActivationContext activationContext,
ConfigDataLocationResolverContext locationResolverContext, ConfigDataLoaderContext loaderContext, ConfigDataLocationResolverContext locationResolverContext, ConfigDataLoaderContext loaderContext,
List<ConfigDataLocation> locations) { List<ConfigDataLocation> locations, boolean resolveProfileSpecific) {
try { try {
Profiles profiles = (activationContext != null) ? activationContext.getProfiles() : null; Profiles profiles = (activationContext != null) ? activationContext.getProfiles() : null;
List<ConfigDataResolutionResult> resolved = resolve(locationResolverContext, profiles, locations); List<ConfigDataResolutionResult> resolved = resolve(locationResolverContext, profiles, locations,
resolveProfileSpecific);
return load(loaderContext, resolved); return load(loaderContext, resolved);
} }
catch (IOException ex) { catch (IOException ex) {
@ -91,18 +93,18 @@ class ConfigDataImporter {
} }
private List<ConfigDataResolutionResult> resolve(ConfigDataLocationResolverContext locationResolverContext, private List<ConfigDataResolutionResult> resolve(ConfigDataLocationResolverContext locationResolverContext,
Profiles profiles, List<ConfigDataLocation> locations) { Profiles profiles, List<ConfigDataLocation> locations, boolean resolveProfileSpecific) {
List<ConfigDataResolutionResult> resolved = new ArrayList<>(locations.size()); List<ConfigDataResolutionResult> resolved = new ArrayList<>(locations.size());
for (ConfigDataLocation location : locations) { for (ConfigDataLocation location : locations) {
resolved.addAll(resolve(locationResolverContext, profiles, location)); resolved.addAll(resolve(locationResolverContext, profiles, location, resolveProfileSpecific));
} }
return Collections.unmodifiableList(resolved); return Collections.unmodifiableList(resolved);
} }
private List<ConfigDataResolutionResult> resolve(ConfigDataLocationResolverContext locationResolverContext, private List<ConfigDataResolutionResult> resolve(ConfigDataLocationResolverContext locationResolverContext,
Profiles profiles, ConfigDataLocation location) { Profiles profiles, ConfigDataLocation location, boolean resolveProfileSpecific) {
try { try {
return this.resolvers.resolve(locationResolverContext, location, profiles); return this.resolvers.resolve(locationResolverContext, location, profiles, resolveProfileSpecific);
} }
catch (ConfigDataNotFoundException ex) { catch (ConfigDataNotFoundException ex) {
handle(ex, location, null); handle(ex, location, null);

@ -98,22 +98,23 @@ class ConfigDataLocationResolvers {
} }
List<ConfigDataResolutionResult> resolve(ConfigDataLocationResolverContext context, ConfigDataLocation location, List<ConfigDataResolutionResult> resolve(ConfigDataLocationResolverContext context, ConfigDataLocation location,
Profiles profiles) { Profiles profiles, boolean resolveProfileSpecific) {
if (location == null) { if (location == null) {
return Collections.emptyList(); return Collections.emptyList();
} }
for (ConfigDataLocationResolver<?> resolver : getResolvers()) { for (ConfigDataLocationResolver<?> resolver : getResolvers()) {
if (resolver.isResolvable(context, location)) { if (resolver.isResolvable(context, location)) {
return resolve(resolver, context, location, profiles); return resolve(resolver, context, location, profiles, resolveProfileSpecific);
} }
} }
throw new UnsupportedConfigDataLocationException(location); throw new UnsupportedConfigDataLocationException(location);
} }
private List<ConfigDataResolutionResult> resolve(ConfigDataLocationResolver<?> resolver, private List<ConfigDataResolutionResult> resolve(ConfigDataLocationResolver<?> resolver,
ConfigDataLocationResolverContext context, ConfigDataLocation location, Profiles profiles) { ConfigDataLocationResolverContext context, ConfigDataLocation location, Profiles profiles,
boolean resolveProfileSpecific) {
List<ConfigDataResolutionResult> resolved = resolve(location, false, () -> resolver.resolve(context, location)); List<ConfigDataResolutionResult> resolved = resolve(location, false, () -> resolver.resolve(context, location));
if (profiles == null) { if (profiles == null || !resolveProfileSpecific) {
return resolved; return resolved;
} }
List<ConfigDataResolutionResult> profileSpecific = resolve(location, true, List<ConfigDataResolutionResult> profileSpecific = resolve(location, true,

@ -43,6 +43,7 @@ import org.springframework.mock.env.MockPropertySource;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
@ -119,7 +120,7 @@ class ConfigDataEnvironmentContributorsTests {
Map<ConfigDataResolutionResult, ConfigData> imported = new LinkedHashMap<>(); Map<ConfigDataResolutionResult, ConfigData> imported = new LinkedHashMap<>();
imported.put(new ConfigDataResolutionResult(LOCATION_1, new TestConfigDataResource("a"), false), 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), anyBoolean()))
.willReturn(imported); .willReturn(imported);
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofInitialImport(LOCATION_1); ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofInitialImport(LOCATION_1);
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory, ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
@ -142,14 +143,14 @@ class ConfigDataEnvironmentContributorsTests {
Map<ConfigDataResolutionResult, ConfigData> initialImported = new LinkedHashMap<>(); Map<ConfigDataResolutionResult, ConfigData> initialImported = new LinkedHashMap<>();
initialImported.put(new ConfigDataResolutionResult(LOCATION_1, new TestConfigDataResource("a"), false), 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); anyBoolean())).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"), false), 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), anyBoolean()))
.willReturn(secondImported); .willReturn(secondImported);
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofInitialImport(LOCATION_1); ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofInitialImport(LOCATION_1);
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory, ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
@ -176,13 +177,13 @@ class ConfigDataEnvironmentContributorsTests {
Map<ConfigDataResolutionResult, ConfigData> imported = new LinkedHashMap<>(); Map<ConfigDataResolutionResult, ConfigData> imported = new LinkedHashMap<>();
imported.put(new ConfigDataResolutionResult(LOCATION_1, new TestConfigDataResource("a'"), false), 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), anyBoolean()))
.willReturn(imported); .willReturn(imported);
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofInitialImport(LOCATION_1); ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofInitialImport(LOCATION_1);
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory, ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
this.bootstrapContext, Arrays.asList(existingContributor, contributor)); this.bootstrapContext, Arrays.asList(existingContributor, contributor));
contributors.withProcessedImports(this.importer, this.activationContext); contributors.withProcessedImports(this.importer, this.activationContext);
verify(this.importer).resolveAndLoad(any(), this.locationResolverContext.capture(), any(), any()); verify(this.importer).resolveAndLoad(any(), this.locationResolverContext.capture(), any(), any(), anyBoolean());
ConfigDataLocationResolverContext context = this.locationResolverContext.getValue(); ConfigDataLocationResolverContext context = this.locationResolverContext.getValue();
assertThat(context.getBinder().bind("test", String.class).get()).isEqualTo("springboot"); assertThat(context.getBinder().bind("test", String.class).get()).isEqualTo("springboot");
} }
@ -196,20 +197,21 @@ class ConfigDataEnvironmentContributorsTests {
Map<ConfigDataResolutionResult, ConfigData> initialImported = new LinkedHashMap<>(); Map<ConfigDataResolutionResult, ConfigData> initialImported = new LinkedHashMap<>();
initialImported.put(new ConfigDataResolutionResult(LOCATION_1, new TestConfigDataResource("a"), false), 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); anyBoolean())).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"), false), 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), anyBoolean()))
.willReturn(secondImported); .willReturn(secondImported);
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofInitialImport(LOCATION_1); ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofInitialImport(LOCATION_1);
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory, ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
this.bootstrapContext, Arrays.asList(contributor)); this.bootstrapContext, Arrays.asList(contributor));
contributors.withProcessedImports(this.importer, this.activationContext); contributors.withProcessedImports(this.importer, this.activationContext);
verify(this.importer).resolveAndLoad(any(), this.locationResolverContext.capture(), any(), eq(secondLocations)); verify(this.importer).resolveAndLoad(any(), this.locationResolverContext.capture(), any(), eq(secondLocations),
anyBoolean());
ConfigDataLocationResolverContext context = this.locationResolverContext.getValue(); ConfigDataLocationResolverContext context = this.locationResolverContext.getValue();
assertThat(context.getParent()).hasToString("a"); assertThat(context.getParent()).hasToString("a");
} }
@ -226,13 +228,13 @@ class ConfigDataEnvironmentContributorsTests {
Map<ConfigDataResolutionResult, ConfigData> imported = new LinkedHashMap<>(); Map<ConfigDataResolutionResult, ConfigData> imported = new LinkedHashMap<>();
imported.put(new ConfigDataResolutionResult(LOCATION_1, new TestConfigDataResource("a'"), false), 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), anyBoolean()))
.willReturn(imported); .willReturn(imported);
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofInitialImport(LOCATION_1); ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofInitialImport(LOCATION_1);
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory, ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
this.bootstrapContext, Arrays.asList(existingContributor, contributor)); this.bootstrapContext, Arrays.asList(existingContributor, contributor));
contributors.withProcessedImports(this.importer, this.activationContext); contributors.withProcessedImports(this.importer, this.activationContext);
verify(this.importer).resolveAndLoad(any(), this.locationResolverContext.capture(), any(), any()); verify(this.importer).resolveAndLoad(any(), this.locationResolverContext.capture(), any(), any(), anyBoolean());
ConfigDataLocationResolverContext context = this.locationResolverContext.getValue(); ConfigDataLocationResolverContext context = this.locationResolverContext.getValue();
assertThat(context.getBootstrapContext()).isSameAs(this.bootstrapContext); assertThat(context.getBootstrapContext()).isSameAs(this.bootstrapContext);
} }
@ -249,13 +251,13 @@ class ConfigDataEnvironmentContributorsTests {
Map<ConfigDataResolutionResult, ConfigData> imported = new LinkedHashMap<>(); Map<ConfigDataResolutionResult, ConfigData> imported = new LinkedHashMap<>();
imported.put(new ConfigDataResolutionResult(LOCATION_1, new TestConfigDataResource("a'"), false), 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), anyBoolean()))
.willReturn(imported); .willReturn(imported);
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofInitialImport(LOCATION_1); ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofInitialImport(LOCATION_1);
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory, ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
this.bootstrapContext, Arrays.asList(existingContributor, contributor)); this.bootstrapContext, Arrays.asList(existingContributor, contributor));
contributors.withProcessedImports(this.importer, this.activationContext); contributors.withProcessedImports(this.importer, this.activationContext);
verify(this.importer).resolveAndLoad(any(), any(), this.loaderContext.capture(), any()); verify(this.importer).resolveAndLoad(any(), any(), this.loaderContext.capture(), any(), anyBoolean());
ConfigDataLoaderContext context = this.loaderContext.getValue(); ConfigDataLoaderContext context = this.loaderContext.getValue();
assertThat(context.getBootstrapContext()).isSameAs(this.bootstrapContext); assertThat(context.getBootstrapContext()).isSameAs(this.bootstrapContext);
} }

@ -24,6 +24,7 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
@ -59,6 +60,7 @@ import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.ResourceLoader;
import org.springframework.util.FileCopyUtils; import org.springframework.util.FileCopyUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -761,6 +763,15 @@ class ConfigDataEnvironmentPostProcessorIntegrationTests {
assertThat(environment.containsProperty("application-profile-specific-import-with-import-import-p2")).isFalse(); assertThat(environment.containsProperty("application-profile-specific-import-with-import-import-p2")).isFalse();
} }
@Test // gh-26753
void runWhenHasProfileSpecificImportWithCustomImportDoesNotResolveProfileSpecific() {
ConfigurableApplicationContext context = this.application
.run("--spring.config.name=application-profile-specific-import-with-custom-import");
ConfigurableEnvironment environment = context.getEnvironment();
assertThat(environment.containsProperty("test:boot")).isTrue();
assertThat(environment.containsProperty("test:boot:ps")).isFalse();
}
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) {
@ -798,7 +809,14 @@ class ConfigDataEnvironmentPostProcessorIntegrationTests {
public List<TestConfigDataResource> resolve(ConfigDataLocationResolverContext context, public List<TestConfigDataResource> resolve(ConfigDataLocationResolverContext context,
ConfigDataLocation location) ConfigDataLocation location)
throws ConfigDataLocationNotFoundException, ConfigDataResourceNotFoundException { throws ConfigDataLocationNotFoundException, ConfigDataResourceNotFoundException {
return Collections.singletonList(new TestConfigDataResource(location)); return Collections.singletonList(new TestConfigDataResource(location, false));
}
@Override
public List<TestConfigDataResource> resolveProfileSpecific(ConfigDataLocationResolverContext context,
ConfigDataLocation location, org.springframework.boot.context.config.Profiles profiles)
throws ConfigDataLocationNotFoundException {
return Collections.singletonList(new TestConfigDataResource(location, true));
} }
} }
@ -811,8 +829,13 @@ class ConfigDataEnvironmentPostProcessorIntegrationTests {
if (resource.isOptional()) { if (resource.isOptional()) {
return null; return null;
} }
MapPropertySource propertySource = new MapPropertySource("loaded", Map<String, Object> map = new LinkedHashMap<>();
Collections.singletonMap("spring", "boot")); if (!resource.isProfileSpecific()) {
map.put("spring", "boot");
}
String suffix = (!resource.isProfileSpecific()) ? "" : ":ps";
map.put(resource.toString() + suffix, "true");
MapPropertySource propertySource = new MapPropertySource("loaded" + suffix, map);
return new ConfigData(Collections.singleton(propertySource)); return new ConfigData(Collections.singleton(propertySource));
} }
@ -820,8 +843,41 @@ class ConfigDataEnvironmentPostProcessorIntegrationTests {
static class TestConfigDataResource extends ConfigDataResource { static class TestConfigDataResource extends ConfigDataResource {
TestConfigDataResource(ConfigDataLocation location) { private final ConfigDataLocation location;
private boolean profileSpecific;
TestConfigDataResource(ConfigDataLocation location, boolean profileSpecific) {
super(location.toString().contains("optionalresult")); super(location.toString().contains("optionalresult"));
this.location = location;
this.profileSpecific = profileSpecific;
}
boolean isProfileSpecific() {
return this.profileSpecific;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
TestConfigDataResource other = (TestConfigDataResource) obj;
return ObjectUtils.nullSafeEquals(this.location, other.location)
&& this.profileSpecific == other.profileSpecific;
}
@Override
public int hashCode() {
return 0;
}
@Override
public String toString() {
return this.location.toString();
} }
} }

@ -80,16 +80,16 @@ class ConfigDataImporterTests {
TestResource resource2 = new TestResource("r2"); TestResource resource2 = new TestResource("r2");
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, true))
.willReturn(Collections.singletonList(new ConfigDataResolutionResult(location1, resource1, false))); .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, true))
.willReturn(Collections.singletonList(new ConfigDataResolutionResult(location2, resource2, false))); .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,
this.resolvers, this.loaders); this.resolvers, this.loaders);
Collection<ConfigData> loaded = importer.resolveAndLoad(this.activationContext, this.locationResolverContext, Collection<ConfigData> loaded = importer.resolveAndLoad(this.activationContext, this.locationResolverContext,
this.loaderContext, Arrays.asList(location1, location2)).values(); this.loaderContext, Arrays.asList(location1, location2), true).values();
assertThat(loaded).containsExactly(configData2, configData1); assertThat(loaded).containsExactly(configData2, configData1);
} }
@ -106,11 +106,11 @@ 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()));
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, true))
.willReturn(Collections.singletonList(new ConfigDataResolutionResult(location1, resource1, false))); .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, true))
.willReturn(Collections.singletonList(new ConfigDataResolutionResult(location2, resource2, false))); .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, true))
.willReturn(Collections.singletonList(new ConfigDataResolutionResult(location3, resource3, false))); .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);
@ -118,9 +118,9 @@ class ConfigDataImporterTests {
ConfigDataImporter importer = new ConfigDataImporter(this.logFactory, ConfigDataNotFoundAction.FAIL, ConfigDataImporter importer = new ConfigDataImporter(this.logFactory, ConfigDataNotFoundAction.FAIL,
this.resolvers, this.loaders); this.resolvers, this.loaders);
Collection<ConfigData> loaded1and2 = importer.resolveAndLoad(this.activationContext, Collection<ConfigData> loaded1and2 = importer.resolveAndLoad(this.activationContext,
this.locationResolverContext, this.loaderContext, locations1and2).values(); this.locationResolverContext, this.loaderContext, locations1and2, true).values();
Collection<ConfigData> loaded2and3 = importer.resolveAndLoad(this.activationContext, Collection<ConfigData> loaded2and3 = importer.resolveAndLoad(this.activationContext,
this.locationResolverContext, this.loaderContext, locations2and3).values(); this.locationResolverContext, this.loaderContext, locations2and3, true).values();
assertThat(loaded1and2).containsExactly(configData2, configData1); assertThat(loaded1and2).containsExactly(configData2, configData1);
assertThat(loaded2and3).containsExactly(configData3); assertThat(loaded2and3).containsExactly(configData3);
} }

@ -131,7 +131,7 @@ class ConfigDataLocationResolversTests {
this.binder, this.resourceLoader, this.binder, this.resourceLoader,
Arrays.asList(LowestTestResolver.class.getName(), HighestTestResolver.class.getName())); Arrays.asList(LowestTestResolver.class.getName(), HighestTestResolver.class.getName()));
ConfigDataLocation location = ConfigDataLocation.of("LowestTestResolver:test"); ConfigDataLocation location = ConfigDataLocation.of("LowestTestResolver:test");
List<ConfigDataResolutionResult> resolved = resolvers.resolve(this.context, location, null); List<ConfigDataResolutionResult> resolved = resolvers.resolve(this.context, location, null, true);
assertThat(resolved).hasSize(1); assertThat(resolved).hasSize(1);
TestConfigDataResource resource = (TestConfigDataResource) resolved.get(0).getResource(); TestConfigDataResource resource = (TestConfigDataResource) resolved.get(0).getResource();
assertThat(resource.getResolver()).isInstanceOf(LowestTestResolver.class); assertThat(resource.getResolver()).isInstanceOf(LowestTestResolver.class);
@ -145,7 +145,7 @@ class ConfigDataLocationResolversTests {
this.binder, this.resourceLoader, this.binder, this.resourceLoader,
Arrays.asList(LowestTestResolver.class.getName(), HighestTestResolver.class.getName())); Arrays.asList(LowestTestResolver.class.getName(), HighestTestResolver.class.getName()));
ConfigDataLocation location = ConfigDataLocation.of("LowestTestResolver:test"); ConfigDataLocation location = ConfigDataLocation.of("LowestTestResolver:test");
List<ConfigDataResolutionResult> resolved = resolvers.resolve(this.context, location, this.profiles); List<ConfigDataResolutionResult> resolved = resolvers.resolve(this.context, location, this.profiles, true);
assertThat(resolved).hasSize(2); assertThat(resolved).hasSize(2);
TestConfigDataResource resource = (TestConfigDataResource) resolved.get(0).getResource(); TestConfigDataResource resource = (TestConfigDataResource) resolved.get(0).getResource();
assertThat(resource.getResolver()).isInstanceOf(LowestTestResolver.class); assertThat(resource.getResolver()).isInstanceOf(LowestTestResolver.class);
@ -164,7 +164,7 @@ class ConfigDataLocationResolversTests {
Arrays.asList(LowestTestResolver.class.getName(), HighestTestResolver.class.getName())); Arrays.asList(LowestTestResolver.class.getName(), HighestTestResolver.class.getName()));
ConfigDataLocation location = ConfigDataLocation.of("Missing:test"); ConfigDataLocation location = ConfigDataLocation.of("Missing:test");
assertThatExceptionOfType(UnsupportedConfigDataLocationException.class) assertThatExceptionOfType(UnsupportedConfigDataLocationException.class)
.isThrownBy(() -> resolvers.resolve(this.context, location, null)) .isThrownBy(() -> resolvers.resolve(this.context, location, null, true))
.satisfies((ex) -> assertThat(ex.getLocation()).isEqualTo(location)); .satisfies((ex) -> assertThat(ex.getLocation()).isEqualTo(location));
} }
@ -173,7 +173,7 @@ class ConfigDataLocationResolversTests {
ConfigDataLocationResolvers resolvers = new ConfigDataLocationResolvers(this.logFactory, this.bootstrapContext, ConfigDataLocationResolvers resolvers = new ConfigDataLocationResolvers(this.logFactory, this.bootstrapContext,
this.binder, this.resourceLoader, Arrays.asList(OptionalResourceTestResolver.class.getName())); this.binder, this.resourceLoader, Arrays.asList(OptionalResourceTestResolver.class.getName()));
ConfigDataLocation location = ConfigDataLocation.of("OptionalResourceTestResolver:test"); ConfigDataLocation location = ConfigDataLocation.of("OptionalResourceTestResolver:test");
List<ConfigDataResolutionResult> resolved = resolvers.resolve(this.context, location, null); List<ConfigDataResolutionResult> resolved = resolvers.resolve(this.context, location, null, true);
assertThat(resolved.get(0).getResource().isOptional()).isTrue(); assertThat(resolved.get(0).getResource().isOptional()).isTrue();
} }

Loading…
Cancel
Save