Skip to content

Commit e393c7b

Browse files
committed
AbstractEnvironment defensively synchronizes access to activeProfiles and defaultProfiles
Issue: SPR-13213
1 parent e214e64 commit e393c7b

File tree

1 file changed

+52
-32
lines changed

1 file changed

+52
-32
lines changed

spring-core/src/main/java/org/springframework/core/env/AbstractEnvironment.java

Lines changed: 52 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.springframework.core.SpringProperties;
2929
import org.springframework.core.convert.support.ConfigurableConversionService;
3030
import org.springframework.util.Assert;
31+
import org.springframework.util.ObjectUtils;
3132
import org.springframework.util.StringUtils;
3233

3334
import static java.lang.String.*;
@@ -103,9 +104,9 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment {
103104

104105
protected final Log logger = LogFactory.getLog(getClass());
105106

106-
private Set<String> activeProfiles = new LinkedHashSet<String>();
107+
private final Set<String> activeProfiles = new LinkedHashSet<String>();
107108

108-
private Set<String> defaultProfiles = new LinkedHashSet<String>(getReservedDefaultProfiles());
109+
private final Set<String> defaultProfiles = new LinkedHashSet<String>(getReservedDefaultProfiles());
109110

110111
private final MutablePropertySources propertySources = new MutablePropertySources(this.logger);
111112

@@ -237,22 +238,26 @@ public String[] getActiveProfiles() {
237238
* @see #ACTIVE_PROFILES_PROPERTY_NAME
238239
*/
239240
protected Set<String> doGetActiveProfiles() {
240-
if (this.activeProfiles.isEmpty()) {
241-
String profiles = getProperty(ACTIVE_PROFILES_PROPERTY_NAME);
242-
if (StringUtils.hasText(profiles)) {
243-
setActiveProfiles(commaDelimitedListToStringArray(trimAllWhitespace(profiles)));
241+
synchronized (this.activeProfiles) {
242+
if (this.activeProfiles.isEmpty()) {
243+
String profiles = getProperty(ACTIVE_PROFILES_PROPERTY_NAME);
244+
if (StringUtils.hasText(profiles)) {
245+
setActiveProfiles(commaDelimitedListToStringArray(trimAllWhitespace(profiles)));
246+
}
244247
}
248+
return this.activeProfiles;
245249
}
246-
return this.activeProfiles;
247250
}
248251

249252
@Override
250253
public void setActiveProfiles(String... profiles) {
251254
Assert.notNull(profiles, "Profile array must not be null");
252-
this.activeProfiles.clear();
253-
for (String profile : profiles) {
254-
validateProfile(profile);
255-
this.activeProfiles.add(profile);
255+
synchronized (this.activeProfiles) {
256+
this.activeProfiles.clear();
257+
for (String profile : profiles) {
258+
validateProfile(profile);
259+
this.activeProfiles.add(profile);
260+
}
256261
}
257262
}
258263

@@ -263,7 +268,9 @@ public void addActiveProfile(String profile) {
263268
}
264269
validateProfile(profile);
265270
doGetActiveProfiles();
266-
this.activeProfiles.add(profile);
271+
synchronized (this.activeProfiles) {
272+
this.activeProfiles.add(profile);
273+
}
267274
}
268275

269276

@@ -285,13 +292,15 @@ public String[] getDefaultProfiles() {
285292
* @see #getReservedDefaultProfiles()
286293
*/
287294
protected Set<String> doGetDefaultProfiles() {
288-
if (this.defaultProfiles.equals(getReservedDefaultProfiles())) {
289-
String profiles = getProperty(DEFAULT_PROFILES_PROPERTY_NAME);
290-
if (StringUtils.hasText(profiles)) {
291-
setDefaultProfiles(commaDelimitedListToStringArray(trimAllWhitespace(profiles)));
295+
synchronized (this.defaultProfiles) {
296+
if (this.defaultProfiles.equals(getReservedDefaultProfiles())) {
297+
String profiles = getProperty(DEFAULT_PROFILES_PROPERTY_NAME);
298+
if (StringUtils.hasText(profiles)) {
299+
setDefaultProfiles(commaDelimitedListToStringArray(trimAllWhitespace(profiles)));
300+
}
292301
}
302+
return this.defaultProfiles;
293303
}
294-
return this.defaultProfiles;
295304
}
296305

297306
/**
@@ -305,18 +314,20 @@ protected Set<String> doGetDefaultProfiles() {
305314
@Override
306315
public void setDefaultProfiles(String... profiles) {
307316
Assert.notNull(profiles, "Profile array must not be null");
308-
this.defaultProfiles.clear();
309-
for (String profile : profiles) {
310-
validateProfile(profile);
311-
this.defaultProfiles.add(profile);
317+
synchronized (this.defaultProfiles) {
318+
this.defaultProfiles.clear();
319+
for (String profile : profiles) {
320+
validateProfile(profile);
321+
this.defaultProfiles.add(profile);
322+
}
312323
}
313324
}
314325

315326
@Override
316327
public boolean acceptsProfiles(String... profiles) {
317328
Assert.notEmpty(profiles, "Must specify at least one profile");
318329
for (String profile : profiles) {
319-
if (profile != null && profile.length() > 0 && profile.charAt(0) == '!') {
330+
if (StringUtils.hasLength(profile) && profile.charAt(0) == '!') {
320331
if (!isProfileActive(profile.substring(1))) {
321332
return true;
322333
}
@@ -335,8 +346,9 @@ else if (isProfileActive(profile)) {
335346
*/
336347
protected boolean isProfileActive(String profile) {
337348
validateProfile(profile);
338-
return doGetActiveProfiles().contains(profile) ||
339-
(doGetActiveProfiles().isEmpty() && doGetDefaultProfiles().contains(profile));
349+
Set<String> currentActiveProfiles = doGetActiveProfiles();
350+
return (currentActiveProfiles.contains(profile) ||
351+
(currentActiveProfiles.isEmpty() && doGetDefaultProfiles().contains(profile)));
340352
}
341353

342354
/**
@@ -364,7 +376,7 @@ public MutablePropertySources getPropertySources() {
364376
}
365377

366378
@Override
367-
@SuppressWarnings({ "unchecked", "rawtypes" })
379+
@SuppressWarnings({"unchecked", "rawtypes"})
368380
public Map<String, Object> getSystemEnvironment() {
369381
if (suppressGetenvAccess()) {
370382
return Collections.emptyMap();
@@ -408,7 +420,7 @@ protected boolean suppressGetenvAccess() {
408420
}
409421

410422
@Override
411-
@SuppressWarnings({ "unchecked", "rawtypes" })
423+
@SuppressWarnings({"unchecked", "rawtypes"})
412424
public Map<String, Object> getSystemProperties() {
413425
try {
414426
return (Map) System.getProperties();
@@ -440,13 +452,21 @@ public void merge(ConfigurableEnvironment parent) {
440452
this.propertySources.addLast(ps);
441453
}
442454
}
443-
for (String profile : parent.getActiveProfiles()) {
444-
this.activeProfiles.add(profile);
455+
String[] parentActiveProfiles = parent.getActiveProfiles();
456+
if (!ObjectUtils.isEmpty(parentActiveProfiles)) {
457+
synchronized (this.activeProfiles) {
458+
for (String profile : parentActiveProfiles) {
459+
this.activeProfiles.add(profile);
460+
}
461+
}
445462
}
446-
if (parent.getDefaultProfiles().length > 0) {
447-
this.defaultProfiles.remove(RESERVED_DEFAULT_PROFILE_NAME);
448-
for (String profile : parent.getDefaultProfiles()) {
449-
this.defaultProfiles.add(profile);
463+
String[] parentDefaultProfiles = parent.getDefaultProfiles();
464+
if (!ObjectUtils.isEmpty(parentDefaultProfiles)) {
465+
synchronized (this.defaultProfiles) {
466+
this.defaultProfiles.remove(RESERVED_DEFAULT_PROFILE_NAME);
467+
for (String profile : parentDefaultProfiles) {
468+
this.defaultProfiles.add(profile);
469+
}
450470
}
451471
}
452472
}

0 commit comments

Comments
 (0)