Browse Source

AbstractEnvironment defensively synchronizes access to activeProfiles and defaultProfiles

Issue: SPR-13213
pull/860/merge
Juergen Hoeller 11 years ago
parent
commit
e393c7b1ee
  1. 84
      spring-core/src/main/java/org/springframework/core/env/AbstractEnvironment.java

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

@ -28,6 +28,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.core.SpringProperties; import org.springframework.core.SpringProperties;
import org.springframework.core.convert.support.ConfigurableConversionService; import org.springframework.core.convert.support.ConfigurableConversionService;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import static java.lang.String.*; import static java.lang.String.*;
@ -103,9 +104,9 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment {
protected final Log logger = LogFactory.getLog(getClass()); protected final Log logger = LogFactory.getLog(getClass());
private Set<String> activeProfiles = new LinkedHashSet<String>(); private final Set<String> activeProfiles = new LinkedHashSet<String>();
private Set<String> defaultProfiles = new LinkedHashSet<String>(getReservedDefaultProfiles()); private final Set<String> defaultProfiles = new LinkedHashSet<String>(getReservedDefaultProfiles());
private final MutablePropertySources propertySources = new MutablePropertySources(this.logger); private final MutablePropertySources propertySources = new MutablePropertySources(this.logger);
@ -237,22 +238,26 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment {
* @see #ACTIVE_PROFILES_PROPERTY_NAME * @see #ACTIVE_PROFILES_PROPERTY_NAME
*/ */
protected Set<String> doGetActiveProfiles() { protected Set<String> doGetActiveProfiles() {
if (this.activeProfiles.isEmpty()) { synchronized (this.activeProfiles) {
String profiles = getProperty(ACTIVE_PROFILES_PROPERTY_NAME); if (this.activeProfiles.isEmpty()) {
if (StringUtils.hasText(profiles)) { String profiles = getProperty(ACTIVE_PROFILES_PROPERTY_NAME);
setActiveProfiles(commaDelimitedListToStringArray(trimAllWhitespace(profiles))); if (StringUtils.hasText(profiles)) {
setActiveProfiles(commaDelimitedListToStringArray(trimAllWhitespace(profiles)));
}
} }
return this.activeProfiles;
} }
return this.activeProfiles;
} }
@Override @Override
public void setActiveProfiles(String... profiles) { public void setActiveProfiles(String... profiles) {
Assert.notNull(profiles, "Profile array must not be null"); Assert.notNull(profiles, "Profile array must not be null");
this.activeProfiles.clear(); synchronized (this.activeProfiles) {
for (String profile : profiles) { this.activeProfiles.clear();
validateProfile(profile); for (String profile : profiles) {
this.activeProfiles.add(profile); validateProfile(profile);
this.activeProfiles.add(profile);
}
} }
} }
@ -263,7 +268,9 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment {
} }
validateProfile(profile); validateProfile(profile);
doGetActiveProfiles(); doGetActiveProfiles();
this.activeProfiles.add(profile); synchronized (this.activeProfiles) {
this.activeProfiles.add(profile);
}
} }
@ -285,13 +292,15 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment {
* @see #getReservedDefaultProfiles() * @see #getReservedDefaultProfiles()
*/ */
protected Set<String> doGetDefaultProfiles() { protected Set<String> doGetDefaultProfiles() {
if (this.defaultProfiles.equals(getReservedDefaultProfiles())) { synchronized (this.defaultProfiles) {
String profiles = getProperty(DEFAULT_PROFILES_PROPERTY_NAME); if (this.defaultProfiles.equals(getReservedDefaultProfiles())) {
if (StringUtils.hasText(profiles)) { String profiles = getProperty(DEFAULT_PROFILES_PROPERTY_NAME);
setDefaultProfiles(commaDelimitedListToStringArray(trimAllWhitespace(profiles))); if (StringUtils.hasText(profiles)) {
setDefaultProfiles(commaDelimitedListToStringArray(trimAllWhitespace(profiles)));
}
} }
return this.defaultProfiles;
} }
return this.defaultProfiles;
} }
/** /**
@ -305,10 +314,12 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment {
@Override @Override
public void setDefaultProfiles(String... profiles) { public void setDefaultProfiles(String... profiles) {
Assert.notNull(profiles, "Profile array must not be null"); Assert.notNull(profiles, "Profile array must not be null");
this.defaultProfiles.clear(); synchronized (this.defaultProfiles) {
for (String profile : profiles) { this.defaultProfiles.clear();
validateProfile(profile); for (String profile : profiles) {
this.defaultProfiles.add(profile); validateProfile(profile);
this.defaultProfiles.add(profile);
}
} }
} }
@ -316,7 +327,7 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment {
public boolean acceptsProfiles(String... profiles) { public boolean acceptsProfiles(String... profiles) {
Assert.notEmpty(profiles, "Must specify at least one profile"); Assert.notEmpty(profiles, "Must specify at least one profile");
for (String profile : profiles) { for (String profile : profiles) {
if (profile != null && profile.length() > 0 && profile.charAt(0) == '!') { if (StringUtils.hasLength(profile) && profile.charAt(0) == '!') {
if (!isProfileActive(profile.substring(1))) { if (!isProfileActive(profile.substring(1))) {
return true; return true;
} }
@ -335,8 +346,9 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment {
*/ */
protected boolean isProfileActive(String profile) { protected boolean isProfileActive(String profile) {
validateProfile(profile); validateProfile(profile);
return doGetActiveProfiles().contains(profile) || Set<String> currentActiveProfiles = doGetActiveProfiles();
(doGetActiveProfiles().isEmpty() && doGetDefaultProfiles().contains(profile)); return (currentActiveProfiles.contains(profile) ||
(currentActiveProfiles.isEmpty() && doGetDefaultProfiles().contains(profile)));
} }
/** /**
@ -364,7 +376,7 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment {
} }
@Override @Override
@SuppressWarnings({ "unchecked", "rawtypes" }) @SuppressWarnings({"unchecked", "rawtypes"})
public Map<String, Object> getSystemEnvironment() { public Map<String, Object> getSystemEnvironment() {
if (suppressGetenvAccess()) { if (suppressGetenvAccess()) {
return Collections.emptyMap(); return Collections.emptyMap();
@ -408,7 +420,7 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment {
} }
@Override @Override
@SuppressWarnings({ "unchecked", "rawtypes" }) @SuppressWarnings({"unchecked", "rawtypes"})
public Map<String, Object> getSystemProperties() { public Map<String, Object> getSystemProperties() {
try { try {
return (Map) System.getProperties(); return (Map) System.getProperties();
@ -440,13 +452,21 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment {
this.propertySources.addLast(ps); this.propertySources.addLast(ps);
} }
} }
for (String profile : parent.getActiveProfiles()) { String[] parentActiveProfiles = parent.getActiveProfiles();
this.activeProfiles.add(profile); if (!ObjectUtils.isEmpty(parentActiveProfiles)) {
synchronized (this.activeProfiles) {
for (String profile : parentActiveProfiles) {
this.activeProfiles.add(profile);
}
}
} }
if (parent.getDefaultProfiles().length > 0) { String[] parentDefaultProfiles = parent.getDefaultProfiles();
this.defaultProfiles.remove(RESERVED_DEFAULT_PROFILE_NAME); if (!ObjectUtils.isEmpty(parentDefaultProfiles)) {
for (String profile : parent.getDefaultProfiles()) { synchronized (this.defaultProfiles) {
this.defaultProfiles.add(profile); this.defaultProfiles.remove(RESERVED_DEFAULT_PROFILE_NAME);
for (String profile : parentDefaultProfiles) {
this.defaultProfiles.add(profile);
}
} }
} }
} }

Loading…
Cancel
Save