From 5e1a69e90ec0da92e53c2eda6c66ab34a7dc0059 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Tue, 15 Dec 2020 19:51:53 -0800 Subject: [PATCH 1/2] Polish --- .../boot/context/config/ConfigDataEnvironment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironment.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironment.java index 674ad2457d..ab7125da54 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironment.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironment.java @@ -93,7 +93,7 @@ class ConfigDataEnvironment { locations.add(ConfigDataLocation.of("optional:file:./config/")); locations.add(ConfigDataLocation.of("optional:file:./config/*/")); DEFAULT_SEARCH_LOCATIONS = locations.toArray(new ConfigDataLocation[0]); - }; + } private static final ConfigDataLocation[] EMPTY_LOCATIONS = new ConfigDataLocation[0]; From 38e4c2a179f320c58986d9209cb12bfc8d6f9fdf Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Tue, 15 Dec 2020 19:34:52 -0800 Subject: [PATCH 2/2] Add ConfigDataEnvironmentUpdateListener support Add an overloaded `ConfigDataEnvironmentPostProcessor.applyTo` method that accepts a listener that can used to track the updates that were applied to the `Environment`. The listener can be used to track the which `ConfigDataLocation` and the `ConfigDataResource` were used to add a `PropertySource`. The lister can also be used to tell which profiles were applied. This enhancement is being added in a patch release because it's will be useful for Spring Cloud 2020.0.0. Closes gh-24504 --- .../context/config/ConfigDataEnvironment.java | 27 +++++-- .../ConfigDataEnvironmentPostProcessor.java | 34 +++++++- .../ConfigDataEnvironmentUpdateListener.java | 56 +++++++++++++ ...nfigDataEnvironmentPostProcessorTests.java | 7 +- .../config/ConfigDataEnvironmentTests.java | 55 +++++++++---- ...stConfigDataEnvironmentUpdateListener.java | 79 +++++++++++++++++++ ...tenerCallsOnPropertySourceAdded.properties | 1 + ...enHasListenerCallsOnSetProfiles.properties | 1 + 8 files changed, 236 insertions(+), 24 deletions(-) create mode 100644 spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironmentUpdateListener.java create mode 100644 spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/TestConfigDataEnvironmentUpdateListener.java create mode 100644 spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/context/config/ConfigDataEnvironmentTests-processAndApplyWhenHasListenerCallsOnPropertySourceAdded.properties create mode 100644 spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/context/config/ConfigDataEnvironmentTests-processAndApplyWhenHasListenerCallsOnSetProfiles.properties diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironment.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironment.java index ab7125da54..8232314a9d 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironment.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironment.java @@ -119,6 +119,8 @@ class ConfigDataEnvironment { private final Collection additionalProfiles; + private final ConfigDataEnvironmentUpdateListener environmentUpdateListener; + private final ConfigDataLoaders loaders; private final ConfigDataEnvironmentContributors contributors; @@ -130,9 +132,13 @@ class ConfigDataEnvironment { * @param environment the Spring {@link Environment}. * @param resourceLoader {@link ResourceLoader} to load resource locations * @param additionalProfiles any additional profiles to activate + * @param environmentUpdateListener optional + * {@link ConfigDataEnvironmentUpdateListener} that can be used to track + * {@link Environment} updates. */ ConfigDataEnvironment(DeferredLogFactory logFactory, ConfigurableBootstrapContext bootstrapContext, - ConfigurableEnvironment environment, ResourceLoader resourceLoader, Collection additionalProfiles) { + ConfigurableEnvironment environment, ResourceLoader resourceLoader, Collection additionalProfiles, + ConfigDataEnvironmentUpdateListener environmentUpdateListener) { Binder binder = Binder.get(environment); UseLegacyConfigProcessingException.throwIfRequested(binder); this.logFactory = logFactory; @@ -143,6 +149,8 @@ class ConfigDataEnvironment { this.environment = environment; this.resolvers = createConfigDataLocationResolvers(logFactory, bootstrapContext, binder, resourceLoader); this.additionalProfiles = additionalProfiles; + this.environmentUpdateListener = (environmentUpdateListener != null) ? environmentUpdateListener + : ConfigDataEnvironmentUpdateListener.NONE; this.loaders = new ConfigDataLoaders(logFactory, bootstrapContext); this.contributors = createContributors(binder); } @@ -301,16 +309,18 @@ class ConfigDataEnvironment { MutablePropertySources propertySources = this.environment.getPropertySources(); this.logger.trace("Applying config data environment contributions"); for (ConfigDataEnvironmentContributor contributor : contributors) { - if (contributor.getKind() == ConfigDataEnvironmentContributor.Kind.BOUND_IMPORT - && contributor.getPropertySource() != null) { + PropertySource propertySource = contributor.getPropertySource(); + if (contributor.getKind() == ConfigDataEnvironmentContributor.Kind.BOUND_IMPORT && propertySource != null) { if (!contributor.isActive(activationContext)) { - this.logger.trace(LogMessage.format("Skipping inactive property source '%s'", - contributor.getPropertySource().getName())); + this.logger.trace( + LogMessage.format("Skipping inactive property source '%s'", propertySource.getName())); } else { - this.logger.trace(LogMessage.format("Adding imported property source '%s'", - contributor.getPropertySource().getName())); - propertySources.addLast(contributor.getPropertySource()); + this.logger + .trace(LogMessage.format("Adding imported property source '%s'", propertySource.getName())); + propertySources.addLast(propertySource); + this.environmentUpdateListener.onPropertySourceAdded(propertySource, contributor.getLocation(), + contributor.getResource()); } } } @@ -320,6 +330,7 @@ class ConfigDataEnvironment { 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) { diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironmentPostProcessor.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironmentPostProcessor.java index 16131d7c9c..6e4675c729 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironmentPostProcessor.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironmentPostProcessor.java @@ -63,11 +63,20 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces private final ConfigurableBootstrapContext bootstrapContext; + private final ConfigDataEnvironmentUpdateListener environmentUpdateListener; + public ConfigDataEnvironmentPostProcessor(DeferredLogFactory logFactory, ConfigurableBootstrapContext bootstrapContext) { + this(logFactory, bootstrapContext, null); + } + + public ConfigDataEnvironmentPostProcessor(DeferredLogFactory logFactory, + ConfigurableBootstrapContext bootstrapContext, + ConfigDataEnvironmentUpdateListener environmentUpdateListener) { this.logFactory = logFactory; this.logger = logFactory.getLog(getClass()); this.bootstrapContext = bootstrapContext; + this.environmentUpdateListener = environmentUpdateListener; } @Override @@ -97,7 +106,7 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces ConfigDataEnvironment getConfigDataEnvironment(ConfigurableEnvironment environment, ResourceLoader resourceLoader, Collection additionalProfiles) { return new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, environment, resourceLoader, - additionalProfiles); + additionalProfiles, this.environmentUpdateListener); } private void postProcessUsingLegacyApplicationListener(ConfigurableEnvironment environment, @@ -154,6 +163,29 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces postProcessor.postProcessEnvironment(environment, resourceLoader, additionalProfiles); } + /** + * Apply {@link ConfigData} post-processing to an existing {@link Environment}. This + * method can be useful when working with an {@link Environment} that has been created + * directly and not necessarily as part of a {@link SpringApplication}. + * @param environment the environment to apply {@link ConfigData} to + * @param resourceLoader the resource loader to use + * @param bootstrapContext the bootstrap context to use or {@code null} to use a + * throw-away context + * @param additionalProfiles any additional profiles that should be applied + * @param environmentUpdateListener optional + * {@link ConfigDataEnvironmentUpdateListener} that can be used to track + * {@link Environment} updates. + */ + public static void applyTo(ConfigurableEnvironment environment, ResourceLoader resourceLoader, + ConfigurableBootstrapContext bootstrapContext, Collection additionalProfiles, + ConfigDataEnvironmentUpdateListener environmentUpdateListener) { + DeferredLogFactory logFactory = Supplier::get; + bootstrapContext = (bootstrapContext != null) ? bootstrapContext : new DefaultBootstrapContext(); + ConfigDataEnvironmentPostProcessor postProcessor = new ConfigDataEnvironmentPostProcessor(logFactory, + bootstrapContext, environmentUpdateListener); + postProcessor.postProcessEnvironment(environment, resourceLoader, additionalProfiles); + } + @SuppressWarnings("deprecation") static class LegacyConfigFileApplicationListener extends ConfigFileApplicationListener { diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironmentUpdateListener.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironmentUpdateListener.java new file mode 100644 index 0000000000..f32f0af784 --- /dev/null +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironmentUpdateListener.java @@ -0,0 +1,56 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.context.config; + +import java.util.EventListener; + +import org.springframework.core.env.Environment; +import org.springframework.core.env.PropertySource; + +/** + * {@link EventListener} to listen to {@link Environment} updates triggered by the + * {@link ConfigDataEnvironmentPostProcessor}. + * + * @author Phillip Webb + * @since 2.4.2 + */ +public interface ConfigDataEnvironmentUpdateListener extends EventListener { + + /** + * A {@link ConfigDataEnvironmentUpdateListener} that does nothing. + */ + ConfigDataEnvironmentUpdateListener NONE = new ConfigDataEnvironmentUpdateListener() { + }; + + /** + * Called when a new {@link PropertySource} is added to the {@link Environment}. + * @param propertySource the {@link PropertySource} that was added + * @param location the original {@link ConfigDataLocation} of the source. + * @param resource the {@link ConfigDataResource} of the source. + */ + default void onPropertySourceAdded(PropertySource propertySource, ConfigDataLocation location, + ConfigDataResource resource) { + } + + /** + * Called when {@link Environment} profiles are set. + * @param profiles the profiles being set + */ + default void onSetProfiles(Profiles profiles) { + } + +} diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigDataEnvironmentPostProcessorTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigDataEnvironmentPostProcessorTests.java index fbf67a693c..a3320116eb 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigDataEnvironmentPostProcessorTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigDataEnvironmentPostProcessorTests.java @@ -16,6 +16,7 @@ package org.springframework.boot.context.config; +import java.util.Collections; import java.util.Set; import java.util.function.Supplier; @@ -119,9 +120,13 @@ class ConfigDataEnvironmentPostProcessorTests { @Test void applyToAppliesPostProcessing() { int before = this.environment.getPropertySources().size(); - ConfigDataEnvironmentPostProcessor.applyTo(this.environment, null, null, "dev"); + TestConfigDataEnvironmentUpdateListener listener = new TestConfigDataEnvironmentUpdateListener(); + ConfigDataEnvironmentPostProcessor.applyTo(this.environment, null, null, Collections.singleton("dev"), + listener); assertThat(this.environment.getPropertySources().size()).isGreaterThan(before); assertThat(this.environment.getActiveProfiles()).containsExactly("dev"); + assertThat(listener.getAddedPropertySources()).hasSizeGreaterThan(0); + assertThat(listener.getProfiles().getActive()).containsExactly("dev"); } } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigDataEnvironmentTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigDataEnvironmentTests.java index 8327d9d52f..3d0d07e5cb 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigDataEnvironmentTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigDataEnvironmentTests.java @@ -30,6 +30,7 @@ import org.springframework.boot.ConfigurableBootstrapContext; import org.springframework.boot.DefaultBootstrapContext; import org.springframework.boot.context.config.ConfigDataEnvironmentContributor.ImportPhase; import org.springframework.boot.context.config.ConfigDataEnvironmentContributor.Kind; +import org.springframework.boot.context.config.TestConfigDataEnvironmentUpdateListener.AddedPropertySource; import org.springframework.boot.context.properties.bind.Binder; import org.springframework.boot.logging.DeferredLogFactory; import org.springframework.core.env.ConfigurableEnvironment; @@ -65,14 +66,14 @@ class ConfigDataEnvironmentTests { this.environment.setProperty("spring.config.use-legacy-processing", "true"); assertThatExceptionOfType(UseLegacyConfigProcessingException.class) .isThrownBy(() -> new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, this.environment, - this.resourceLoader, this.additionalProfiles)); + this.resourceLoader, this.additionalProfiles, null)); } @Test void createExposesEnvironmentBinderToConfigDataLocationResolvers() { this.environment.setProperty("spring", "boot"); TestConfigDataEnvironment configDataEnvironment = new TestConfigDataEnvironment(this.logFactory, - this.bootstrapContext, this.environment, this.resourceLoader, this.additionalProfiles); + this.bootstrapContext, this.environment, this.resourceLoader, this.additionalProfiles, null); assertThat(configDataEnvironment.getConfigDataLocationResolversBinder().bind("spring", String.class).get()) .isEqualTo("boot"); } @@ -86,7 +87,7 @@ class ConfigDataEnvironmentTests { this.environment.getPropertySources().addLast(propertySource2); this.environment.getPropertySources().addLast(propertySource3); ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, - this.environment, this.resourceLoader, this.additionalProfiles); + this.environment, this.resourceLoader, this.additionalProfiles, null); List children = configDataEnvironment.getContributors().getRoot() .getChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION); Object[] wrapped = children.stream().filter((child) -> child.getKind() == Kind.EXISTING) @@ -105,7 +106,7 @@ class ConfigDataEnvironmentTests { this.environment.getPropertySources().addLast(propertySource1); this.environment.getPropertySources().addLast(propertySource2); ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, - this.environment, this.resourceLoader, this.additionalProfiles); + this.environment, this.resourceLoader, this.additionalProfiles, null); List children = configDataEnvironment.getContributors().getRoot() .getChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION); Object[] wrapped = children.stream().filter((child) -> child.getKind() == Kind.EXISTING) @@ -121,7 +122,7 @@ class ConfigDataEnvironmentTests { this.environment.setProperty("spring.config.additional-location", "a1,a2"); this.environment.setProperty("spring.config.import", "i1,i2"); ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, - this.environment, this.resourceLoader, this.additionalProfiles); + this.environment, this.resourceLoader, this.additionalProfiles, null); List children = configDataEnvironment.getContributors().getRoot() .getChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION); Object[] imports = children.stream().filter((child) -> child.getKind() == Kind.INITIAL_IMPORT) @@ -133,7 +134,7 @@ class ConfigDataEnvironmentTests { void processAndApplyAddsImportedSourceToEnvironment(TestInfo info) { this.environment.setProperty("spring.config.location", getConfigLocation(info)); ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, - this.environment, this.resourceLoader, this.additionalProfiles); + this.environment, this.resourceLoader, this.additionalProfiles, null); configDataEnvironment.processAndApply(); assertThat(this.environment.getProperty("spring")).isEqualTo("boot"); } @@ -142,7 +143,7 @@ class ConfigDataEnvironmentTests { void processAndApplyOnlyAddsActiveContributors(TestInfo info) { this.environment.setProperty("spring.config.location", getConfigLocation(info)); ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, - this.environment, this.resourceLoader, this.additionalProfiles); + this.environment, this.resourceLoader, this.additionalProfiles, null); configDataEnvironment.processAndApply(); assertThat(this.environment.getProperty("spring")).isEqualTo("boot"); assertThat(this.environment.getProperty("other")).isNull(); @@ -154,7 +155,7 @@ class ConfigDataEnvironmentTests { this.environment.getPropertySources().addFirst(defaultPropertySource); this.environment.setProperty("spring.config.location", getConfigLocation(info)); ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, - this.environment, this.resourceLoader, this.additionalProfiles); + this.environment, this.resourceLoader, this.additionalProfiles, null); configDataEnvironment.processAndApply(); List> sources = this.environment.getPropertySources().stream().collect(Collectors.toList()); assertThat(sources.get(sources.size() - 1)).isSameAs(defaultPropertySource); @@ -164,7 +165,7 @@ class ConfigDataEnvironmentTests { void processAndApplySetsDefaultProfiles(TestInfo info) { this.environment.setProperty("spring.config.location", getConfigLocation(info)); ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, - this.environment, this.resourceLoader, this.additionalProfiles); + this.environment, this.resourceLoader, this.additionalProfiles, null); configDataEnvironment.processAndApply(); assertThat(this.environment.getDefaultProfiles()).containsExactly("one", "two", "three"); } @@ -173,7 +174,7 @@ class ConfigDataEnvironmentTests { void processAndApplySetsActiveProfiles(TestInfo info) { this.environment.setProperty("spring.config.location", getConfigLocation(info)); ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, - this.environment, this.resourceLoader, this.additionalProfiles); + this.environment, this.resourceLoader, this.additionalProfiles, null); configDataEnvironment.processAndApply(); assertThat(this.environment.getActiveProfiles()).containsExactly("one", "two", "three"); } @@ -182,7 +183,7 @@ class ConfigDataEnvironmentTests { void processAndApplySetsActiveProfilesAndProfileGroups(TestInfo info) { this.environment.setProperty("spring.config.location", getConfigLocation(info)); ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, - this.environment, this.resourceLoader, this.additionalProfiles); + this.environment, this.resourceLoader, this.additionalProfiles, null); configDataEnvironment.processAndApply(); assertThat(this.environment.getActiveProfiles()).containsExactly("one", "four", "five", "two", "three"); } @@ -192,11 +193,36 @@ class ConfigDataEnvironmentTests { void processAndApplyWhenHasInvalidPropertyThrowsException() { this.environment.setProperty("spring.profile", "a"); ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, - this.environment, this.resourceLoader, this.additionalProfiles); + this.environment, this.resourceLoader, this.additionalProfiles, null); assertThatExceptionOfType(InvalidConfigDataPropertyException.class) .isThrownBy(() -> configDataEnvironment.processAndApply()); } + @Test + void processAndApplyWhenHasListenerCallsOnPropertySourceAdded(TestInfo info) { + this.environment.setProperty("spring.config.location", getConfigLocation(info)); + TestConfigDataEnvironmentUpdateListener listener = new TestConfigDataEnvironmentUpdateListener(); + ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, + this.environment, this.resourceLoader, this.additionalProfiles, listener); + configDataEnvironment.processAndApply(); + assertThat(listener.getAddedPropertySources()).hasSize(1); + AddedPropertySource addedPropertySource = listener.getAddedPropertySources().get(0); + assertThat(addedPropertySource.getPropertySource().getProperty("spring")).isEqualTo("boot"); + assertThat(addedPropertySource.getLocation().toString()).isEqualTo(getConfigLocation(info)); + assertThat(addedPropertySource.getResource().toString()).contains("class path resource") + .contains(info.getTestMethod().get().getName()); + } + + @Test + void processAndApplyWhenHasListenerCallsOnSetProfiles(TestInfo info) { + this.environment.setProperty("spring.config.location", getConfigLocation(info)); + TestConfigDataEnvironmentUpdateListener listener = new TestConfigDataEnvironmentUpdateListener(); + ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, + this.environment, this.resourceLoader, this.additionalProfiles, listener); + configDataEnvironment.processAndApply(); + assertThat(listener.getProfiles().getActive()).containsExactly("one", "two", "three"); + } + private String getConfigLocation(TestInfo info) { return "optional:classpath:" + info.getTestClass().get().getName().replace('.', '/') + "-" + info.getTestMethod().get().getName() + ".properties"; @@ -208,8 +234,9 @@ class ConfigDataEnvironmentTests { TestConfigDataEnvironment(DeferredLogFactory logFactory, ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment, ResourceLoader resourceLoader, - Collection additionalProfiles) { - super(logFactory, bootstrapContext, environment, resourceLoader, additionalProfiles); + Collection additionalProfiles, ConfigDataEnvironmentUpdateListener environmentUpdateListener) { + super(logFactory, bootstrapContext, environment, resourceLoader, additionalProfiles, + environmentUpdateListener); } @Override diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/TestConfigDataEnvironmentUpdateListener.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/TestConfigDataEnvironmentUpdateListener.java new file mode 100644 index 0000000000..07fc93616c --- /dev/null +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/TestConfigDataEnvironmentUpdateListener.java @@ -0,0 +1,79 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.context.config; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.springframework.core.env.PropertySource; + +class TestConfigDataEnvironmentUpdateListener implements ConfigDataEnvironmentUpdateListener { + + private final List addedPropertySources = new ArrayList<>(); + + private Profiles profiles; + + @Override + public void onPropertySourceAdded(PropertySource propertySource, ConfigDataLocation location, + ConfigDataResource resource) { + this.addedPropertySources.add(new AddedPropertySource(propertySource, location, resource)); + } + + @Override + public void onSetProfiles(Profiles profiles) { + this.profiles = profiles; + } + + List getAddedPropertySources() { + return Collections.unmodifiableList(this.addedPropertySources); + } + + Profiles getProfiles() { + return this.profiles; + } + + static class AddedPropertySource { + + private final PropertySource propertySource; + + private final ConfigDataLocation location; + + private final ConfigDataResource resource; + + AddedPropertySource(PropertySource propertySource, ConfigDataLocation location, + ConfigDataResource resource) { + this.propertySource = propertySource; + this.location = location; + this.resource = resource; + } + + PropertySource getPropertySource() { + return this.propertySource; + } + + ConfigDataLocation getLocation() { + return this.location; + } + + ConfigDataResource getResource() { + return this.resource; + } + + } + +} diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/context/config/ConfigDataEnvironmentTests-processAndApplyWhenHasListenerCallsOnPropertySourceAdded.properties b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/context/config/ConfigDataEnvironmentTests-processAndApplyWhenHasListenerCallsOnPropertySourceAdded.properties new file mode 100644 index 0000000000..74bc31f180 --- /dev/null +++ b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/context/config/ConfigDataEnvironmentTests-processAndApplyWhenHasListenerCallsOnPropertySourceAdded.properties @@ -0,0 +1 @@ +spring=boot diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/context/config/ConfigDataEnvironmentTests-processAndApplyWhenHasListenerCallsOnSetProfiles.properties b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/context/config/ConfigDataEnvironmentTests-processAndApplyWhenHasListenerCallsOnSetProfiles.properties new file mode 100644 index 0000000000..d0e7d24f23 --- /dev/null +++ b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/context/config/ConfigDataEnvironmentTests-processAndApplyWhenHasListenerCallsOnSetProfiles.properties @@ -0,0 +1 @@ +spring.profiles.active=one,two,three