This is an automated email from the ASF dual-hosted git repository.

kwin pushed a commit to branch master
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-resourceresolver.git


The following commit(s) were added to refs/heads/master by this push:
     new a19995d  SLING-12160 Prevent ConcurrentModificationException in 
readAliasesOptimized(...) (#107)
a19995d is described below

commit a19995d2ec700f1b444adc52c783cdbceae5a7ce
Author: Konrad Windszus <k...@apache.org>
AuthorDate: Mon Nov 27 09:00:50 2023 +0100

    SLING-12160 Prevent ConcurrentModificationException in 
readAliasesOptimized(...) (#107)
    
    Refactor to use nested ConcurrentHashMap with Collection<String> for alias 
map
---
 .../impl/ResourceResolverImpl.java                 |  25 ++-
 .../resourceresolver/impl/mapping/MapEntries.java  |  85 ++++----
 .../impl/mapping/MapEntriesHandler.java            |   8 +-
 .../impl/mapping/PathGenerator.java                |   3 +-
 .../impl/mapping/ResourceMapperImpl.java           |  18 +-
 .../mapping/AbstractMappingMapEntriesTest.java     |   2 +-
 .../impl/mapping/MapEntriesTest.java               | 240 ++++++++++-----------
 7 files changed, 176 insertions(+), 205 deletions(-)

diff --git 
a/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverImpl.java
 
b/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverImpl.java
index 0a528d2..7b32c4d 100644
--- 
a/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverImpl.java
+++ 
b/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverImpl.java
@@ -30,6 +30,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Set;
 import java.util.StringTokenizer;
 import java.util.concurrent.ConcurrentHashMap;
@@ -839,20 +840,18 @@ public class ResourceResolverImpl extends SlingAdaptable 
implements ResourceReso
         if (factory.getMapEntries().isOptimizeAliasResolutionEnabled()){
             logger.debug("getChildInternal: Optimize Alias Resolution is 
Enabled");
             //optimization made in SLING-2521
-            final Map<String, String> aliases = 
factory.getMapEntries().getAliasMap(parent.getPath());
-            if (aliases != null) {
-                final String aliasName = aliases.get(childName);
-                if (aliasName != null ) {
-                    final String aliasPath;
-                    if ( aliasName.startsWith("/") ) {
-                        aliasPath = aliasName;
-                    } else {
-                        aliasPath = parent.getPath() + '/' + aliasName;
-                    }
-                    final Resource aliasedChild = 
getAbsoluteResourceInternal(parent, ResourceUtil.normalize(aliasPath), 
EMPTY_PARAMETERS, true );
-                    logger.debug("getChildInternal: Found Resource {} with 
alias {} to use", aliasedChild, childName);
-                    return aliasedChild;
+            final Optional<String> aliasedResourceName = 
factory.getMapEntries().getAliasMap(parent.getPath()).entrySet()
+                    .stream().filter(e -> 
e.getValue().contains(childName)).findFirst().map(Map.Entry::getKey);
+            if (aliasedResourceName.isPresent()) {
+                final String aliasPath;
+                if ( aliasedResourceName.get().startsWith("/") ) {
+                    aliasPath = aliasedResourceName.get();
+                } else {
+                    aliasPath = parent.getPath() + '/' + 
aliasedResourceName.get();
                 }
+                final Resource aliasedChild = 
getAbsoluteResourceInternal(parent, ResourceUtil.normalize(aliasPath), 
EMPTY_PARAMETERS, true );
+                logger.debug("getChildInternal: Found Resource {} with alias 
{} to use", aliasedChild, childName);
+                return aliasedChild;
             }
         } else {
             if ( this.factory.isOptimizeAliasResolutionEnabled() ) {
diff --git 
a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java 
b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java
index 84b64fd..1c89504 100644
--- 
a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java
+++ 
b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java
@@ -34,6 +34,7 @@ import org.apache.sling.api.resource.path.Path;
 import org.apache.sling.resourceresolver.impl.ResourceResolverImpl;
 import org.apache.sling.resourceresolver.impl.ResourceResolverMetrics;
 import 
org.apache.sling.resourceresolver.impl.mapping.MapConfigurationProvider.VanityPathConfig;
+import org.jetbrains.annotations.NotNull;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceRegistration;
@@ -56,7 +57,6 @@ import java.util.Dictionary;
 import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.Iterator;
-import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -68,6 +68,7 @@ import java.util.SortedMap;
 import java.util.TreeMap;
 import java.util.TreeSet;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
@@ -140,7 +141,10 @@ public class MapEntries implements
 
     private Map <String,List <String>> vanityTargets;
 
-    private Map<String, Map<String, String>> aliasMap;
+    /**
+     * The key of the map is the parent path, while the value is a map with 
the the resource name as key and the actual aliases as values)
+     */
+    private Map<String, Map<String, Collection<String>>> aliasMapsMap;
 
     private final AtomicLong aliasResourcesOnStartup;
 
@@ -159,7 +163,6 @@ public class MapEntries implements
     private final StringInterpolationProvider stringInterpolationProvider;
 
     private final boolean useOptimizeAliasResolution;
-
     public MapEntries(final MapConfigurationProvider factory, 
             final BundleContext bundleContext, 
             final EventAdmin eventAdmin, 
@@ -174,7 +177,7 @@ public class MapEntries implements
         this.resolveMapsMap = Collections.singletonMap(GLOBAL_LIST_KEY, 
Collections.emptyList());
         this.mapMaps = Collections.<MapEntry> emptyList();
         this.vanityTargets = Collections.<String,List <String>>emptyMap();
-        this.aliasMap = Collections.<String, Map<String, String>>emptyMap();
+        this.aliasMapsMap = new ConcurrentHashMap<>();
         this.stringInterpolationProvider = stringInterpolationProvider;
 
         this.aliasResourcesOnStartup = new AtomicLong(0);
@@ -197,7 +200,7 @@ public class MapEntries implements
             
this.metrics.get().setNumberOfVanityPathLookupsSupplier(vanityPathLookups::get);
             
this.metrics.get().setNumberOfVanityPathBloomNegativeSupplier(vanityPathBloomNegative::get);
             
this.metrics.get().setNumberOfVanityPathBloomFalsePositiveSupplier(vanityPathBloomFalsePositive::get);
-            
this.metrics.get().setNumberOfResourcesWithAliasedChildrenSupplier(() -> (long) 
aliasMap.size());
+            
this.metrics.get().setNumberOfResourcesWithAliasedChildrenSupplier(() -> (long) 
aliasMapsMap.size());
             
this.metrics.get().setNumberOfResourcesWithAliasesOnStartupSupplier(aliasResourcesOnStartup::get);
         }
     }
@@ -237,8 +240,8 @@ public class MapEntries implements
             //optimization made in SLING-2521
             if (isOptimizeAliasResolutionEnabled) {
                 try {
-                    final Map<String, Map<String, String>> loadedMap = 
this.loadAliases(resolver);
-                    this.aliasMap = loadedMap;
+                    final Map<String, Map<String, Collection<String>>> 
loadedMap = this.loadAliases(resolver);
+                    this.aliasMapsMap = loadedMap;
     
                 } catch (final Exception e) {
 
@@ -430,7 +433,7 @@ public class MapEntries implements
         }
         if (this.useOptimizeAliasResolution) {
             final String pathPrefix = path + "/";
-            for (final String contentPath : this.aliasMap.keySet()) {
+            for (final String contentPath : this.aliasMapsMap.keySet()) {
                 if (path.startsWith(contentPath + "/") || 
path.equals(contentPath)
                         || contentPath.startsWith(pathPrefix)) {
                     changed |= removeAlias(contentPath, path, 
resolverRefreshed);
@@ -451,7 +454,7 @@ public class MapEntries implements
         // a direct child of vanity path but not jcr:content, or a jcr:content 
child of a direct child
         // otherwise we can discard the event
         boolean handle = true;
-        String resourcePath = null;
+        final String resourcePath;
         if ( path != null  && path.length() > contentPath.length()) {
             final String subPath = path.substring(contentPath.length() + 1);
             final int firstSlash = subPath.indexOf('/');
@@ -467,6 +470,7 @@ public class MapEntries implements
                 resourcePath = ResourceUtil.getParent(path);
             } else {
                 handle = false;
+                resourcePath = null;
             }
         }
         else {
@@ -478,20 +482,13 @@ public class MapEntries implements
 
         this.initializing.lock();
         try {
-            final Map<String, String> aliasMapEntry = 
aliasMap.get(contentPath);
+            final Map<String, Collection<String>> aliasMapEntry = 
aliasMapsMap.get(contentPath);
             if (aliasMapEntry != null) {
                 this.refreshResolverIfNecessary(resolverRefreshed);
 
-                for (Iterator<Map.Entry<String, String>> iterator = 
aliasMapEntry.entrySet().iterator(); iterator.hasNext(); ) {
-                    final Map.Entry<String, String> entry = iterator.next();
-                    String prefix = contentPath.endsWith("/") ? contentPath : 
contentPath + "/";
-                    if ((prefix + entry.getValue()).startsWith(resourcePath)){
-                        iterator.remove();
-                    }
-                }
-
-                if (aliasMapEntry.isEmpty()) {
-                    this.aliasMap.remove(contentPath);
+                String prefix = contentPath.endsWith("/") ? contentPath : 
contentPath + "/";
+                if (aliasMapEntry.entrySet().removeIf(e -> (prefix + 
e.getKey()).startsWith(resourcePath)) &&  (aliasMapEntry.isEmpty())) {
+                    this.aliasMapsMap.remove(contentPath);
                 }
 
                 Resource containingResource = this.resolver != null ? 
this.resolver.getResource(resourcePath) : null;
@@ -575,7 +572,7 @@ public class MapEntries implements
     }
 
     private boolean doAddAlias(final Resource resource) {
-        return loadAlias(resource, this.aliasMap);
+        return loadAlias(resource, this.aliasMapsMap);
     }
 
     /**
@@ -595,20 +592,14 @@ public class MapEntries implements
             final String containingResourceName = containingResource.getName();
             final String parentPath = 
ResourceUtil.getParent(containingResource.getPath());
 
-            final Map<String, String> aliasMapEntry = parentPath == null ? 
null : aliasMap.get(parentPath);
+            final Map<String, Collection<String>> aliasMapEntry = parentPath 
== null ? null : aliasMapsMap.get(parentPath);
             if (aliasMapEntry != null) {
-                for (Iterator<Map.Entry<String, String>> iterator = 
aliasMapEntry.entrySet().iterator(); iterator.hasNext(); ) {
-                    final Map.Entry<String, String> entry = iterator.next();
-                    if (containingResourceName.equals(entry.getValue())){
-                        iterator.remove();
-                    }
+                aliasMapEntry.remove(containingResourceName);
+                if (aliasMapEntry.isEmpty()) {
+                    this.aliasMapsMap.remove(parentPath);
                 }
             }
 
-            if (aliasMapEntry != null && aliasMapEntry.isEmpty()) {
-                this.aliasMap.remove(parentPath);
-            }
-
             boolean changed = aliasMapEntry != null;
 
             if ( 
containingResource.getValueMap().containsKey(ResourceResolverImpl.PROP_ALIAS) ) 
{
@@ -710,8 +701,9 @@ public class MapEntries implements
     }
     
     @Override
-    public Map<String, String> getAliasMap(final String parentPath) {
-        return aliasMap.get(parentPath);
+    public @NotNull Map<String, Collection<String>> getAliasMap(final String 
parentPath) {
+        Map<String, Collection<String>> aliasMapForParent = 
aliasMapsMap.get(parentPath);
+        return aliasMapForParent != null ? aliasMapForParent : 
Collections.emptyMap();
     }
 
     @Override
@@ -1156,8 +1148,8 @@ public class MapEntries implements
      * Load aliases - Search for all nodes (except under /jcr:system) below
      * configured alias locations having the sling:alias property
      */
-    private Map<String, Map<String, String>> loadAliases(final 
ResourceResolver resolver) {
-        final Map<String, Map<String, String>> map = new ConcurrentHashMap<>();
+    private Map<String, Map<String, Collection<String>>> loadAliases(final 
ResourceResolver resolver) {
+        final Map<String, Map<String, Collection<String>>> map = new 
ConcurrentHashMap<>();
         final String queryString = generateAliasQuery();
 
         log.debug("start alias query: {}", queryString);
@@ -1211,7 +1203,7 @@ public class MapEntries implements
     /**
      * Load alias given a resource
      */
-    private boolean loadAlias(final Resource resource, Map<String, Map<String, 
String>> map) {
+    private boolean loadAlias(final Resource resource, Map<String, Map<String, 
Collection<String>>> map) {
 
         // resource containing the alias
         final Resource containingResource;
@@ -1243,24 +1235,23 @@ public class MapEntries implements
 
             if (aliasArray != null) {
                 log.debug("Found alias, total size {}", aliasArray.length);
+                // the order matters here, the first alias in the array must 
come first
                 for (final String alias : aliasArray) {
                     if (isAliasValid(alias)) {
                         log.warn("Encountered invalid alias {} under parent 
path {}. Refusing to use it.", alias, parentPath);
                     } else {
-                        Map<String, String> parentMap = map.get(parentPath);
-
-                        if (parentMap == null) {
-                            parentMap = new LinkedHashMap<>();
-                            map.put(parentPath, parentMap);
-                        }
-
-                        String current = parentMap.get(alias);
-                        if (current != null) {
+                        Map<String, Collection<String>> parentMap = 
map.computeIfAbsent(parentPath, key -> new ConcurrentHashMap<>());
+                        Optional<String> siblingResourceNameWithDuplicateAlias 
= parentMap.entrySet().stream()
+                                .filter(entry -> 
!entry.getKey().equals(resourceName)) // ignore entry for the current resource
+                                .filter(entry -> 
entry.getValue().contains(alias))
+                                .findFirst().map(Map.Entry::getKey);
+                        if (siblingResourceNameWithDuplicateAlias.isPresent()) 
{
                             log.warn(
                                     "Encountered duplicate alias {} under 
parent path {}. Refusing to replace current target {} with {}.",
-                                    alias, parentPath, current, resourceName);
+                                    alias, parentPath, 
siblingResourceNameWithDuplicateAlias.get(), resourceName);
                         } else {
-                            parentMap.put(alias, resourceName);
+                            Collection<String> existingAliases = 
parentMap.computeIfAbsent(resourceName, name -> new CopyOnWriteArrayList<>());
+                            existingAliases.add(alias);
                             hasAlias = true;
                         }
                     }
diff --git 
a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesHandler.java
 
b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesHandler.java
index a32a457..78e3024 100644
--- 
a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesHandler.java
+++ 
b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesHandler.java
@@ -57,7 +57,7 @@ public interface MapEntriesHandler {
         }
 
         @Override
-        public Map<String, String> getAliasMap(String parentPath) {
+        public Map<String, Collection<String>> getAliasMap(String parentPath) {
             return Collections.emptyMap();
         }
 
@@ -89,14 +89,14 @@ public interface MapEntriesHandler {
     void logDisableAliasOptimization();
 
     /**
-     * Returns all alias entries that for children of the specified 
<code>parentPath</code>
+     * Returns all alias entries for children of the specified 
<code>parentPath</code>
      *
-     * <p>The returned map has resource names as keys and aliases as 
values.</p>
+     * <p>The returned map has resource names as keys and the assigned aliases 
as values.</p>
      *
      * @param parentPath the parent path
      * @return a map of all child alias entries, possibly empty
      */
-    @NotNull Map<String, String> getAliasMap(@NotNull String parentPath);
+    @NotNull Map<String, Collection<String>> getAliasMap(@NotNull String 
parentPath);
 
     /**
      * Creates an iterator over the possibly applicable mapping entries for 
resolving a resource
diff --git 
a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/PathGenerator.java
 
b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/PathGenerator.java
index 0d61e1a..a3bcd3d 100644
--- 
a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/PathGenerator.java
+++ 
b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/PathGenerator.java
@@ -19,6 +19,7 @@
 package org.apache.sling.resourceresolver.impl.mapping;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -74,7 +75,7 @@ public class PathGenerator {
      * @param alias the list of aliases
      * @param name the name
      */
-    public void insertSegment(@NotNull List<String> alias, @NotNull String 
name) {
+    public void insertSegment(@NotNull Collection<String> alias, @NotNull 
String name) {
         
         List<String> filtered = Stream.concat(alias.stream(), Stream.of(name) )
             .filter( e -> e != null && ! e.isEmpty() )
diff --git 
a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/ResourceMapperImpl.java
 
b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/ResourceMapperImpl.java
index f1e3dcb..4a1da82 100644
--- 
a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/ResourceMapperImpl.java
+++ 
b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/ResourceMapperImpl.java
@@ -24,10 +24,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.LinkedHashSet;
 import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
 import java.util.function.UnaryOperator;
-import java.util.stream.Collectors;
 
 import javax.servlet.http.HttpServletRequest;
 
@@ -223,7 +220,7 @@ public class ResourceMapperImpl implements ResourceMapper {
         if (this.mapEntries.isOptimizeAliasResolutionEnabled()) {
                // this code path avoids any creation of Sling Resource objects
                while (path != null) {
-                   List<String> aliases = Collections.emptyList();
+                   Collection<String> aliases = Collections.emptyList();
                    // read alias only if we can read the resources and it's 
not a jcr:content leaf
                    if (!path.endsWith(ResourceResolverImpl.JCR_CONTENT_LEAF)) {
                        aliases = readAliasesOptimized(path);
@@ -278,7 +275,7 @@ public class ResourceMapperImpl implements ResourceMapper {
      * @param path
      * @return
      */
-    private List<String> readAliasesOptimized(String path) {
+    private Collection<String> readAliasesOptimized(String path) {
        logger.debug("map: Optimize Alias Resolution is Enabled");
        String parentPath = ResourceUtil.getParent(path);
        if ( parentPath == null ) {
@@ -286,16 +283,7 @@ public class ResourceMapperImpl implements ResourceMapper {
        }
        String name = ResourceUtil.getName(path);
 
-       final Map<String, String> aliases = mapEntries.getAliasMap(parentPath);
-
-       if ( aliases == null || !aliases.containsValue(name) ) 
-               return Collections.emptyList();
-
-       return aliases.entrySet().stream()
-                       .filter( e -> name.contentEquals(e.getValue()) )
-                       .map( Entry::getKey )
-                       .collect(Collectors.toList());
-
+       return mapEntries.getAliasMap(parentPath).getOrDefault(name, 
Collections.emptyList());
     }
 
     private void populateMappingsFromMapEntries(List<String> mappings, 
List<String> mappedPathList,
diff --git 
a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/AbstractMappingMapEntriesTest.java
 
b/src/test/java/org/apache/sling/resourceresolver/impl/mapping/AbstractMappingMapEntriesTest.java
index fd66d0e..ce65917 100644
--- 
a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/AbstractMappingMapEntriesTest.java
+++ 
b/src/test/java/org/apache/sling/resourceresolver/impl/mapping/AbstractMappingMapEntriesTest.java
@@ -120,7 +120,7 @@ public abstract class AbstractMappingMapEntriesTest {
         setupStringInterpolationProvider(stringInterpolationProvider, 
stringInterpolationProviderConfiguration, new String[] {});
         mapEntries = new MapEntries(resourceResolverFactory, bundleContext, 
eventAdmin, stringInterpolationProvider, metrics);
 
-        final Field aliasMapField = 
MapEntries.class.getDeclaredField("aliasMap");
+        final Field aliasMapField = 
MapEntries.class.getDeclaredField("aliasMapsMap");
         aliasMapField.setAccessible(true);
         this.aliasMap = ( Map<String, Map<String, String>>) 
aliasMapField.get(mapEntries);
     }
diff --git 
a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java
 
b/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java
index fc8ec76..f5d842a 100644
--- 
a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java
+++ 
b/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java
@@ -161,8 +161,8 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         Optional<ResourceResolverMetrics> metrics = Optional.empty();
 
-        mapEntries = Mockito.spy(new MapEntries(resourceResolverFactory, 
bundleContext, eventAdmin, stringInterpolationProvider, metrics));
-        final Field aliasMapField = 
MapEntries.class.getDeclaredField("aliasMap");
+        mapEntries = new MapEntries(resourceResolverFactory, bundleContext, 
eventAdmin, stringInterpolationProvider, metrics);
+        final Field aliasMapField = 
MapEntries.class.getDeclaredField("aliasMapsMap");
         aliasMapField.setAccessible(true);
 
         this.aliasMap = ( Map<String, Map<String, String>>) 
aliasMapField.get(mapEntries);
@@ -201,10 +201,10 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         mapEntries.doInit();
 
-        Map<String, String> aliasMap = mapEntries.getAliasMap("/parent");
+        Map<String, Collection<String>> aliasMap = 
mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMap);
-        assertTrue(aliasMap.containsKey("alias"));
-        assertEquals("child", aliasMap.get("alias"));
+        assertTrue(aliasMap.containsKey("child"));
+        assertEquals(Collections.singletonList("alias"), 
aliasMap.get("child"));
     }
 
     @Test
@@ -238,10 +238,10 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         mapEntries.doInit();
 
-        Map<String, String> aliasMap = mapEntries.getAliasMap("/parent");
+        Map<String, Collection<String>> aliasMap = 
mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMap);
-        assertTrue(aliasMap.containsKey("alias"));
-        assertEquals("child", aliasMap.get("alias"));
+        assertTrue(aliasMap.containsKey("child"));
+        assertEquals(Collections.singletonList("alias"), 
aliasMap.get("child"));
     }
 
     @Test
@@ -936,8 +936,8 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         addResource.invoke(mapEntries, "/parent/child", new AtomicBoolean());
 
-        Map<String, String> aliasMap = mapEntries.getAliasMap("/parent");
-        assertNull(aliasMap);
+        Map<String, Collection<String>> aliasMap = 
mapEntries.getAliasMap("/parent");
+        assertNotNull(aliasMap);
     }
 
     //SLING-3727
@@ -961,8 +961,8 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         addResource.invoke(mapEntries, "/parent/child", new AtomicBoolean());
 
-        Map<String, String> aliasMap = mapEntries.getAliasMap("/parent");
-        assertNull(aliasMap);
+        Map<String, Collection<String>> aliasMap = 
mapEntries.getAliasMap("/parent");
+        assertEquals(Collections.emptyMap(), aliasMap);
     }
 
     //SLING-3727
@@ -986,8 +986,8 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         removeAlias.invoke(mapEntries, "/parent", "/parent/child", new 
AtomicBoolean());
 
-        Map<String, String> aliasMap = mapEntries.getAliasMap("/parent");
-        assertNull(aliasMap);
+        Map<String, Collection<String>> aliasMap = 
mapEntries.getAliasMap("/parent");
+        assertEquals(Collections.emptyMap(), aliasMap);
     }
 
     @Test
@@ -1009,10 +1009,10 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         addResource.invoke(mapEntries, "/parent/child", new AtomicBoolean());
 
-        Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/parent");
+        Map<String, Collection<String>> aliasMapEntry = 
mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMapEntry);
-        assertTrue(aliasMapEntry.containsKey("alias"));
-        assertEquals("child", aliasMapEntry.get("alias"));
+        assertTrue(aliasMapEntry.containsKey("child"));
+        assertEquals(Collections.singletonList("alias"), 
aliasMapEntry.get("child"));
 
         assertEquals(1, aliasMap.size());
 
@@ -1028,8 +1028,8 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         aliasMapEntry = mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMapEntry);
-        assertTrue(aliasMapEntry.containsKey("alias"));
-        assertEquals("child", aliasMapEntry.get("alias"));
+        assertTrue(aliasMapEntry.containsKey("child"));
+        assertEquals(Collections.singletonList("alias"), 
aliasMapEntry.get("child"));
 
         assertEquals(1, aliasMap.size());
 
@@ -1045,9 +1045,9 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         aliasMapEntry = mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMapEntry);
-        assertEquals(2, aliasMapEntry.size());
-        assertTrue(aliasMapEntry.containsKey("aliasJcrContent"));
-        assertEquals("child", aliasMapEntry.get("aliasJcrContent"));
+        assertEquals(1, aliasMapEntry.size()); // only 2 aliases for 1 child 
resource
+        assertTrue(aliasMapEntry.containsKey("child"));
+        assertEquals(List.of("alias","aliasJcrContent"), 
aliasMapEntry.get("child"));
 
         assertEquals(1, aliasMap.size());
     }
@@ -1071,10 +1071,10 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         addResource.invoke(mapEntries, "/parent", new AtomicBoolean());
 
-        Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/");
+        Map<String, Collection<String>> aliasMapEntry = 
mapEntries.getAliasMap("/");
         assertNotNull(aliasMapEntry);
-        assertTrue(aliasMapEntry.containsKey("alias"));
-        assertEquals("parent", aliasMapEntry.get("alias"));
+        assertTrue(aliasMapEntry.containsKey("parent"));
+        assertEquals(Collections.singletonList("alias"), 
aliasMapEntry.get("parent"));
 
         assertEquals(1, aliasMap.size());
 
@@ -1090,8 +1090,8 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         aliasMapEntry = mapEntries.getAliasMap("/");
         assertNotNull(aliasMapEntry);
-        assertTrue(aliasMapEntry.containsKey("alias"));
-        assertEquals("parent", aliasMapEntry.get("alias"));
+        assertTrue(aliasMapEntry.containsKey("parent"));
+        assertEquals(Collections.singletonList("alias"), 
aliasMapEntry.get("parent"));
 
         assertEquals(1, aliasMap.size());
 
@@ -1107,9 +1107,9 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         aliasMapEntry = mapEntries.getAliasMap("/");
         assertNotNull(aliasMapEntry);
-        assertEquals(2, aliasMapEntry.size());
-        assertTrue(aliasMapEntry.containsKey("aliasJcrContent"));
-        assertEquals("parent", aliasMapEntry.get("aliasJcrContent"));
+        assertEquals(1, aliasMapEntry.size());
+        assertTrue(aliasMapEntry.containsKey("parent"));
+        assertEquals(List.of("alias","aliasJcrContent"), 
aliasMapEntry.get("parent"));
 
         assertEquals(1, aliasMap.size());
 
@@ -1125,8 +1125,8 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         aliasMapEntry = mapEntries.getAliasMap("/");
         assertNotNull(aliasMapEntry);
-        assertTrue(aliasMapEntry.containsKey("alias"));
-        assertEquals("parent", aliasMapEntry.get("alias"));
+        assertTrue(aliasMapEntry.containsKey("parent"));
+        assertEquals(List.of("alias", "aliasJcrContent"), 
aliasMapEntry.get("parent"));
         assertEquals(1, aliasMap.size());
 
     }
@@ -1150,11 +1150,10 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         updateResource.invoke(mapEntries, "/parent/child", new 
AtomicBoolean());
 
-        Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/parent");
+        Map<String, Collection<String>> aliasMapEntry = 
mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMapEntry);
-        assertTrue(aliasMapEntry.containsKey("alias"));
-        assertFalse(aliasMapEntry.containsKey("aliasUpdated"));
-        assertEquals("child", aliasMapEntry.get("alias"));
+        assertTrue(aliasMapEntry.containsKey("child"));
+        assertEquals(List.of("alias"), aliasMapEntry.get("child"));
 
         assertEquals(1, aliasMap.size());
 
@@ -1164,9 +1163,8 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         aliasMapEntry = mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMapEntry);
-        assertFalse(aliasMapEntry.containsKey("alias"));
-        assertTrue(aliasMapEntry.containsKey("aliasUpdated"));
-        assertEquals("child", aliasMapEntry.get("aliasUpdated"));
+        assertTrue(aliasMapEntry.containsKey("child"));
+        assertEquals(List.of("aliasUpdated"), aliasMapEntry.get("child"));
 
         assertEquals(1, aliasMap.size());
 
@@ -1183,10 +1181,9 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         aliasMapEntry = mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMapEntry);
-        assertEquals(2, aliasMapEntry.size());
-        assertTrue(aliasMapEntry.containsKey("aliasJcrContent"));
-        assertFalse(aliasMapEntry.containsKey("aliasJcrContentUpdated"));
-        assertEquals("child", aliasMapEntry.get("aliasJcrContent"));
+        assertEquals(1, aliasMapEntry.size());
+        assertTrue(aliasMapEntry.containsKey("child"));
+        assertEquals(List.of("aliasUpdated","aliasJcrContent"), 
aliasMapEntry.get("child"));
 
         assertEquals(1, aliasMap.size());
 
@@ -1195,10 +1192,9 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         aliasMapEntry = mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMapEntry);
-        assertEquals(2, aliasMapEntry.size());
-        assertFalse(aliasMapEntry.containsKey("aliasJcrContent"));
-        assertTrue(aliasMapEntry.containsKey("aliasJcrContentUpdated"));
-        assertEquals("child", aliasMapEntry.get("aliasJcrContentUpdated"));
+        assertEquals(1, aliasMapEntry.size());
+        assertTrue(aliasMapEntry.containsKey("child"));
+        assertEquals(List.of("aliasUpdated", "aliasJcrContentUpdated"), 
aliasMapEntry.get("child"));
 
         assertEquals(1, aliasMap.size());
 
@@ -1207,10 +1203,9 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         aliasMapEntry = mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMapEntry);
-        assertEquals(2, aliasMapEntry.size());
-        assertFalse(aliasMapEntry.containsKey("alias"));
-        assertTrue(aliasMapEntry.containsKey("aliasUpdated"));
-        assertEquals("child", aliasMapEntry.get("aliasUpdated"));
+        assertEquals(1, aliasMapEntry.size());
+        assertTrue(aliasMapEntry.containsKey("child"));
+        assertEquals(List.of("aliasUpdated","aliasJcrContentUpdated"), 
aliasMapEntry.get("child"));
 
         //add another node with different alias and check that the update 
doesn't break anything (see also SLING-3728)
         final Resource secondResult = mock(Resource.class);
@@ -1225,17 +1220,16 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         aliasMapEntry = mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMapEntry);
-        assertEquals(3, aliasMapEntry.size());
+        assertEquals(2, aliasMapEntry.size());
 
         
when(jcrContentResult.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS,
 "aliasJcrContentUpdated"));
         updateResource.invoke(mapEntries, "/parent/child/jcr:content", new 
AtomicBoolean());
 
         aliasMapEntry = mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMapEntry);
-        assertEquals(3, aliasMapEntry.size());
-        assertFalse(aliasMapEntry.containsKey("aliasJcrContent"));
-        assertTrue(aliasMapEntry.containsKey("aliasJcrContentUpdated"));
-        assertEquals("child", aliasMapEntry.get("aliasJcrContentUpdated"));
+        assertEquals(2, aliasMapEntry.size());
+        assertTrue(aliasMapEntry.containsKey("child"));
+        assertEquals(List.of("aliasUpdated","aliasJcrContentUpdated"), 
aliasMapEntry.get("child"));
 
         assertEquals(1, aliasMap.size());
 
@@ -1247,9 +1241,8 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
         aliasMapEntry = mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMapEntry);
         assertEquals(2, aliasMapEntry.size());
-        assertFalse(aliasMapEntry.containsKey("aliasJcrContent"));
-        assertTrue(aliasMapEntry.containsKey("aliasJcrContentUpdated"));
-        assertEquals("child", aliasMapEntry.get("aliasJcrContentUpdated"));
+        assertTrue(aliasMapEntry.containsKey("child"));
+        assertEquals(List.of("aliasJcrContentUpdated"), 
aliasMapEntry.get("child"));
 
         assertEquals(1, aliasMap.size());
 
@@ -1278,10 +1271,10 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         addResource.invoke(mapEntries, "/parent/child", new AtomicBoolean());
 
-        Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/parent");
+        Map<String, Collection<String>> aliasMapEntry = 
mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMapEntry);
-        assertTrue(aliasMapEntry.containsKey("alias"));
-        assertEquals("child", aliasMapEntry.get("alias"));
+        assertTrue(aliasMapEntry.containsKey("child"));
+        assertEquals(List.of("alias"), aliasMapEntry.get("child"));
 
         assertEquals(1, aliasMap.size());
 
@@ -1289,7 +1282,7 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
         removeAlias.invoke(mapEntries, "/parent", "/parent/child", new 
AtomicBoolean());
 
         aliasMapEntry = mapEntries.getAliasMap("/parent");
-        assertNull(aliasMapEntry);
+        assertEquals(Collections.emptyMap(), aliasMapEntry);
 
         assertEquals(0, aliasMap.size());
 
@@ -1299,8 +1292,8 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         aliasMapEntry = mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMapEntry);
-        assertTrue(aliasMapEntry.containsKey("alias"));
-        assertEquals("child", aliasMapEntry.get("alias"));
+        assertTrue(aliasMapEntry.containsKey("child"));
+        assertEquals(List.of("alias"), aliasMapEntry.get("child"));
 
         assertEquals(1, aliasMap.size());
 
@@ -1308,7 +1301,7 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
         removeAlias.invoke(mapEntries, "/parent", "/parent/child", new 
AtomicBoolean());
 
         aliasMapEntry = mapEntries.getAliasMap("/parent");
-        assertNull(aliasMapEntry);
+        assertEquals(Collections.emptyMap(), aliasMapEntry);
 
         assertEquals(0, aliasMap.size());
     }
@@ -1344,10 +1337,10 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         addResource.invoke(mapEntries, "/parent/child/jcr:content", new 
AtomicBoolean());
 
-        Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/parent");
+        Map<String, Collection<String>> aliasMapEntry = 
mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMapEntry);
-        assertTrue(aliasMapEntry.containsKey("aliasJcrContent"));
-        assertEquals("child", aliasMapEntry.get("aliasJcrContent"));
+        assertTrue(aliasMapEntry.containsKey("child"));
+        assertEquals(List.of("aliasJcrContent"), aliasMapEntry.get("child"));
 
         assertEquals(1, aliasMap.size());
 
@@ -1356,7 +1349,7 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
         removeAlias.invoke(mapEntries, "/parent", "/parent/child/jcr:content", 
new AtomicBoolean());
 
         aliasMapEntry = mapEntries.getAliasMap("/parent");
-        assertNull(aliasMapEntry);
+        assertEquals(Collections.emptyMap(), aliasMapEntry);
 
         assertEquals(0, aliasMap.size());
 
@@ -1367,8 +1360,8 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         aliasMapEntry = mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMapEntry);
-        assertTrue(aliasMapEntry.containsKey("aliasJcrContent"));
-        assertEquals("child", aliasMapEntry.get("aliasJcrContent"));
+        assertTrue(aliasMapEntry.containsKey("child"));
+        assertEquals(List.of("aliasJcrContent"), aliasMapEntry.get("child"));
 
         assertEquals(1, aliasMap.size());
         
when(resourceResolver.getResource("/parent/child/jcr:content")).thenReturn(null);
@@ -1376,11 +1369,12 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
         removeAlias.invoke(mapEntries, "/parent", "/parent/child/jcr:content", 
new AtomicBoolean());
 
         aliasMapEntry = mapEntries.getAliasMap("/parent");
-        assertNull(aliasMapEntry);
+        assertEquals(Collections.emptyMap(), aliasMapEntry);
 
         assertEquals(0, aliasMap.size());
     }
 
+    
     @Test
     public void test_doRemoveAlias3() throws Exception {
         final Method addResource = 
MapEntries.class.getDeclaredMethod("addResource", String.class, 
AtomicBoolean.class);
@@ -1415,11 +1409,10 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         // test with two nodes
         assertEquals(1, aliasMap.size());
-        Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/parent");
+        Map<String, Collection<String>> aliasMapEntry = 
mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMapEntry);
-        assertEquals(2, aliasMapEntry.size());
-        assertEquals("child", aliasMapEntry.get("aliasJcrContent"));
-        assertEquals("child", aliasMapEntry.get("alias"));
+        assertEquals(1, aliasMapEntry.size());
+        assertEquals(List.of("alias", "aliasJcrContent"), 
aliasMapEntry.get("child"));
 
         // remove child jcr:content node
         
when(resourceResolver.getResource("/parent/child/jcr:content")).thenReturn(null);
@@ -1431,7 +1424,7 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
         aliasMapEntry = mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMapEntry);
         assertEquals(1, aliasMapEntry.size());
-        assertEquals("child", aliasMapEntry.get("alias"));
+        assertEquals(List.of("alias"), aliasMapEntry.get("child"));
 
         // re-add the node and test /parent/child
         
when(resourceResolver.getResource("/parent/child/jcr:content")).thenReturn(jcrContentResult);
@@ -1441,9 +1434,8 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
         // STOP
         aliasMapEntry = mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMapEntry);
-        assertEquals(2, aliasMapEntry.size());
-        assertEquals("child", aliasMapEntry.get("aliasJcrContent"));
-        assertEquals("child", aliasMapEntry.get("alias"));
+        assertEquals(1, aliasMapEntry.size());
+        assertEquals(List.of("alias", "aliasJcrContent"), 
aliasMapEntry.get("child"));
 
         when(resourceResolver.getResource("/parent/child")).thenReturn(null);
         removeAlias.invoke(mapEntries, "/parent", "/parent/child", new 
AtomicBoolean());
@@ -1454,16 +1446,16 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
         aliasMapEntry = mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMapEntry);
         assertEquals(1, aliasMapEntry.size());
-        assertEquals("child", aliasMapEntry.get("aliasJcrContent"));
+        assertEquals(List.of("aliasJcrContent"), aliasMapEntry.get("child"));
 
         // re-add the node and test node removal
         addResource.invoke(mapEntries, "/parent/child", new AtomicBoolean());
 
         aliasMapEntry = mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMapEntry);
-        assertTrue(aliasMapEntry.containsKey("aliasJcrContent"));
-        assertEquals("child", aliasMapEntry.get("aliasJcrContent"));
-        assertEquals(2, aliasMapEntry.size());
+        assertTrue(aliasMapEntry.containsKey("child"));
+        assertEquals(List.of("aliasJcrContent", "alias"), 
aliasMapEntry.get("child"));
+        assertEquals(1, aliasMapEntry.size());
 
         
when(resourceResolver.getResource("/parent/child/jcr:content")).thenReturn(null);
         when(childRsrc.getChild("jcr:content")).thenReturn(null);
@@ -1482,16 +1474,16 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         aliasMapEntry = mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMapEntry);
-        assertTrue(aliasMapEntry.containsKey("aliasJcrContent"));
-        assertEquals("child", aliasMapEntry.get("aliasJcrContent"));
-        assertEquals(2, aliasMapEntry.size());
+        assertTrue(aliasMapEntry.containsKey("child"));
+        assertEquals(List.of("alias","aliasJcrContent"), 
aliasMapEntry.get("child"));
+        assertEquals(1, aliasMapEntry.size());
 
         when(resourceResolver.getResource("/parent/child")).thenReturn( null);
         removeAlias.invoke(mapEntries, "/parent", "/parent/child", new 
AtomicBoolean());
 
         assertEquals(0, aliasMap.size());
         aliasMapEntry = mapEntries.getAliasMap("/parent");
-        assertNull(aliasMapEntry);
+        assertEquals(Collections.emptyMap(), aliasMapEntry);
     }
 
     @Test
@@ -1516,10 +1508,10 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         addResource.invoke(mapEntries, "/parent", new AtomicBoolean());
 
-        Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/");
+        Map<String, Collection<String>> aliasMapEntry = 
mapEntries.getAliasMap("/");
         assertNotNull(aliasMapEntry);
-        assertTrue(aliasMapEntry.containsKey("alias"));
-        assertEquals("parent", aliasMapEntry.get("alias"));
+        assertTrue(aliasMapEntry.containsKey("parent"));
+        assertEquals(List.of("alias"), aliasMapEntry.get("parent"));
 
         assertEquals(1, aliasMap.size());
 
@@ -1527,7 +1519,7 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
         removeAlias.invoke(mapEntries, "/", "/parent", new AtomicBoolean());
 
         aliasMapEntry = mapEntries.getAliasMap("/");
-        assertNull(aliasMapEntry);
+        assertEquals(Collections.emptyMap(), aliasMapEntry);
 
         assertEquals(0, aliasMap.size());
 
@@ -1537,8 +1529,8 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         aliasMapEntry = mapEntries.getAliasMap("/");
         assertNotNull(aliasMapEntry);
-        assertTrue(aliasMapEntry.containsKey("alias"));
-        assertEquals("parent", aliasMapEntry.get("alias"));
+        assertTrue(aliasMapEntry.containsKey("parent"));
+        assertEquals(List.of("alias"), aliasMapEntry.get("parent"));
 
         assertEquals(1, aliasMap.size());
 
@@ -1546,7 +1538,7 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
         removeAlias.invoke(mapEntries, "/", "/parent", new AtomicBoolean());
 
         aliasMapEntry = mapEntries.getAliasMap("/");
-        assertNull(aliasMapEntry);
+        assertEquals(Collections.emptyMap(), aliasMapEntry);
 
         assertEquals(0, aliasMap.size());
     }
@@ -1582,10 +1574,10 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         addResource.invoke(mapEntries, "/parent/jcr:content", new 
AtomicBoolean());
 
-        Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/");
+        Map<String, Collection<String>> aliasMapEntry = 
mapEntries.getAliasMap("/");
         assertNotNull(aliasMapEntry);
-        assertTrue(aliasMapEntry.containsKey("aliasJcrContent"));
-        assertEquals("parent", aliasMapEntry.get("aliasJcrContent"));
+        assertTrue(aliasMapEntry.containsKey("parent"));
+        assertEquals(List.of("aliasJcrContent"), aliasMapEntry.get("parent"));
 
         assertEquals(1, aliasMap.size());
 
@@ -1594,7 +1586,7 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
         removeAlias.invoke(mapEntries, "/", "/parent/jcr:content", new 
AtomicBoolean());
 
         aliasMapEntry = mapEntries.getAliasMap("/");
-        assertNull(aliasMapEntry);
+        assertEquals(Collections.emptyMap(), aliasMapEntry);
 
         assertEquals(0, aliasMap.size());
     }
@@ -1659,11 +1651,11 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         addResource.invoke(mapEntries, grandChildJcrContent.getPath(), new 
AtomicBoolean());
 
-        Map<String, String> aliasMapEntry = 
mapEntries.getAliasMap("/parent/container/childContainer");
+        Map<String, Collection<String>> aliasMapEntry = 
mapEntries.getAliasMap("/parent/container/childContainer");
         assertNotNull(aliasMapEntry);
         assertEquals(1, aliasMapEntry.size());
-        assertTrue(aliasMapEntry.containsKey("gc"));
-        assertEquals("grandChild", aliasMapEntry.get("gc"));
+        assertTrue(aliasMapEntry.containsKey("grandChild"));
+        assertEquals(List.of("gc"), aliasMapEntry.get("grandChild"));
 
 
         // delete the jcr:content present in a parent path
@@ -1674,8 +1666,8 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
         aliasMapEntry = 
mapEntries.getAliasMap("/parent/container/childContainer");
         assertNotNull(aliasMapEntry);
         assertEquals(1, aliasMapEntry.size());
-        assertTrue(aliasMapEntry.containsKey("gc"));
-        assertEquals("grandChild", aliasMapEntry.get("gc"));
+        assertTrue(aliasMapEntry.containsKey("grandChild"));
+        assertEquals(List.of("gc"), aliasMapEntry.get("grandChild"));
 
     }
 
@@ -1717,10 +1709,10 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         addResource.invoke(mapEntries, child1JcrContent.getPath(), new 
AtomicBoolean());
 
-        Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/parent");
+        Map<String, Collection<String>> aliasMapEntry = 
mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMapEntry);
-        assertTrue(aliasMapEntry.containsKey("test1"));
-        assertEquals("child1", aliasMapEntry.get("test1"));
+        assertTrue(aliasMapEntry.containsKey("child1"));
+        assertEquals(List.of("test1"), aliasMapEntry.get("child1"));
 
         assertEquals(1, aliasMap.size());
 
@@ -1745,10 +1737,10 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         aliasMapEntry = mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMapEntry);
-        assertTrue(aliasMapEntry.containsKey("test1"));
-        assertTrue(aliasMapEntry.containsKey("test2"));
-        assertEquals("child1", aliasMapEntry.get("test1"));
-        assertEquals("child2", aliasMapEntry.get("test2"));
+        assertTrue(aliasMapEntry.containsKey("child1"));
+        assertTrue(aliasMapEntry.containsKey("child2"));
+        assertEquals(List.of("test1"), aliasMapEntry.get("child1"));
+        assertEquals(List.of("test2"), aliasMapEntry.get("child2"));
 
 
         assertEquals(1, aliasMap.size());
@@ -1765,10 +1757,10 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         aliasMapEntry = mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMapEntry);
-        assertTrue(aliasMapEntry.containsKey("test1"));
-        assertTrue(aliasMapEntry.containsKey("test2"));
-        assertEquals("child1", aliasMapEntry.get("test1"));
-        assertEquals("child2", aliasMapEntry.get("test2"));
+        assertTrue(aliasMapEntry.containsKey("child1"));
+        assertTrue(aliasMapEntry.containsKey("child2"));
+        assertEquals(List.of("test1"), aliasMapEntry.get("child1"));
+        assertEquals(List.of("test2"), aliasMapEntry.get("child2"));
 
 
         assertEquals(1, aliasMap.size());
@@ -1780,8 +1772,8 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         aliasMapEntry = mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMapEntry);
-        assertTrue(aliasMapEntry.containsKey("test1"));
-        assertEquals("child1", aliasMapEntry.get("test1"));
+        assertTrue(aliasMapEntry.containsKey("child1"));
+        assertEquals(List.of("test1"), aliasMapEntry.get("child1"));
 
 
         assertEquals(1, aliasMap.size());
@@ -1792,7 +1784,7 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
         removeResource.invoke(mapEntries, child1JcrContent.getPath(), new 
AtomicBoolean());
 
         aliasMapEntry = mapEntries.getAliasMap("/parent");
-        assertNull(aliasMapEntry);
+        assertEquals(Collections.emptyMap(), aliasMapEntry);
 
         when(child1.getChild("jcr:content")).thenReturn(child1JcrContent);
         addResource.invoke(mapEntries, child1JcrContent.getPath(), new 
AtomicBoolean());
@@ -1801,10 +1793,10 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
         aliasMapEntry = mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMapEntry);
-        assertTrue(aliasMapEntry.containsKey("test1"));
-        assertTrue(aliasMapEntry.containsKey("test2"));
-        assertEquals("child1", aliasMapEntry.get("test1"));
-        assertEquals("child2", aliasMapEntry.get("test2"));
+        assertTrue(aliasMapEntry.containsKey("child1"));
+        assertTrue(aliasMapEntry.containsKey("child2"));
+        assertEquals(List.of("test1"), aliasMapEntry.get("child1"));
+        assertEquals(List.of("test2"), aliasMapEntry.get("child2"));
 
 
         assertEquals(1, aliasMap.size());
@@ -1814,7 +1806,7 @@ public class MapEntriesTest extends 
AbstractMappingMapEntriesTest {
 
 
         aliasMapEntry = mapEntries.getAliasMap("/parent");
-        assertNull(aliasMapEntry);
+        assertEquals(Collections.emptyMap(), aliasMapEntry);
     }
 
     @Test

Reply via email to