Skip to content

Commit c0237e7

Browse files
committed
Make dynamicPropertyHandlerMap in ValueUtils thread-safe
1 parent 9041cbf commit c0237e7

File tree

2 files changed

+52
-2
lines changed

2 files changed

+52
-2
lines changed

src/main/java/org/apache/commons/jxpath/util/ValueUtils.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@
2626
import java.util.ArrayList;
2727
import java.util.Collection;
2828
import java.util.Collections;
29-
import java.util.HashMap;
3029
import java.util.Iterator;
3130
import java.util.List;
3231
import java.util.Map;
32+
import java.util.concurrent.ConcurrentHashMap;
3333

3434
import org.apache.commons.jxpath.Container;
3535
import org.apache.commons.jxpath.DynamicPropertyHandler;
@@ -40,7 +40,7 @@
4040
*/
4141
public class ValueUtils {
4242

43-
private static Map<Class, DynamicPropertyHandler> dynamicPropertyHandlerMap = new HashMap<>();
43+
private static Map<Class, DynamicPropertyHandler> dynamicPropertyHandlerMap = new ConcurrentHashMap<>();
4444
private static final int UNKNOWN_LENGTH_MAX_COUNT = 16000;
4545

4646
/**

src/test/java/org/apache/commons/jxpath/util/ValueUtilsTest.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,18 @@
2020
import static org.junit.jupiter.api.Assertions.assertNull;
2121
import static org.junit.jupiter.api.Assertions.assertSame;
2222

23+
import java.util.ArrayList;
2324
import java.util.Arrays;
2425
import java.util.Collections;
2526
import java.util.HashSet;
27+
import java.util.List;
2628
import java.util.Set;
29+
import java.util.concurrent.ExecutorService;
30+
import java.util.concurrent.Executors;
31+
import java.util.concurrent.Future;
32+
import java.util.concurrent.TimeUnit;
2733

34+
import org.apache.commons.jxpath.DynamicPropertyHandler;
2835
import org.junit.jupiter.api.Test;
2936

3037
class ValueUtilsTest {
@@ -87,4 +94,47 @@ void testGetValueFromSetNegativeIndex() {
8794
void testGetValueFromSetTooSmall() {
8895
assertNull(ValueUtils.getValue(Collections.EMPTY_SET, 2));
8996
}
97+
98+
@Test
99+
void testGetDynamicPropertyHandlerConcurrently() throws InterruptedException {
100+
// This test is to ensure that the dynamic property handler can be accessed concurrently
101+
// without throwing any exceptions. It does not assert any specific behavior, but rather
102+
// ensures that no exceptions are thrown during concurrent access.
103+
int nThreads = 200; // Number of threads to simulate concurrent access
104+
List<Future<?>> futures = new ArrayList<>();
105+
ExecutorService threadPool = Executors.newFixedThreadPool(nThreads);
106+
for (int i = 0; i < nThreads; i++) {
107+
futures.add(threadPool.submit(() -> ValueUtils.getDynamicPropertyHandler(DummyHandler.class)));
108+
}
109+
110+
threadPool.shutdown();
111+
threadPool.awaitTermination(1, TimeUnit.SECONDS);
112+
113+
for (Future<?> future : futures) {
114+
try {
115+
future.get(); // This will throw an exception if any thread encountered an issue
116+
} catch (Exception e) {
117+
// If an exception is thrown, the test fails
118+
throw new AssertionError("Exception thrown during concurrent access", e);
119+
}
120+
}
121+
}
122+
123+
public static class DummyHandler implements DynamicPropertyHandler {
124+
125+
@Override
126+
public Object getProperty(Object object, String propertyName) {
127+
return null;
128+
}
129+
130+
@Override
131+
public String[] getPropertyNames(Object object) {
132+
return new String[0];
133+
}
134+
135+
@Override
136+
public void setProperty(Object object, String propertyName, Object value) {
137+
138+
}
139+
}
90140
}

0 commit comments

Comments
 (0)