Skip to content

Commit c53f325

Browse files
authored
Merge pull request #251 from Dima1224/value-utils-concurrent-access-fix
Make dynamicPropertyHandlerMap in ValueUtils thread-safe
2 parents 9041cbf + 0dfbe65 commit c53f325

File tree

2 files changed

+47
-2
lines changed

2 files changed

+47
-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: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,19 @@
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.ExecutionException;
30+
import java.util.concurrent.ExecutorService;
31+
import java.util.concurrent.Executors;
32+
import java.util.concurrent.Future;
33+
import java.util.concurrent.TimeUnit;
2734

35+
import org.apache.commons.jxpath.DynamicPropertyHandler;
2836
import org.junit.jupiter.api.Test;
2937

3038
class ValueUtilsTest {
@@ -87,4 +95,41 @@ void testGetValueFromSetNegativeIndex() {
8795
void testGetValueFromSetTooSmall() {
8896
assertNull(ValueUtils.getValue(Collections.EMPTY_SET, 2));
8997
}
98+
99+
@Test
100+
void testGetDynamicPropertyHandlerConcurrently() throws InterruptedException, ExecutionException {
101+
// This test ensures that ValueUtils::getDynamicPropertyHandler can be accessed concurrently
102+
// It does not assert any specific behavior, but rather ensures that no exceptions are thrown on 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+
future.get(); // This will throw if any thread threw
115+
}
116+
}
117+
118+
public static class DummyHandler implements DynamicPropertyHandler {
119+
120+
@Override
121+
public Object getProperty(Object object, String propertyName) {
122+
return null;
123+
}
124+
125+
@Override
126+
public String[] getPropertyNames(Object object) {
127+
return new String[0];
128+
}
129+
130+
@Override
131+
public void setProperty(Object object, String propertyName, Object value) {
132+
133+
}
134+
}
90135
}

0 commit comments

Comments
 (0)