Skip to content

Commit b567417

Browse files
committed
Merge branch '2.4.x'
Closes gh-24893
2 parents 452fbf3 + 80dbbaf commit b567417

9 files changed

+128
-45
lines changed

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigData.java

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -90,7 +90,13 @@ public enum Option {
9090
/**
9191
* Ignore all imports properties from the sources.
9292
*/
93-
IGNORE_IMPORTS;
93+
IGNORE_IMPORTS,
94+
95+
/**
96+
* Ignore all profile activation and include properties.
97+
* @since 2.4.3
98+
*/
99+
IGNORE_PROFILES;
94100

95101
}
96102

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironment.java

+15-10
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,11 @@ private ConfigDataEnvironmentContributors createContributors(Binder binder) {
181181
this.logger.trace("Creating wrapped config data contributor for default property source");
182182
contributors.add(ConfigDataEnvironmentContributor.ofExisting(defaultPropertySource));
183183
}
184+
return createContributors(contributors);
185+
}
186+
187+
protected ConfigDataEnvironmentContributors createContributors(
188+
List<ConfigDataEnvironmentContributor> contributors) {
184189
return new ConfigDataEnvironmentContributors(this.logFactory, this.bootstrapContext, contributors);
185190
}
186191

@@ -263,7 +268,8 @@ private ConfigDataEnvironmentContributors processWithoutProfiles(ConfigDataEnvir
263268
private ConfigDataActivationContext withProfiles(ConfigDataEnvironmentContributors contributors,
264269
ConfigDataActivationContext activationContext) {
265270
this.logger.trace("Deducing profiles from current config data environment contributors");
266-
Binder binder = contributors.getBinder(activationContext, BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE);
271+
Binder binder = contributors.getBinder(activationContext,
272+
ConfigDataEnvironmentContributor::isNotIgnoringProfiles, BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE);
267273
try {
268274
Set<String> additionalProfiles = new LinkedHashSet<>(this.additionalProfiles);
269275
additionalProfiles.addAll(getIncludedProfiles(contributors, activationContext));
@@ -285,16 +291,15 @@ private Collection<? extends String> getIncludedProfiles(ConfigDataEnvironmentCo
285291
Set<String> result = new LinkedHashSet<>();
286292
for (ConfigDataEnvironmentContributor contributor : contributors) {
287293
ConfigurationPropertySource source = contributor.getConfigurationPropertySource();
288-
if (source == null) {
289-
continue;
294+
if (source != null && contributor.isNotIgnoringProfiles()) {
295+
Binder binder = new Binder(Collections.singleton(source), placeholdersResolver);
296+
binder.bind(Profiles.INCLUDE_PROFILES, STRING_LIST).ifBound((includes) -> {
297+
if (!contributor.isActive(activationContext)) {
298+
InactiveConfigDataAccessException.throwIfPropertyFound(contributor, Profiles.INCLUDE_PROFILES);
299+
}
300+
result.addAll(includes);
301+
});
290302
}
291-
Binder binder = new Binder(Collections.singleton(source), placeholdersResolver);
292-
binder.bind(Profiles.INCLUDE_PROFILES, STRING_LIST).ifBound((includes) -> {
293-
if (!contributor.isActive(activationContext)) {
294-
InactiveConfigDataAccessException.throwIfPropertyFound(contributor, Profiles.INCLUDE_PROFILES);
295-
}
296-
result.addAll(includes);
297-
});
298303
}
299304
return result;
300305
}

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironmentContributor.java

+27-14
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.util.List;
2424
import java.util.Map;
2525
import java.util.NoSuchElementException;
26+
import java.util.Set;
2627
import java.util.stream.Stream;
2728
import java.util.stream.StreamSupport;
2829

@@ -51,6 +52,9 @@
5152
*/
5253
class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironmentContributor> {
5354

55+
private static final Set<ConfigData.Option> EMPTY_LOCATION_OPTIONS = Collections
56+
.unmodifiableSet(Collections.singleton(ConfigData.Option.IGNORE_IMPORTS));
57+
5458
private final ConfigDataLocation location;
5559

5660
private final ConfigDataResource resource;
@@ -63,7 +67,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
6367

6468
private final ConfigDataProperties properties;
6569

66-
private final boolean ignoreImports;
70+
private final Set<ConfigData.Option> configDataOptions;
6771

6872
private final Map<ImportPhase, List<ConfigDataEnvironmentContributor>> children;
6973

@@ -79,21 +83,22 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
7983
* @param configurationPropertySource the configuration property source for the data
8084
* or {@code null}
8185
* @param properties the config data properties or {@code null}
82-
* @param ignoreImports if import properties should be ignored
86+
* @param configDataOptions any config data options that should apply
8387
* @param children the children of this contributor at each {@link ImportPhase}
8488
*/
8589
ConfigDataEnvironmentContributor(Kind kind, ConfigDataLocation location, ConfigDataResource resource,
8690
boolean profileSpecific, PropertySource<?> propertySource,
8791
ConfigurationPropertySource configurationPropertySource, ConfigDataProperties properties,
88-
boolean ignoreImports, Map<ImportPhase, List<ConfigDataEnvironmentContributor>> children) {
92+
Set<ConfigData.Option> configDataOptions,
93+
Map<ImportPhase, List<ConfigDataEnvironmentContributor>> children) {
8994
this.kind = kind;
9095
this.location = location;
9196
this.resource = resource;
9297
this.profileSpecific = profileSpecific;
9398
this.properties = properties;
9499
this.propertySource = propertySource;
95100
this.configurationPropertySource = configurationPropertySource;
96-
this.ignoreImports = ignoreImports;
101+
this.configDataOptions = (configDataOptions != null) ? configDataOptions : Collections.emptySet();
97102
this.children = (children != null) ? children : Collections.emptyMap();
98103
}
99104

@@ -150,6 +155,15 @@ ConfigurationPropertySource getConfigurationPropertySource() {
150155
return this.configurationPropertySource;
151156
}
152157

158+
/**
159+
* Returns {@code true} if this contributor is not ignoring profile properties.
160+
* @return if the contributor is not ignoring profiles
161+
* @see ConfigData.Option#IGNORE_PROFILES
162+
*/
163+
boolean isNotIgnoringProfiles() {
164+
return !this.configDataOptions.contains(ConfigData.Option.IGNORE_PROFILES);
165+
}
166+
153167
/**
154168
* Return any imports requested by this contributor.
155169
* @return the imports
@@ -209,12 +223,12 @@ public Iterator<ConfigDataEnvironmentContributor> iterator() {
209223
ConfigDataEnvironmentContributor withBoundProperties(Binder binder) {
210224
UseLegacyConfigProcessingException.throwIfRequested(binder);
211225
ConfigDataProperties properties = ConfigDataProperties.get(binder);
212-
if (this.ignoreImports) {
226+
if (this.configDataOptions.contains(ConfigData.Option.IGNORE_IMPORTS)) {
213227
properties = properties.withoutImports();
214228
}
215229
return new ConfigDataEnvironmentContributor(Kind.BOUND_IMPORT, this.location, this.resource,
216230
this.profileSpecific, this.propertySource, this.configurationPropertySource, properties,
217-
this.ignoreImports, null);
231+
this.configDataOptions, null);
218232
}
219233

220234
/**
@@ -229,7 +243,7 @@ ConfigDataEnvironmentContributor withChildren(ImportPhase importPhase,
229243
Map<ImportPhase, List<ConfigDataEnvironmentContributor>> updatedChildren = new LinkedHashMap<>(this.children);
230244
updatedChildren.put(importPhase, children);
231245
return new ConfigDataEnvironmentContributor(this.kind, this.location, this.resource, this.profileSpecific,
232-
this.propertySource, this.configurationPropertySource, this.properties, this.ignoreImports,
246+
this.propertySource, this.configurationPropertySource, this.properties, this.configDataOptions,
233247
updatedChildren);
234248
}
235249

@@ -255,7 +269,7 @@ ConfigDataEnvironmentContributor withReplacement(ConfigDataEnvironmentContributo
255269
updatedChildren.put(importPhase, Collections.unmodifiableList(updatedContributors));
256270
});
257271
return new ConfigDataEnvironmentContributor(this.kind, this.location, this.resource, this.profileSpecific,
258-
this.propertySource, this.configurationPropertySource, this.properties, this.ignoreImports,
272+
this.propertySource, this.configurationPropertySource, this.properties, this.configDataOptions,
259273
updatedChildren);
260274
}
261275

@@ -267,7 +281,7 @@ ConfigDataEnvironmentContributor withReplacement(ConfigDataEnvironmentContributo
267281
static ConfigDataEnvironmentContributor of(List<ConfigDataEnvironmentContributor> contributors) {
268282
Map<ImportPhase, List<ConfigDataEnvironmentContributor>> children = new LinkedHashMap<>();
269283
children.put(ImportPhase.BEFORE_PROFILE_ACTIVATION, Collections.unmodifiableList(contributors));
270-
return new ConfigDataEnvironmentContributor(Kind.ROOT, null, null, false, null, null, null, false, children);
284+
return new ConfigDataEnvironmentContributor(Kind.ROOT, null, null, false, null, null, null, null, children);
271285
}
272286

273287
/**
@@ -281,7 +295,7 @@ static ConfigDataEnvironmentContributor ofInitialImport(ConfigDataLocation initi
281295
List<ConfigDataLocation> imports = Collections.singletonList(initialImport);
282296
ConfigDataProperties properties = new ConfigDataProperties(imports, null);
283297
return new ConfigDataEnvironmentContributor(Kind.INITIAL_IMPORT, null, null, false, null, null, properties,
284-
false, null);
298+
null, null);
285299
}
286300

287301
/**
@@ -293,7 +307,7 @@ static ConfigDataEnvironmentContributor ofInitialImport(ConfigDataLocation initi
293307
*/
294308
static ConfigDataEnvironmentContributor ofExisting(PropertySource<?> propertySource) {
295309
return new ConfigDataEnvironmentContributor(Kind.EXISTING, null, null, false, propertySource,
296-
ConfigurationPropertySource.from(propertySource), null, false, null);
310+
ConfigurationPropertySource.from(propertySource), null, null, null);
297311
}
298312

299313
/**
@@ -311,9 +325,8 @@ static ConfigDataEnvironmentContributor ofUnboundImport(ConfigDataLocation locat
311325
boolean profileSpecific, ConfigData configData, int propertySourceIndex) {
312326
PropertySource<?> propertySource = configData.getPropertySources().get(propertySourceIndex);
313327
ConfigurationPropertySource configurationPropertySource = ConfigurationPropertySource.from(propertySource);
314-
boolean ignoreImports = configData.getOptions().contains(ConfigData.Option.IGNORE_IMPORTS);
315328
return new ConfigDataEnvironmentContributor(Kind.UNBOUND_IMPORT, location, resource, profileSpecific,
316-
propertySource, configurationPropertySource, null, ignoreImports, null);
329+
propertySource, configurationPropertySource, null, configData.getOptions(), null);
317330
}
318331

319332
/**
@@ -324,7 +337,7 @@ static ConfigDataEnvironmentContributor ofUnboundImport(ConfigDataLocation locat
324337
*/
325338
static ConfigDataEnvironmentContributor ofEmptyLocation(ConfigDataLocation location, boolean profileSpecific) {
326339
return new ConfigDataEnvironmentContributor(Kind.EMPTY_LOCATION, location, null, profileSpecific, null, null,
327-
null, true, null);
340+
null, EMPTY_LOCATION_OPTIONS, null);
328341
}
329342

330343
/**

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironmentContributors.java

+23-12
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
import java.util.List;
2525
import java.util.Map;
2626
import java.util.Set;
27+
import java.util.function.Predicate;
2728
import java.util.stream.Collectors;
28-
import java.util.stream.Stream;
2929

3030
import org.apache.commons.logging.Log;
3131

@@ -52,6 +52,8 @@
5252
*/
5353
class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmentContributor> {
5454

55+
private static final Predicate<ConfigDataEnvironmentContributor> NO_CONTRIBUTOR_FILTER = (contributor) -> true;
56+
5557
private final Log logger;
5658

5759
private final ConfigDataEnvironmentContributor root;
@@ -186,38 +188,47 @@ ConfigDataEnvironmentContributor getRoot() {
186188
}
187189

188190
/**
189-
* Return a {@link Binder} that works against all active contributors.
191+
* Return a {@link Binder} backed by the contributors.
190192
* @param activationContext the activation context
191193
* @param options binder options to apply
192194
* @return a binder instance
193195
*/
194196
Binder getBinder(ConfigDataActivationContext activationContext, BinderOption... options) {
195-
return getBinder(activationContext, asBinderOptionsSet(options));
197+
return getBinder(activationContext, NO_CONTRIBUTOR_FILTER, options);
198+
}
199+
200+
/**
201+
* Return a {@link Binder} backed by the contributors.
202+
* @param activationContext the activation context
203+
* @param filter a filter used to limit the contributors
204+
* @param options binder options to apply
205+
* @return a binder instance
206+
*/
207+
Binder getBinder(ConfigDataActivationContext activationContext, Predicate<ConfigDataEnvironmentContributor> filter,
208+
BinderOption... options) {
209+
return getBinder(activationContext, filter, asBinderOptionsSet(options));
196210
}
197211

198212
private Set<BinderOption> asBinderOptionsSet(BinderOption... options) {
199213
return ObjectUtils.isEmpty(options) ? EnumSet.noneOf(BinderOption.class)
200214
: EnumSet.copyOf(Arrays.asList(options));
201215
}
202216

203-
private Binder getBinder(ConfigDataActivationContext activationContext, Set<BinderOption> options) {
217+
private Binder getBinder(ConfigDataActivationContext activationContext,
218+
Predicate<ConfigDataEnvironmentContributor> filter, Set<BinderOption> options) {
204219
boolean failOnInactiveSource = options.contains(BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE);
205220
Iterable<ConfigurationPropertySource> sources = () -> getBinderSources(activationContext,
206-
!options.contains(BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE));
221+
filter.and((contributor) -> failOnInactiveSource || contributor.isActive(activationContext)));
207222
PlaceholdersResolver placeholdersResolver = new ConfigDataEnvironmentContributorPlaceholdersResolver(this.root,
208223
activationContext, failOnInactiveSource);
209224
BindHandler bindHandler = !failOnInactiveSource ? null : new InactiveSourceChecker(activationContext);
210225
return new Binder(sources, placeholdersResolver, null, null, bindHandler);
211226
}
212227

213228
private Iterator<ConfigurationPropertySource> getBinderSources(ConfigDataActivationContext activationContext,
214-
boolean filterInactive) {
215-
Stream<ConfigDataEnvironmentContributor> sources = this.root.stream()
216-
.filter(this::hasConfigurationPropertySource);
217-
if (filterInactive) {
218-
sources = sources.filter((contributor) -> contributor.isActive(activationContext));
219-
}
220-
return sources.map(ConfigDataEnvironmentContributor::getConfigurationPropertySource).iterator();
229+
Predicate<ConfigDataEnvironmentContributor> filter) {
230+
return this.root.stream().filter(this::hasConfigurationPropertySource).filter(filter)
231+
.map(ConfigDataEnvironmentContributor::getConfigurationPropertySource).iterator();
221232
}
222233

223234
private boolean hasConfigurationPropertySource(ConfigDataEnvironmentContributor contributor) {

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/InvalidConfigDataPropertyException.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ static void throwOrWarn(Log logger, ConfigDataEnvironmentContributor contributor
114114
logger.warn(getMessage(property, false, replacement, contributor.getResource()));
115115
}
116116
});
117-
if (contributor.isProfileSpecific()) {
117+
if (contributor.isProfileSpecific() && contributor.isNotIgnoringProfiles()) {
118118
PROFILE_SPECIFIC_ERRORS.forEach((name) -> {
119119
ConfigurationProperty property = propertySource.getConfigurationProperty(name);
120120
if (property != null) {

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigDataEnvironmentContributorPlaceholdersResolverTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ static class TestConfigDataEnvironmentContributor extends ConfigDataEnvironmentC
122122
private final boolean active;
123123

124124
protected TestConfigDataEnvironmentContributor(PropertySource<?> propertySource, boolean active) {
125-
super(Kind.ROOT, null, null, false, propertySource, null, null, false, null);
125+
super(Kind.ROOT, null, null, false, propertySource, null, null, null, null);
126126
this.active = active;
127127
}
128128

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigDataEnvironmentTests.java

+29-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,7 +18,9 @@
1818

1919
import java.util.Collection;
2020
import java.util.Collections;
21+
import java.util.LinkedHashMap;
2122
import java.util.List;
23+
import java.util.Map;
2224
import java.util.function.Supplier;
2325
import java.util.stream.Collectors;
2426

@@ -34,6 +36,7 @@
3436
import org.springframework.boot.context.properties.bind.Binder;
3537
import org.springframework.boot.logging.DeferredLogFactory;
3638
import org.springframework.core.env.ConfigurableEnvironment;
39+
import org.springframework.core.env.MapPropertySource;
3740
import org.springframework.core.env.PropertySource;
3841
import org.springframework.core.io.DefaultResourceLoader;
3942
import org.springframework.core.io.ResourceLoader;
@@ -42,6 +45,7 @@
4245

4346
import static org.assertj.core.api.Assertions.assertThat;
4447
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
48+
import static org.mockito.Mockito.mock;
4549

4650
/**
4751
* Tests for {@link ConfigDataEnvironment}.
@@ -188,6 +192,30 @@ void processAndApplySetsActiveProfilesAndProfileGroups(TestInfo info) {
188192
assertThat(this.environment.getActiveProfiles()).containsExactly("one", "four", "five", "two", "three");
189193
}
190194

195+
@Test
196+
void processAndApplyDoesNotSetProfilesFromIgnoreProfilesContributors(TestInfo info) {
197+
this.environment.setProperty("spring.config.location", getConfigLocation(info));
198+
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
199+
this.environment, this.resourceLoader, this.additionalProfiles, null) {
200+
201+
@Override
202+
protected ConfigDataEnvironmentContributors createContributors(
203+
List<ConfigDataEnvironmentContributor> contributors) {
204+
Map<String, Object> source = new LinkedHashMap<>();
205+
source.put("spring.profiles.active", "ignore1");
206+
source.put("spring.profiles.include", "ignore2");
207+
ConfigData data = new ConfigData(Collections.singleton(new MapPropertySource("test", source)),
208+
ConfigData.Option.IGNORE_PROFILES);
209+
contributors.add(ConfigDataEnvironmentContributor.ofUnboundImport(ConfigDataLocation.of("test"),
210+
mock(ConfigDataResource.class), false, data, 0));
211+
return super.createContributors(contributors);
212+
}
213+
214+
};
215+
configDataEnvironment.processAndApply();
216+
assertThat(this.environment.getActiveProfiles()).containsExactly("test");
217+
}
218+
191219
@Test
192220
@Disabled("Disabled until spring.profiles support is dropped")
193221
void processAndApplyWhenHasInvalidPropertyThrowsException() {

0 commit comments

Comments
 (0)