You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by as...@apache.org on 2015/07/27 09:17:55 UTC
svn commit: r1692825 - in /sling/trunk/bundles/resourceresolver/src:
main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java
test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java
Author: asanso
Date: Mon Jul 27 07:17:54 2015
New Revision: 1692825
URL: http://svn.apache.org/r1692825
Log:
SLING-4903 - ConcurrentModificationException in MapEntries
Modified:
sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java
sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java
Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java?rev=1692825&r1=1692824&r2=1692825&view=diff
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java (original)
+++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java Mon Jul 27 07:17:54 2015
@@ -1020,17 +1020,25 @@ public class MapEntries implements Event
* Add an entry to the resolve map.
*/
private boolean addEntry(final Map<String, List<MapEntry>> entryMap, final String key, final MapEntry entry) {
+
if (entry==null){
return false;
}
+
List<MapEntry> entries = entryMap.get(key);
if (entries == null) {
entries = new ArrayList<MapEntry>();
+ entries.add(entry);
+ // and finally sort list
+ Collections.sort(entries);
entryMap.put(key, entries);
+ } else {
+ List<MapEntry> entriesCopy =new ArrayList<MapEntry>(entries);
+ entriesCopy.add(entry);
+ // and finally sort list
+ Collections.sort( entriesCopy);
+ entryMap.put(key, entriesCopy);
}
- entries.add(entry);
- // and finally sort list
- Collections.sort(entries);
return true;
}
Modified: sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java?rev=1692825&r1=1692824&r2=1692825&view=diff
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java (original)
+++ sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java Mon Jul 27 07:17:54 2015
@@ -40,7 +40,12 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicLong;
+
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceUtil;
@@ -1801,4 +1806,66 @@ public class MapEntriesTest {
assertEquals(2, counter.longValue());
}
+ @Test
+ //SLING-4883
+ public void test_concutrrent_getResolveMapsIterator() throws Exception {
+ ExecutorService pool = Executors.newFixedThreadPool(10);
+
+ final Resource justVanityPath = mock(Resource.class, "justVanityPath");
+ when(resourceResolver.getResource("/justVanityPath")).thenReturn(justVanityPath);
+ when(justVanityPath.getPath()).thenReturn("/justVanityPath");
+ when(justVanityPath.getName()).thenReturn("justVanityPath");
+ when(justVanityPath.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath"));
+
+
+ when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() {
+
+ public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable {
+ if (invocation.getArguments()[0].toString().contains("sling:vanityPath")) {
+ return Collections.singleton(justVanityPath).iterator();
+ } else {
+ return Collections.<Resource> emptySet().iterator();
+ }
+ }
+ });
+
+
+ Field field1 = MapEntries.class.getDeclaredField("maxCachedVanityPathEntries");
+ field1.setAccessible(true);
+ field1.set(mapEntries, 2);
+
+ ArrayList<DataFuture> list = new ArrayList<DataFuture>();
+ for (int i =0;i<10;i++) {
+ list.add(createDataFuture(pool, mapEntries));
+
+ }
+
+ for (DataFuture df : list) {
+ df.future.get();
+ }
+
+ }
+
+ // -------------------------- private methods ----------
+ private DataFuture createDataFuture(ExecutorService pool, final MapEntries mapEntries) {
+
+ Future<Iterator> future = pool.submit(new Callable<Iterator>() {
+ @Override
+ public Iterator call() throws Exception {
+ return mapEntries.getResolveMapsIterator("http/localhost.8080/target/justVanityPath");
+ }
+ });
+ return new DataFuture(future);
+ }
+
+ // -------------------------- inner classes ------------
+
+ private static class DataFuture {
+ public Future<Iterator> future;
+
+ public DataFuture(Future<Iterator> future) {
+ super();
+ this.future = future;
+ }
+ }
}