Skip to content

Commit d2447ce

Browse files
committed
AbstractEnvironment defensively synchronizes access to activeProfiles and defaultProfiles
Issue: SPR-13213 (cherry picked from commit af5f4e6)
1 parent 30a55d7 commit d2447ce

File tree

1 file changed

+51
-31
lines changed

1 file changed

+51
-31
lines changed

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

Lines changed: 51 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2015 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.
@@ -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

@@ -236,21 +237,25 @@ public String[] getActiveProfiles() {
236237
* @see #ACTIVE_PROFILES_PROPERTY_NAME
237238
*/
238239
protected Set<String> doGetActiveProfiles() {
239-
if (this.activeProfiles.isEmpty()) {
240-
String profiles = getProperty(ACTIVE_PROFILES_PROPERTY_NAME);
241-
if (StringUtils.hasText(profiles)) {
242-
setActiveProfiles(commaDelimitedListToStringArray(trimAllWhitespace(profiles)));
240+
synchronized (this.activeProfiles) {
241+
if (this.activeProfiles.isEmpty()) {
242+
String profiles = getProperty(ACTIVE_PROFILES_PROPERTY_NAME);
243+
if (StringUtils.hasText(profiles)) {
244+
setActiveProfiles(commaDelimitedListToStringArray(trimAllWhitespace(profiles)));
245+
}
243246
}
247+
return this.activeProfiles;
244248
}
245-
return this.activeProfiles;
246249
}
247250

248251
public void setActiveProfiles(String... profiles) {
249252
Assert.notNull(profiles, "Profile array must not be null");
250-
this.activeProfiles.clear();
251-
for (String profile : profiles) {
252-
validateProfile(profile);
253-
this.activeProfiles.add(profile);
253+
synchronized (this.activeProfiles) {
254+
this.activeProfiles.clear();
255+
for (String profile : profiles) {
256+
validateProfile(profile);
257+
this.activeProfiles.add(profile);
258+
}
254259
}
255260
}
256261

@@ -260,7 +265,9 @@ public void addActiveProfile(String profile) {
260265
}
261266
validateProfile(profile);
262267
doGetActiveProfiles();
263-
this.activeProfiles.add(profile);
268+
synchronized (this.activeProfiles) {
269+
this.activeProfiles.add(profile);
270+
}
264271
}
265272

266273

@@ -281,13 +288,15 @@ public String[] getDefaultProfiles() {
281288
* @see #getReservedDefaultProfiles()
282289
*/
283290
protected Set<String> doGetDefaultProfiles() {
284-
if (this.defaultProfiles.equals(getReservedDefaultProfiles())) {
285-
String profiles = getProperty(DEFAULT_PROFILES_PROPERTY_NAME);
286-
if (StringUtils.hasText(profiles)) {
287-
setDefaultProfiles(commaDelimitedListToStringArray(trimAllWhitespace(profiles)));
291+
synchronized (this.defaultProfiles) {
292+
if (this.defaultProfiles.equals(getReservedDefaultProfiles())) {
293+
String profiles = getProperty(DEFAULT_PROFILES_PROPERTY_NAME);
294+
if (StringUtils.hasText(profiles)) {
295+
setDefaultProfiles(commaDelimitedListToStringArray(trimAllWhitespace(profiles)));
296+
}
288297
}
298+
return this.defaultProfiles;
289299
}
290-
return this.defaultProfiles;
291300
}
292301

293302
/**
@@ -300,17 +309,19 @@ protected Set<String> doGetDefaultProfiles() {
300309
*/
301310
public void setDefaultProfiles(String... profiles) {
302311
Assert.notNull(profiles, "Profile array must not be null");
303-
this.defaultProfiles.clear();
304-
for (String profile : profiles) {
305-
validateProfile(profile);
306-
this.defaultProfiles.add(profile);
312+
synchronized (this.defaultProfiles) {
313+
this.defaultProfiles.clear();
314+
for (String profile : profiles) {
315+
validateProfile(profile);
316+
this.defaultProfiles.add(profile);
317+
}
307318
}
308319
}
309320

310321
public boolean acceptsProfiles(String... profiles) {
311322
Assert.notEmpty(profiles, "Must specify at least one profile");
312323
for (String profile : profiles) {
313-
if (profile != null && profile.length() > 0 && profile.charAt(0) == '!') {
324+
if (StringUtils.hasLength(profile) && profile.charAt(0) == '!') {
314325
if (!isProfileActive(profile.substring(1))) {
315326
return true;
316327
}
@@ -329,8 +340,9 @@ else if (isProfileActive(profile)) {
329340
*/
330341
protected boolean isProfileActive(String profile) {
331342
validateProfile(profile);
332-
return doGetActiveProfiles().contains(profile) ||
333-
(doGetActiveProfiles().isEmpty() && doGetDefaultProfiles().contains(profile));
343+
Set<String> currentActiveProfiles = doGetActiveProfiles();
344+
return (currentActiveProfiles.contains(profile) ||
345+
(currentActiveProfiles.isEmpty() && doGetDefaultProfiles().contains(profile)));
334346
}
335347

336348
/**
@@ -430,13 +442,21 @@ public void merge(ConfigurableEnvironment parent) {
430442
this.propertySources.addLast(ps);
431443
}
432444
}
433-
for (String profile : parent.getActiveProfiles()) {
434-
this.activeProfiles.add(profile);
445+
String[] parentActiveProfiles = parent.getActiveProfiles();
446+
if (!ObjectUtils.isEmpty(parentActiveProfiles)) {
447+
synchronized (this.activeProfiles) {
448+
for (String profile : parentActiveProfiles) {
449+
this.activeProfiles.add(profile);
450+
}
451+
}
435452
}
436-
if (parent.getDefaultProfiles().length > 0) {
437-
this.defaultProfiles.remove(RESERVED_DEFAULT_PROFILE_NAME);
438-
for (String profile : parent.getDefaultProfiles()) {
439-
this.defaultProfiles.add(profile);
453+
String[] parentDefaultProfiles = parent.getDefaultProfiles();
454+
if (!ObjectUtils.isEmpty(parentDefaultProfiles)) {
455+
synchronized (this.defaultProfiles) {
456+
this.defaultProfiles.remove(RESERVED_DEFAULT_PROFILE_NAME);
457+
for (String profile : parentDefaultProfiles) {
458+
this.defaultProfiles.add(profile);
459+
}
440460
}
441461
}
442462
}

0 commit comments

Comments
 (0)