Author: pauls
Date: Mon Jul 24 14:27:32 2017
New Revision: 1802818

URL: http://svn.apache.org/viewvc?rev=1802818&view=rev
Log:
SLING-7018: Fix a bug that removed to many aliases in certain cases when a 
resource got removed.

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=1802818&r1=1802817&r2=1802818&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 24 14:27:32 2017
@@ -331,7 +331,7 @@ public class MapEntries implements
         if (this.factory.isOptimizeAliasResolutionEnabled()) {
             for (final String contentPath : this.aliasMap.keySet()) {
                 if (path.startsWith(contentPath + "/") || 
path.equals(contentPath)) {
-                    changed |= removeAlias(contentPath, null, 
resolverRefreshed);
+                    changed |= removeAlias(contentPath, path, 
resolverRefreshed);
                 } else if ( contentPath.startsWith(actualContentPathPrefix) ) {
                     changed |= removeAlias(contentPath, path, 
resolverRefreshed);
                 }
@@ -352,37 +352,59 @@ 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 addParentPath = null;
-        if ( path != null ) {
+        String resourcePath = null;
+        if ( path != null  && path.length() > contentPath.length()) {
             final String subPath = path.substring(contentPath.length() + 1);
             final int firstSlash = subPath.indexOf('/');
             if ( firstSlash == -1 ) {
                 if ( subPath.equals(JCR_CONTENT) ) {
                     handle = false;
                 }
+                resourcePath = path;
             } else if ( subPath.lastIndexOf('/') == firstSlash) {
                 if ( subPath.startsWith(JCR_CONTENT_PREFIX) || 
!subPath.endsWith(JCR_CONTENT_SUFFIX) ) {
                     handle = false;
                 }
-                addParentPath = ResourceUtil.getParent(path);
+                resourcePath = ResourceUtil.getParent(path);
             } else {
                 handle = false;
             }
         }
+        else {
+            resourcePath = contentPath;
+        }
         if ( !handle ) {
             return false;
         }
 
         this.initializing.lock();
         try {
-            final Map<String, String> aliasMapEntry = 
aliasMap.remove(contentPath);
-            if (aliasMapEntry != null && addParentPath != null ) {
+            final Map<String, String> aliasMapEntry = 
aliasMap.get(contentPath);
+            if (aliasMapEntry != null) {
                 this.refreshResolverIfNecessary(resolverRefreshed);
-                // we need to re-add
-                // from a potential parent
-                final Resource parent = 
this.resolver.getResource(addParentPath);
-                if ( parent != null && 
parent.getValueMap().containsKey(ResourceResolverImpl.PROP_ALIAS)) {
-                    doAddAlias(parent);
+
+                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);
+                }
+
+                Resource containingResource = 
this.resolver.getResource(resourcePath);
+
+                if (containingResource != null) {
+                    if 
(containingResource.getValueMap().containsKey(ResourceResolverImpl.PROP_ALIAS)) 
{
+                        doAddAlias(containingResource);
+                    }
+                    final Resource child = 
containingResource.getChild(JCR_CONTENT);
+                    if (child != null && 
child.getValueMap().containsKey(ResourceResolverImpl.PROP_ALIAS)) {
+                        doAddAlias(child);
+                    }
                 }
             }
             return aliasMapEntry != null;

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=1802818&r1=1802817&r2=1802818&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 24 14:27:32 2017
@@ -1183,6 +1183,7 @@ public class MapEntriesTest {
 
         assertEquals(1, aliasMap.size());
 
+        when(resourceResolver.getResource("/parent/child")).thenReturn(null);
         removeAlias.invoke(mapEntries, "/parent", "/parent/child", new 
AtomicBoolean());
 
         aliasMapEntry = mapEntries.getAliasMap("/parent");
@@ -1191,6 +1192,7 @@ public class MapEntriesTest {
         assertEquals(0, aliasMap.size());
 
         //re-add node and test nodeDeletion true
+        when(resourceResolver.getResource("/parent/child")).thenReturn(child);
         addResource.invoke(mapEntries, "/parent/child", new AtomicBoolean());
 
         aliasMapEntry = mapEntries.getAliasMap("/parent");
@@ -1247,6 +1249,8 @@ public class MapEntriesTest {
 
         assertEquals(1, aliasMap.size());
 
+        
when(resourceResolver.getResource("/parent/child/jcr:content")).thenReturn(null);
+        when(result.getChild("jcr:content")).thenReturn(null);
         removeAlias.invoke(mapEntries, "/parent", "/parent/child/jcr:content", 
new AtomicBoolean());
 
         aliasMapEntry = mapEntries.getAliasMap("/parent");
@@ -1255,6 +1259,8 @@ public class MapEntriesTest {
         assertEquals(0, aliasMap.size());
 
         //re-add node and test nodeDeletion true
+        
when(resourceResolver.getResource("/parent/child/jcr:content")).thenReturn(jcrContentResult);
+        when(result.getChild("jcr:content")).thenReturn(jcrContentResult);
         addResource.invoke(mapEntries, "/parent/child/jcr:content", new 
AtomicBoolean());
 
         aliasMapEntry = mapEntries.getAliasMap("/parent");
@@ -1314,6 +1320,8 @@ public class MapEntriesTest {
         assertEquals("child", aliasMapEntry.get("alias"));
 
         // remove child jcr:content node
+        
when(resourceResolver.getResource("/parent/child/jcr:content")).thenReturn(null);
+        when(childRsrc.getChild("jcr:content")).thenReturn(null);
         removeAlias.invoke(mapEntries, "/parent", "/parent/child/jcr:content", 
new AtomicBoolean());
 
         // test with one node
@@ -1324,6 +1332,8 @@ public class MapEntriesTest {
         assertEquals("child", aliasMapEntry.get("alias"));
 
         // re-add the node and test /parent/child
+        
when(resourceResolver.getResource("/parent/child/jcr:content")).thenReturn(jcrContentResult);
+        when(childRsrc.getChild("jcr:content")).thenReturn(jcrContentResult);
         addResource.invoke(mapEntries, "/parent/child/jcr:content", new 
AtomicBoolean());
 
         // STOP
@@ -1333,7 +1343,9 @@ public class MapEntriesTest {
         assertEquals("child", aliasMapEntry.get("aliasJcrContent"));
         assertEquals("child", aliasMapEntry.get("alias"));
 
+        when(resourceResolver.getResource("/parent/child")).thenReturn(null);
         removeAlias.invoke(mapEntries, "/parent", "/parent/child", new 
AtomicBoolean());
+        
when(resourceResolver.getResource("/parent/child")).thenReturn(childRsrc);
         addResource.invoke(mapEntries, "/parent/child/jcr:content", new 
AtomicBoolean());
 
         assertEquals(1, aliasMap.size());
@@ -1372,6 +1384,7 @@ public class MapEntriesTest {
         assertEquals("child", aliasMapEntry.get("aliasJcrContent"));
         assertEquals(2, aliasMapEntry.size());
 
+        when(resourceResolver.getResource("/parent/child")).thenReturn( null);
         removeAlias.invoke(mapEntries, "/parent", "/parent/child", new 
AtomicBoolean());
 
         assertEquals(0, aliasMap.size());
@@ -1408,6 +1421,7 @@ public class MapEntriesTest {
 
         assertEquals(1, aliasMap.size());
 
+        when(resourceResolver.getResource("/parent")).thenReturn(null);
         removeAlias.invoke(mapEntries, "/", "/parent", new AtomicBoolean());
 
         aliasMapEntry = mapEntries.getAliasMap("/");
@@ -1416,6 +1430,7 @@ public class MapEntriesTest {
         assertEquals(0, aliasMap.size());
 
         //re-add node and test nodeDeletion true
+        when(resourceResolver.getResource("/parent")).thenReturn(result);
         addResource.invoke(mapEntries, "/parent", new AtomicBoolean());
 
         aliasMapEntry = mapEntries.getAliasMap("/");
@@ -1472,30 +1487,152 @@ public class MapEntriesTest {
 
         assertEquals(1, aliasMap.size());
 
+        
when(resourceResolver.getResource("/parent/jcr:content")).thenReturn(null);
+        when(result.getChild("jcr:content")).thenReturn(null);
         removeAlias.invoke(mapEntries, "/", "/parent/jcr:content", new 
AtomicBoolean());
 
         aliasMapEntry = mapEntries.getAliasMap("/");
         assertNull(aliasMapEntry);
 
         assertEquals(0, aliasMap.size());
+    }
 
-        //re-add node and test nodeDeletion true
-        addResource.invoke(mapEntries, "/parent/jcr:content", new 
AtomicBoolean());
+    @Test
+    public void test_doRemoveAliasFromSibling() throws Exception {
+        final Method addResource = 
MapEntries.class.getDeclaredMethod("addResource", String.class, 
AtomicBoolean.class);
+        addResource.setAccessible(true);
 
-        aliasMapEntry = mapEntries.getAliasMap("/");
+        final Method removeResource = 
MapEntries.class.getDeclaredMethod("removeResource", String.class, 
AtomicBoolean.class);
+        removeResource.setAccessible(true);
+
+        assertEquals(0, aliasMap.size());
+
+        Resource parent = mock(Resource.class);
+        when(parent.getPath()).thenReturn("/parent");
+
+        when(resourceResolver.getResource("/parent")).thenReturn(parent);
+        when(parent.getParent()).thenReturn(parent);
+        when(parent.getPath()).thenReturn("/parent");
+        when(parent.getName()).thenReturn("parent");
+        when(parent.getValueMap()).thenReturn(buildValueMap());
+
+        final Resource child1 = mock(Resource.class);
+        
when(resourceResolver.getResource("/parent/child1")).thenReturn(child1);
+        when(child1.getParent()).thenReturn(parent);
+        when(child1.getPath()).thenReturn("/parent/child1");
+        when(child1.getName()).thenReturn("child1");
+        when(child1.getValueMap()).thenReturn(buildValueMap());
+
+        final Resource child1JcrContent = mock(Resource.class);
+        
when(resourceResolver.getResource("/parent/child1/jcr:content")).thenReturn(child1JcrContent);
+        when(child1JcrContent.getParent()).thenReturn(child1);
+        
when(child1JcrContent.getPath()).thenReturn("/parent/child1/jcr:content");
+        when(child1JcrContent.getName()).thenReturn("jcr:content");
+        
when(child1JcrContent.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS,
 "test1"));
+        when(child1.getChild("jcr:content")).thenReturn(child1JcrContent);
+
+        when(parent.getChild("child1")).thenReturn(child1);
+
+        addResource.invoke(mapEntries, child1JcrContent.getPath(), new 
AtomicBoolean());
+
+        Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/parent");
         assertNotNull(aliasMapEntry);
-        assertTrue(aliasMapEntry.containsKey("aliasJcrContent"));
-        assertEquals("parent", aliasMapEntry.get("aliasJcrContent"));
+        assertTrue(aliasMapEntry.containsKey("test1"));
+        assertEquals("child1", aliasMapEntry.get("test1"));
 
         assertEquals(1, aliasMap.size());
-        
when(resourceResolver.getResource("/parent/jcr:content")).thenReturn(null);
-        when(result.getChild("jcr:content")).thenReturn(null);
-        removeAlias.invoke(mapEntries, "/", "/parent/jcr:content", new 
AtomicBoolean());
 
-        aliasMapEntry = mapEntries.getAliasMap("/");
+        final Resource child2 = mock(Resource.class);
+        
when(resourceResolver.getResource("/parent/child2")).thenReturn(child2);
+        when(child2.getParent()).thenReturn(parent);
+        when(child2.getPath()).thenReturn("/parent/child2");
+        when(child2.getName()).thenReturn("child2");
+        when(child2.getValueMap()).thenReturn(buildValueMap());
+
+        final Resource child2JcrContent = mock(Resource.class);
+        
when(resourceResolver.getResource("/parent/child2/jcr:content")).thenReturn(child2JcrContent);
+        when(child2JcrContent.getParent()).thenReturn(child2);
+        
when(child2JcrContent.getPath()).thenReturn("/parent/child2/jcr:content");
+        when(child2JcrContent.getName()).thenReturn("jcr:content");
+        
when(child2JcrContent.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS,
 "test2"));
+        when(child2.getChild("jcr:content")).thenReturn(child2JcrContent);
+
+        when(parent.getChild("child2")).thenReturn(child2);
+
+        addResource.invoke(mapEntries, child2JcrContent.getPath(), new 
AtomicBoolean());
+
+        aliasMapEntry = mapEntries.getAliasMap("/parent");
+        assertNotNull(aliasMapEntry);
+        assertTrue(aliasMapEntry.containsKey("test1"));
+        assertTrue(aliasMapEntry.containsKey("test2"));
+        assertEquals("child1", aliasMapEntry.get("test1"));
+        assertEquals("child2", aliasMapEntry.get("test2"));
+
+
+        assertEquals(1, aliasMap.size());
+        assertEquals(2, mapEntries.getAliasMap("/parent").size());
+
+        final Resource child2JcrContentChild = mock(Resource.class);
+        
when(resourceResolver.getResource("/parent/child2/jcr:content/test")).thenReturn(child2JcrContentChild);
+        when(child2JcrContentChild.getParent()).thenReturn(child2);
+        
when(child2JcrContentChild.getPath()).thenReturn("/parent/child2/jcr:content/test");
+        when(child2JcrContentChild.getName()).thenReturn("test");
+        
when(child2JcrContent.getChild("test")).thenReturn(child2JcrContentChild);
+
+        removeResource.invoke(mapEntries, child2JcrContentChild.getPath(), new 
AtomicBoolean());
+
+        aliasMapEntry = mapEntries.getAliasMap("/parent");
+        assertNotNull(aliasMapEntry);
+        assertTrue(aliasMapEntry.containsKey("test1"));
+        assertTrue(aliasMapEntry.containsKey("test2"));
+        assertEquals("child1", aliasMapEntry.get("test1"));
+        assertEquals("child2", aliasMapEntry.get("test2"));
+
+
+        assertEquals(1, aliasMap.size());
+        assertEquals(2, mapEntries.getAliasMap("/parent").size());
+
+        when(child2.getChild("jcr:content")).thenReturn(null);
+
+        removeResource.invoke(mapEntries, child2JcrContent.getPath(), new 
AtomicBoolean());
+
+        aliasMapEntry = mapEntries.getAliasMap("/parent");
+        assertNotNull(aliasMapEntry);
+        assertTrue(aliasMapEntry.containsKey("test1"));
+        assertEquals("child1", aliasMapEntry.get("test1"));
+
+
+        assertEquals(1, aliasMap.size());
+        assertEquals(1, mapEntries.getAliasMap("/parent").size());
+
+        when(child1.getChild("jcr:content")).thenReturn(null);
+
+        removeResource.invoke(mapEntries, child1JcrContent.getPath(), new 
AtomicBoolean());
+
+        aliasMapEntry = mapEntries.getAliasMap("/parent");
         assertNull(aliasMapEntry);
 
-        assertEquals(0, aliasMap.size());
+        when(child1.getChild("jcr:content")).thenReturn(child1JcrContent);
+        addResource.invoke(mapEntries, child1JcrContent.getPath(), new 
AtomicBoolean());
+        when(child2.getChild("jcr:content")).thenReturn(child2JcrContent);
+        addResource.invoke(mapEntries, child2JcrContent.getPath(), new 
AtomicBoolean());
+
+        aliasMapEntry = mapEntries.getAliasMap("/parent");
+        assertNotNull(aliasMapEntry);
+        assertTrue(aliasMapEntry.containsKey("test1"));
+        assertTrue(aliasMapEntry.containsKey("test2"));
+        assertEquals("child1", aliasMapEntry.get("test1"));
+        assertEquals("child2", aliasMapEntry.get("test2"));
+
+
+        assertEquals(1, aliasMap.size());
+        assertEquals(2, mapEntries.getAliasMap("/parent").size());
+
+        removeResource.invoke(mapEntries, parent.getPath(), new 
AtomicBoolean());
+
+
+        aliasMapEntry = mapEntries.getAliasMap("/parent");
+        assertNull(aliasMapEntry);
     }
 
     @Test


Reply via email to