Merge branch '2.4.x'

Closes gh-24524
pull/24532/head
Phillip Webb 4 years ago
commit 5bd5ca5107

@ -93,7 +93,7 @@ class ConfigDataEnvironment {
locations.add(ConfigDataLocation.of("optional:file:./config/")); locations.add(ConfigDataLocation.of("optional:file:./config/"));
locations.add(ConfigDataLocation.of("optional:file:./config/*/")); locations.add(ConfigDataLocation.of("optional:file:./config/*/"));
DEFAULT_SEARCH_LOCATIONS = locations.toArray(new ConfigDataLocation[0]); DEFAULT_SEARCH_LOCATIONS = locations.toArray(new ConfigDataLocation[0]);
}; }
private static final ConfigDataLocation[] EMPTY_LOCATIONS = new ConfigDataLocation[0]; private static final ConfigDataLocation[] EMPTY_LOCATIONS = new ConfigDataLocation[0];
@ -119,6 +119,8 @@ class ConfigDataEnvironment {
private final Collection<String> additionalProfiles; private final Collection<String> additionalProfiles;
private final ConfigDataEnvironmentUpdateListener environmentUpdateListener;
private final ConfigDataLoaders loaders; private final ConfigDataLoaders loaders;
private final ConfigDataEnvironmentContributors contributors; private final ConfigDataEnvironmentContributors contributors;
@ -130,9 +132,13 @@ class ConfigDataEnvironment {
* @param environment the Spring {@link Environment}. * @param environment the Spring {@link Environment}.
* @param resourceLoader {@link ResourceLoader} to load resource locations * @param resourceLoader {@link ResourceLoader} to load resource locations
* @param additionalProfiles any additional profiles to activate * @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, ConfigDataEnvironment(DeferredLogFactory logFactory, ConfigurableBootstrapContext bootstrapContext,
ConfigurableEnvironment environment, ResourceLoader resourceLoader, Collection<String> additionalProfiles) { ConfigurableEnvironment environment, ResourceLoader resourceLoader, Collection<String> additionalProfiles,
ConfigDataEnvironmentUpdateListener environmentUpdateListener) {
Binder binder = Binder.get(environment); Binder binder = Binder.get(environment);
UseLegacyConfigProcessingException.throwIfRequested(binder); UseLegacyConfigProcessingException.throwIfRequested(binder);
this.logFactory = logFactory; this.logFactory = logFactory;
@ -143,6 +149,8 @@ class ConfigDataEnvironment {
this.environment = environment; this.environment = environment;
this.resolvers = createConfigDataLocationResolvers(logFactory, bootstrapContext, binder, resourceLoader); this.resolvers = createConfigDataLocationResolvers(logFactory, bootstrapContext, binder, resourceLoader);
this.additionalProfiles = additionalProfiles; this.additionalProfiles = additionalProfiles;
this.environmentUpdateListener = (environmentUpdateListener != null) ? environmentUpdateListener
: ConfigDataEnvironmentUpdateListener.NONE;
this.loaders = new ConfigDataLoaders(logFactory, bootstrapContext); this.loaders = new ConfigDataLoaders(logFactory, bootstrapContext);
this.contributors = createContributors(binder); this.contributors = createContributors(binder);
} }
@ -301,16 +309,18 @@ class ConfigDataEnvironment {
MutablePropertySources propertySources = this.environment.getPropertySources(); MutablePropertySources propertySources = this.environment.getPropertySources();
this.logger.trace("Applying config data environment contributions"); this.logger.trace("Applying config data environment contributions");
for (ConfigDataEnvironmentContributor contributor : contributors) { for (ConfigDataEnvironmentContributor contributor : contributors) {
if (contributor.getKind() == ConfigDataEnvironmentContributor.Kind.BOUND_IMPORT PropertySource<?> propertySource = contributor.getPropertySource();
&& contributor.getPropertySource() != null) { if (contributor.getKind() == ConfigDataEnvironmentContributor.Kind.BOUND_IMPORT && propertySource != null) {
if (!contributor.isActive(activationContext)) { if (!contributor.isActive(activationContext)) {
this.logger.trace(LogMessage.format("Skipping inactive property source '%s'", this.logger.trace(
contributor.getPropertySource().getName())); LogMessage.format("Skipping inactive property source '%s'", propertySource.getName()));
} }
else { else {
this.logger.trace(LogMessage.format("Adding imported property source '%s'", this.logger
contributor.getPropertySource().getName())); .trace(LogMessage.format("Adding imported property source '%s'", propertySource.getName()));
propertySources.addLast(contributor.getPropertySource()); 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.environment.setDefaultProfiles(StringUtils.toStringArray(profiles.getDefault()));
this.logger.trace(LogMessage.format("Setting active profiles: %s", profiles.getActive())); this.logger.trace(LogMessage.format("Setting active profiles: %s", profiles.getActive()));
this.environment.setActiveProfiles(StringUtils.toStringArray(profiles.getActive())); this.environment.setActiveProfiles(StringUtils.toStringArray(profiles.getActive()));
this.environmentUpdateListener.onSetProfiles(profiles);
} }
private void checkForInvalidProperties(ConfigDataEnvironmentContributors contributors) { private void checkForInvalidProperties(ConfigDataEnvironmentContributors contributors) {

@ -63,11 +63,20 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces
private final ConfigurableBootstrapContext bootstrapContext; private final ConfigurableBootstrapContext bootstrapContext;
private final ConfigDataEnvironmentUpdateListener environmentUpdateListener;
public ConfigDataEnvironmentPostProcessor(DeferredLogFactory logFactory, public ConfigDataEnvironmentPostProcessor(DeferredLogFactory logFactory,
ConfigurableBootstrapContext bootstrapContext) { ConfigurableBootstrapContext bootstrapContext) {
this(logFactory, bootstrapContext, null);
}
public ConfigDataEnvironmentPostProcessor(DeferredLogFactory logFactory,
ConfigurableBootstrapContext bootstrapContext,
ConfigDataEnvironmentUpdateListener environmentUpdateListener) {
this.logFactory = logFactory; this.logFactory = logFactory;
this.logger = logFactory.getLog(getClass()); this.logger = logFactory.getLog(getClass());
this.bootstrapContext = bootstrapContext; this.bootstrapContext = bootstrapContext;
this.environmentUpdateListener = environmentUpdateListener;
} }
@Override @Override
@ -97,7 +106,7 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces
ConfigDataEnvironment getConfigDataEnvironment(ConfigurableEnvironment environment, ResourceLoader resourceLoader, ConfigDataEnvironment getConfigDataEnvironment(ConfigurableEnvironment environment, ResourceLoader resourceLoader,
Collection<String> additionalProfiles) { Collection<String> additionalProfiles) {
return new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, environment, resourceLoader, return new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, environment, resourceLoader,
additionalProfiles); additionalProfiles, this.environmentUpdateListener);
} }
private void postProcessUsingLegacyApplicationListener(ConfigurableEnvironment environment, private void postProcessUsingLegacyApplicationListener(ConfigurableEnvironment environment,
@ -154,6 +163,29 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces
postProcessor.postProcessEnvironment(environment, resourceLoader, additionalProfiles); 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<String> 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") @SuppressWarnings("deprecation")
static class LegacyConfigFileApplicationListener extends ConfigFileApplicationListener { static class LegacyConfigFileApplicationListener extends ConfigFileApplicationListener {

@ -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) {
}
}

@ -16,6 +16,7 @@
package org.springframework.boot.context.config; package org.springframework.boot.context.config;
import java.util.Collections;
import java.util.Set; import java.util.Set;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -119,9 +120,13 @@ class ConfigDataEnvironmentPostProcessorTests {
@Test @Test
void applyToAppliesPostProcessing() { void applyToAppliesPostProcessing() {
int before = this.environment.getPropertySources().size(); 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.getPropertySources().size()).isGreaterThan(before);
assertThat(this.environment.getActiveProfiles()).containsExactly("dev"); assertThat(this.environment.getActiveProfiles()).containsExactly("dev");
assertThat(listener.getAddedPropertySources()).hasSizeGreaterThan(0);
assertThat(listener.getProfiles().getActive()).containsExactly("dev");
} }
} }

@ -30,6 +30,7 @@ import org.springframework.boot.ConfigurableBootstrapContext;
import org.springframework.boot.DefaultBootstrapContext; import org.springframework.boot.DefaultBootstrapContext;
import org.springframework.boot.context.config.ConfigDataEnvironmentContributor.ImportPhase; import org.springframework.boot.context.config.ConfigDataEnvironmentContributor.ImportPhase;
import org.springframework.boot.context.config.ConfigDataEnvironmentContributor.Kind; import org.springframework.boot.context.config.ConfigDataEnvironmentContributor.Kind;
import org.springframework.boot.context.config.TestConfigDataEnvironmentUpdateListener.AddedPropertySource;
import org.springframework.boot.context.properties.bind.Binder; import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.logging.DeferredLogFactory; import org.springframework.boot.logging.DeferredLogFactory;
import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.ConfigurableEnvironment;
@ -65,14 +66,14 @@ class ConfigDataEnvironmentTests {
this.environment.setProperty("spring.config.use-legacy-processing", "true"); this.environment.setProperty("spring.config.use-legacy-processing", "true");
assertThatExceptionOfType(UseLegacyConfigProcessingException.class) assertThatExceptionOfType(UseLegacyConfigProcessingException.class)
.isThrownBy(() -> new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, this.environment, .isThrownBy(() -> new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, this.environment,
this.resourceLoader, this.additionalProfiles)); this.resourceLoader, this.additionalProfiles, null));
} }
@Test @Test
void createExposesEnvironmentBinderToConfigDataLocationResolvers() { void createExposesEnvironmentBinderToConfigDataLocationResolvers() {
this.environment.setProperty("spring", "boot"); this.environment.setProperty("spring", "boot");
TestConfigDataEnvironment configDataEnvironment = new TestConfigDataEnvironment(this.logFactory, 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()) assertThat(configDataEnvironment.getConfigDataLocationResolversBinder().bind("spring", String.class).get())
.isEqualTo("boot"); .isEqualTo("boot");
} }
@ -86,7 +87,7 @@ class ConfigDataEnvironmentTests {
this.environment.getPropertySources().addLast(propertySource2); this.environment.getPropertySources().addLast(propertySource2);
this.environment.getPropertySources().addLast(propertySource3); this.environment.getPropertySources().addLast(propertySource3);
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
this.environment, this.resourceLoader, this.additionalProfiles); this.environment, this.resourceLoader, this.additionalProfiles, null);
List<ConfigDataEnvironmentContributor> children = configDataEnvironment.getContributors().getRoot() List<ConfigDataEnvironmentContributor> children = configDataEnvironment.getContributors().getRoot()
.getChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION); .getChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION);
Object[] wrapped = children.stream().filter((child) -> child.getKind() == Kind.EXISTING) 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(propertySource1);
this.environment.getPropertySources().addLast(propertySource2); this.environment.getPropertySources().addLast(propertySource2);
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
this.environment, this.resourceLoader, this.additionalProfiles); this.environment, this.resourceLoader, this.additionalProfiles, null);
List<ConfigDataEnvironmentContributor> children = configDataEnvironment.getContributors().getRoot() List<ConfigDataEnvironmentContributor> children = configDataEnvironment.getContributors().getRoot()
.getChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION); .getChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION);
Object[] wrapped = children.stream().filter((child) -> child.getKind() == Kind.EXISTING) 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.additional-location", "a1,a2");
this.environment.setProperty("spring.config.import", "i1,i2"); this.environment.setProperty("spring.config.import", "i1,i2");
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
this.environment, this.resourceLoader, this.additionalProfiles); this.environment, this.resourceLoader, this.additionalProfiles, null);
List<ConfigDataEnvironmentContributor> children = configDataEnvironment.getContributors().getRoot() List<ConfigDataEnvironmentContributor> children = configDataEnvironment.getContributors().getRoot()
.getChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION); .getChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION);
Object[] imports = children.stream().filter((child) -> child.getKind() == Kind.INITIAL_IMPORT) Object[] imports = children.stream().filter((child) -> child.getKind() == Kind.INITIAL_IMPORT)
@ -133,7 +134,7 @@ class ConfigDataEnvironmentTests {
void processAndApplyAddsImportedSourceToEnvironment(TestInfo info) { void processAndApplyAddsImportedSourceToEnvironment(TestInfo info) {
this.environment.setProperty("spring.config.location", getConfigLocation(info)); this.environment.setProperty("spring.config.location", getConfigLocation(info));
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
this.environment, this.resourceLoader, this.additionalProfiles); this.environment, this.resourceLoader, this.additionalProfiles, null);
configDataEnvironment.processAndApply(); configDataEnvironment.processAndApply();
assertThat(this.environment.getProperty("spring")).isEqualTo("boot"); assertThat(this.environment.getProperty("spring")).isEqualTo("boot");
} }
@ -142,7 +143,7 @@ class ConfigDataEnvironmentTests {
void processAndApplyOnlyAddsActiveContributors(TestInfo info) { void processAndApplyOnlyAddsActiveContributors(TestInfo info) {
this.environment.setProperty("spring.config.location", getConfigLocation(info)); this.environment.setProperty("spring.config.location", getConfigLocation(info));
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
this.environment, this.resourceLoader, this.additionalProfiles); this.environment, this.resourceLoader, this.additionalProfiles, null);
configDataEnvironment.processAndApply(); configDataEnvironment.processAndApply();
assertThat(this.environment.getProperty("spring")).isEqualTo("boot"); assertThat(this.environment.getProperty("spring")).isEqualTo("boot");
assertThat(this.environment.getProperty("other")).isNull(); assertThat(this.environment.getProperty("other")).isNull();
@ -154,7 +155,7 @@ class ConfigDataEnvironmentTests {
this.environment.getPropertySources().addFirst(defaultPropertySource); this.environment.getPropertySources().addFirst(defaultPropertySource);
this.environment.setProperty("spring.config.location", getConfigLocation(info)); this.environment.setProperty("spring.config.location", getConfigLocation(info));
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
this.environment, this.resourceLoader, this.additionalProfiles); this.environment, this.resourceLoader, this.additionalProfiles, null);
configDataEnvironment.processAndApply(); configDataEnvironment.processAndApply();
List<PropertySource<?>> sources = this.environment.getPropertySources().stream().collect(Collectors.toList()); List<PropertySource<?>> sources = this.environment.getPropertySources().stream().collect(Collectors.toList());
assertThat(sources.get(sources.size() - 1)).isSameAs(defaultPropertySource); assertThat(sources.get(sources.size() - 1)).isSameAs(defaultPropertySource);
@ -164,7 +165,7 @@ class ConfigDataEnvironmentTests {
void processAndApplySetsDefaultProfiles(TestInfo info) { void processAndApplySetsDefaultProfiles(TestInfo info) {
this.environment.setProperty("spring.config.location", getConfigLocation(info)); this.environment.setProperty("spring.config.location", getConfigLocation(info));
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
this.environment, this.resourceLoader, this.additionalProfiles); this.environment, this.resourceLoader, this.additionalProfiles, null);
configDataEnvironment.processAndApply(); configDataEnvironment.processAndApply();
assertThat(this.environment.getDefaultProfiles()).containsExactly("one", "two", "three"); assertThat(this.environment.getDefaultProfiles()).containsExactly("one", "two", "three");
} }
@ -173,7 +174,7 @@ class ConfigDataEnvironmentTests {
void processAndApplySetsActiveProfiles(TestInfo info) { void processAndApplySetsActiveProfiles(TestInfo info) {
this.environment.setProperty("spring.config.location", getConfigLocation(info)); this.environment.setProperty("spring.config.location", getConfigLocation(info));
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
this.environment, this.resourceLoader, this.additionalProfiles); this.environment, this.resourceLoader, this.additionalProfiles, null);
configDataEnvironment.processAndApply(); configDataEnvironment.processAndApply();
assertThat(this.environment.getActiveProfiles()).containsExactly("one", "two", "three"); assertThat(this.environment.getActiveProfiles()).containsExactly("one", "two", "three");
} }
@ -182,7 +183,7 @@ class ConfigDataEnvironmentTests {
void processAndApplySetsActiveProfilesAndProfileGroups(TestInfo info) { void processAndApplySetsActiveProfilesAndProfileGroups(TestInfo info) {
this.environment.setProperty("spring.config.location", getConfigLocation(info)); this.environment.setProperty("spring.config.location", getConfigLocation(info));
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
this.environment, this.resourceLoader, this.additionalProfiles); this.environment, this.resourceLoader, this.additionalProfiles, null);
configDataEnvironment.processAndApply(); configDataEnvironment.processAndApply();
assertThat(this.environment.getActiveProfiles()).containsExactly("one", "four", "five", "two", "three"); assertThat(this.environment.getActiveProfiles()).containsExactly("one", "four", "five", "two", "three");
} }
@ -192,11 +193,36 @@ class ConfigDataEnvironmentTests {
void processAndApplyWhenHasInvalidPropertyThrowsException() { void processAndApplyWhenHasInvalidPropertyThrowsException() {
this.environment.setProperty("spring.profile", "a"); this.environment.setProperty("spring.profile", "a");
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
this.environment, this.resourceLoader, this.additionalProfiles); this.environment, this.resourceLoader, this.additionalProfiles, null);
assertThatExceptionOfType(InvalidConfigDataPropertyException.class) assertThatExceptionOfType(InvalidConfigDataPropertyException.class)
.isThrownBy(() -> configDataEnvironment.processAndApply()); .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) { private String getConfigLocation(TestInfo info) {
return "optional:classpath:" + info.getTestClass().get().getName().replace('.', '/') + "-" return "optional:classpath:" + info.getTestClass().get().getName().replace('.', '/') + "-"
+ info.getTestMethod().get().getName() + ".properties"; + info.getTestMethod().get().getName() + ".properties";
@ -208,8 +234,9 @@ class ConfigDataEnvironmentTests {
TestConfigDataEnvironment(DeferredLogFactory logFactory, ConfigurableBootstrapContext bootstrapContext, TestConfigDataEnvironment(DeferredLogFactory logFactory, ConfigurableBootstrapContext bootstrapContext,
ConfigurableEnvironment environment, ResourceLoader resourceLoader, ConfigurableEnvironment environment, ResourceLoader resourceLoader,
Collection<String> additionalProfiles) { Collection<String> additionalProfiles, ConfigDataEnvironmentUpdateListener environmentUpdateListener) {
super(logFactory, bootstrapContext, environment, resourceLoader, additionalProfiles); super(logFactory, bootstrapContext, environment, resourceLoader, additionalProfiles,
environmentUpdateListener);
} }
@Override @Override

@ -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<AddedPropertySource> 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<AddedPropertySource> 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;
}
}
}
Loading…
Cancel
Save