Skip to content

Commit 1ef06cc

Browse files
committed
MutablePropertySources uses an internal CopyOnWriteArrayList for defensiveness against concurrent modifications
Issue: SPR-12428
1 parent b4167be commit 1ef06cc

File tree

2 files changed

+33
-36
lines changed

2 files changed

+33
-36
lines changed

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

+19-19
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@
1717
package org.springframework.core.env;
1818

1919
import java.util.Iterator;
20-
import java.util.LinkedList;
20+
import java.util.List;
21+
import java.util.concurrent.CopyOnWriteArrayList;
2122

2223
import org.apache.commons.logging.Log;
2324
import org.apache.commons.logging.LogFactory;
2425

25-
import org.springframework.util.Assert;
2626
import org.springframework.util.StringUtils;
2727

2828
/**
@@ -35,24 +35,22 @@
3535
* will be searched when resolving a given property with a {@link PropertyResolver}.
3636
*
3737
* @author Chris Beams
38+
* @author Juergen Hoeller
3839
* @since 3.1
3940
* @see PropertySourcesPropertyResolver
4041
*/
4142
public class MutablePropertySources implements PropertySources {
4243

43-
static final String NON_EXISTENT_PROPERTY_SOURCE_MESSAGE = "PropertySource named [%s] does not exist";
44-
static final String ILLEGAL_RELATIVE_ADDITION_MESSAGE = "PropertySource named [%s] cannot be added relative to itself";
45-
4644
private final Log logger;
4745

48-
private final LinkedList<PropertySource<?>> propertySourceList = new LinkedList<PropertySource<?>>();
46+
private final List<PropertySource<?>> propertySourceList = new CopyOnWriteArrayList<PropertySource<?>>();
4947

5048

5149
/**
5250
* Create a new {@link MutablePropertySources} object.
5351
*/
5452
public MutablePropertySources() {
55-
this.logger = LogFactory.getLog(this.getClass());
53+
this.logger = LogFactory.getLog(getClass());
5654
}
5755

5856
/**
@@ -62,7 +60,7 @@ public MutablePropertySources() {
6260
public MutablePropertySources(PropertySources propertySources) {
6361
this();
6462
for (PropertySource<?> propertySource : propertySources) {
65-
this.addLast(propertySource);
63+
addLast(propertySource);
6664
}
6765
}
6866

@@ -83,7 +81,7 @@ public boolean contains(String name) {
8381
@Override
8482
public PropertySource<?> get(String name) {
8583
int index = this.propertySourceList.indexOf(PropertySource.named(name));
86-
return index == -1 ? null : this.propertySourceList.get(index);
84+
return (index != -1 ? this.propertySourceList.get(index) : null);
8785
}
8886

8987
@Override
@@ -100,7 +98,7 @@ public void addFirst(PropertySource<?> propertySource) {
10098
propertySource.getName()));
10199
}
102100
removeIfPresent(propertySource);
103-
this.propertySourceList.addFirst(propertySource);
101+
this.propertySourceList.add(0, propertySource);
104102
}
105103

106104
/**
@@ -112,7 +110,7 @@ public void addLast(PropertySource<?> propertySource) {
112110
propertySource.getName()));
113111
}
114112
removeIfPresent(propertySource);
115-
this.propertySourceList.addLast(propertySource);
113+
this.propertySourceList.add(propertySource);
116114
}
117115

118116
/**
@@ -161,7 +159,7 @@ public PropertySource<?> remove(String name) {
161159
logger.debug(String.format("Removing [%s] PropertySource", name));
162160
}
163161
int index = this.propertySourceList.indexOf(PropertySource.named(name));
164-
return index == -1 ? null : this.propertySourceList.remove(index);
162+
return (index != -1 ? this.propertySourceList.remove(index) : null);
165163
}
166164

167165
/**
@@ -190,7 +188,7 @@ public int size() {
190188
@Override
191189
public String toString() {
192190
String[] names = new String[this.size()];
193-
for (int i=0; i < size(); i++) {
191+
for (int i = 0; i < size(); i++) {
194192
names[i] = this.propertySourceList.get(i).getName();
195193
}
196194
return String.format("[%s]", StringUtils.arrayToCommaDelimitedString(names));
@@ -201,17 +199,17 @@ public String toString() {
201199
*/
202200
protected void assertLegalRelativeAddition(String relativePropertySourceName, PropertySource<?> propertySource) {
203201
String newPropertySourceName = propertySource.getName();
204-
Assert.isTrue(!relativePropertySourceName.equals(newPropertySourceName),
205-
String.format(ILLEGAL_RELATIVE_ADDITION_MESSAGE, newPropertySourceName));
202+
if (relativePropertySourceName.equals(newPropertySourceName)) {
203+
throw new IllegalArgumentException(
204+
String.format("PropertySource named [%s] cannot be added relative to itself", newPropertySourceName));
205+
}
206206
}
207207

208208
/**
209209
* Remove the given property source if it is present.
210210
*/
211211
protected void removeIfPresent(PropertySource<?> propertySource) {
212-
if (this.propertySourceList.contains(propertySource)) {
213-
this.propertySourceList.remove(propertySource);
214-
}
212+
this.propertySourceList.remove(propertySource);
215213
}
216214

217215
/**
@@ -230,7 +228,9 @@ private void addAtIndex(int index, PropertySource<?> propertySource) {
230228
*/
231229
private int assertPresentAndGetIndex(String name) {
232230
int index = this.propertySourceList.indexOf(PropertySource.named(name));
233-
Assert.isTrue(index >= 0, String.format(NON_EXISTENT_PROPERTY_SOURCE_MESSAGE, name));
231+
if (index == -1) {
232+
throw new IllegalArgumentException(String.format("PropertySource named [%s] does not exist", name));
233+
}
234234
return index;
235235
}
236236

spring-core/src/test/java/org/springframework/core/env/MutablePropertySourcesTests.java

+14-17
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2014 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.
@@ -20,15 +20,12 @@
2020

2121
import org.springframework.mock.env.MockPropertySource;
2222

23-
import static java.lang.String.format;
2423
import static org.hamcrest.CoreMatchers.*;
2524
import static org.junit.Assert.*;
26-
import static org.springframework.core.env.MutablePropertySources.*;
2725

2826
/**
29-
* Unit tests for {@link MutablePropertySources}
30-
*
3127
* @author Chris Beams
28+
* @author Juergen Hoeller
3229
*/
3330
public class MutablePropertySourcesTests {
3431

@@ -106,9 +103,9 @@ public void test() {
106103
try {
107104
sources.addAfter(bogusPS, new MockPropertySource("h"));
108105
fail("expected non-existent PropertySource exception");
109-
} catch (IllegalArgumentException ex) {
110-
assertThat(ex.getMessage(),
111-
equalTo(format(NON_EXISTENT_PROPERTY_SOURCE_MESSAGE, bogusPS)));
106+
}
107+
catch (IllegalArgumentException ex) {
108+
assertTrue(ex.getMessage().contains("does not exist"));
112109
}
113110

114111
sources.addFirst(new MockPropertySource("a"));
@@ -128,25 +125,25 @@ public void test() {
128125
try {
129126
sources.replace(bogusPS, new MockPropertySource("bogus-replaced"));
130127
fail("expected non-existent PropertySource exception");
131-
} catch (IllegalArgumentException ex) {
132-
assertThat(ex.getMessage(),
133-
equalTo(format(NON_EXISTENT_PROPERTY_SOURCE_MESSAGE, bogusPS)));
128+
}
129+
catch (IllegalArgumentException ex) {
130+
assertTrue(ex.getMessage().contains("does not exist"));
134131
}
135132

136133
try {
137134
sources.addBefore("b", new MockPropertySource("b"));
138135
fail("expected exception");
139-
} catch (IllegalArgumentException ex) {
140-
assertThat(ex.getMessage(),
141-
equalTo(format(ILLEGAL_RELATIVE_ADDITION_MESSAGE, "b")));
136+
}
137+
catch (IllegalArgumentException ex) {
138+
assertTrue(ex.getMessage().contains("cannot be added relative to itself"));
142139
}
143140

144141
try {
145142
sources.addAfter("b", new MockPropertySource("b"));
146143
fail("expected exception");
147-
} catch (IllegalArgumentException ex) {
148-
assertThat(ex.getMessage(),
149-
equalTo(format(ILLEGAL_RELATIVE_ADDITION_MESSAGE, "b")));
144+
}
145+
catch (IllegalArgumentException ex) {
146+
assertTrue(ex.getMessage().contains("cannot be added relative to itself"));
150147
}
151148
}
152149

0 commit comments

Comments
 (0)