You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2017/03/24 15:59:58 UTC

svn commit: r1788490 - 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: cziegeler
Date: Fri Mar 24 15:59:58 2017
New Revision: 1788490

URL: http://svn.apache.org/viewvc?rev=1788490&view=rev
Log:
SLING-6710 : Vanity Path might get removed if a resource is updated

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=1788490&r1=1788489&r2=1788490&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 Fri Mar 24 15:59:58 2017
@@ -61,6 +61,7 @@ import org.apache.sling.api.resource.obs
 import org.apache.sling.api.resource.observation.ResourceChange;
 import org.apache.sling.api.resource.observation.ResourceChangeListener;
 import org.apache.sling.api.resource.path.Path;
+import org.apache.sling.resourceresolver.impl.ResourceResolverFactoryImpl;
 import org.apache.sling.resourceresolver.impl.ResourceResolverImpl;
 import org.apache.sling.resourceresolver.impl.mapping.MapConfigurationProvider.VanityPathConfig;
 import org.osgi.framework.BundleContext;
@@ -155,7 +156,7 @@ public class MapEntries implements
 
         doInit();
 
-        final Dictionary<String, Object> props = new Hashtable<String, Object>();
+        final Dictionary<String, Object> props = new Hashtable<>();
         final String[] paths = new String[factory.getObservationPaths().length];
         for(int i=0 ; i < paths.length; i++) {
             paths[i] = factory.getObservationPaths()[i].getPath();
@@ -186,7 +187,7 @@ public class MapEntries implements
                 return;
             }
 
-            final Map<String, List<MapEntry>> newResolveMapsMap = new ConcurrentHashMap<String, List<MapEntry>>();
+            final Map<String, List<MapEntry>> newResolveMapsMap = new ConcurrentHashMap<>();
 
             //optimization made in SLING-2521
             if (this.factory.isOptimizeAliasResolutionEnabled()) {
@@ -268,12 +269,8 @@ public class MapEntries implements
             this.refreshResolverIfNecessary(resolverRefreshed);
             final Resource resource = resolver.getResource(path);
             if (resource != null) {
-                boolean changed = false;
-                final ValueMap props = resource.getValueMap();
-                if (props.containsKey(PROP_VANITY_PATH)) {
-                    changed |= doAddVanity(resource, props);
-                }
-                if (this.factory.isOptimizeAliasResolutionEnabled() && props.containsKey(ResourceResolverImpl.PROP_ALIAS)) {
+                boolean changed = doAddVanity(resource);
+                if (this.factory.isOptimizeAliasResolutionEnabled() && resource.getValueMap().containsKey(ResourceResolverImpl.PROP_ALIAS)) {
                     changed |= doAddAlias(resource);
                 }
                 return changed;
@@ -286,31 +283,39 @@ public class MapEntries implements
     }
 
     private boolean updateResource(final String path, final AtomicBoolean resolverRefreshed) {
-        this.initializing.lock();
-
-        try {
-            this.refreshResolverIfNecessary(resolverRefreshed);
-            final Resource resource = resolver.getResource(path);
-            if (resource != null) {
-                boolean changed = false;
-                final ValueMap props = resource.getValueMap();
+        final boolean isValidVanityPath =  this.isValidVanityPath(path);
+        if ( this.factory.isOptimizeAliasResolutionEnabled() || isValidVanityPath) {
+            this.initializing.lock();
 
-                changed |= doRemoveVanity(path);
-                if (props.containsKey(PROP_VANITY_PATH)) {
-                    changed |= doAddVanity(resource, props);
-                }
+            try {
+                this.refreshResolverIfNecessary(resolverRefreshed);
+                final Resource resource = resolver.getResource(path);
+                if (resource != null) {
+                    boolean changed = false;
+                    if ( isValidVanityPath ) {
+                        // we remove the old vanity path first
+                        changed |= doRemoveVanity(path);
+
+                        // add back vanity path
+                        Resource contentRsrc = null;
+                        if ( !resource.getName().equals(JCR_CONTENT)) {
+                            // there might be a JCR_CONTENT child resource
+                            contentRsrc = resource.getChild(JCR_CONTENT);
+                        }
+                        changed |= doAddVanity(contentRsrc != null ? contentRsrc : resource);
+                    }
+                    if (this.factory.isOptimizeAliasResolutionEnabled()) {
+                        changed |= doUpdateAlias(resource);
+                    }
 
-                if (this.factory.isOptimizeAliasResolutionEnabled()) {
-                    changed |= doUpdateAlias(resource);
+                    return changed;
                 }
-
-                return changed;
+            } finally {
+                this.initializing.unlock();
             }
-
-            return false;
-        } finally {
-            this.initializing.unlock();
         }
+
+        return false;
     }
 
     private boolean removeResource(final String path, final AtomicBoolean resolverRefreshed) {
@@ -400,8 +405,8 @@ public class MapEntries implements
      * Does no locking and does not send an event at the end
      */
     private void doUpdateConfiguration() {
-        final List<MapEntry> globalResolveMap = new ArrayList<MapEntry>();
-        final SortedMap<String, MapEntry> newMapMaps = new TreeMap<String, MapEntry>();
+        final List<MapEntry> globalResolveMap = new ArrayList<>();
+        final SortedMap<String, MapEntry> newMapMaps = new TreeMap<>();
         // load the /etc/map entries into the maps
         loadResolverMap(resolver, globalResolveMap, newMapMaps);
         // load the configuration into the resolver map
@@ -411,10 +416,10 @@ public class MapEntries implements
         // sort global list and add to map
         Collections.sort(globalResolveMap);
         resolveMapsMap.put(GLOBAL_LIST_KEY, globalResolveMap);
-        this.mapMaps = Collections.unmodifiableSet(new TreeSet<MapEntry>(newMapMaps.values()));
+        this.mapMaps = Collections.unmodifiableSet(new TreeSet<>(newMapMaps.values()));
     }
 
-    private boolean doAddVanity(final Resource resource, final ValueMap props) {
+    private boolean doAddVanity(final Resource resource) {
         log.debug("doAddVanity getting {}", resource.getPath());
 
         boolean needsUpdate = false;
@@ -573,7 +578,7 @@ public class MapEntries implements
      */
     @Override
     public List<MapEntry> getResolveMaps() {
-        final List<MapEntry> entries = new ArrayList<MapEntry>();
+        final List<MapEntry> entries = new ArrayList<>();
         for (final List<MapEntry> list : this.resolveMapsMap.values()) {
             entries.addAll(list);
         }
@@ -793,7 +798,7 @@ public class MapEntries implements
      */
     private Map<String, List<MapEntry>> getVanityPaths(String vanityPath) {
 
-        Map<String, List<MapEntry>> entryMap = new HashMap<String, List<MapEntry>>();
+        Map<String, List<MapEntry>> entryMap = new HashMap<>();
 
                 // sling:vanityPath (lowercase) is the property name
         final String queryString = "SELECT sling:vanityPath, sling:redirect, sling:redirectStatus FROM nt:base WHERE sling:vanityPath ="
@@ -818,7 +823,7 @@ public class MapEntries implements
                         loadVanityPath(resource, resolveMapsMap, vanityTargets, true, false);
                         entryMap = resolveMapsMap;
                     } else {
-                        final Map <String, List<String>> targetPaths = new HashMap <String, List<String>>();
+                        final Map <String, List<String>> targetPaths = new HashMap <>();
                         loadVanityPath(resource, entryMap, targetPaths, true, false);
                     }
                 }
@@ -834,18 +839,18 @@ public class MapEntries implements
     }
 
     /**
-     * Check if the resource is a valid vanity path resource
-     * @param resource The resource to check
+     * Check if the path is a valid vanity path
+     * @param path The resource path to check
      * @return {@code true} if this is valid, {@code false} otherwise
      */
-    private boolean isValidVanityPath(Resource resource){
-        if(resource == null) {
-            throw new IllegalArgumentException("Unexpected null resource");
+    private boolean isValidVanityPath(final String path){
+        if (path == null) {
+            throw new IllegalArgumentException("Unexpected null path");
         }
 
         // ignore system tree
-        if (resource.getPath().startsWith(JCR_SYSTEM_PREFIX)) {
-            log.debug("isValidVanityPath: not valid {}", resource);
+        if (path.startsWith(JCR_SYSTEM_PREFIX)) {
+            log.debug("isValidVanityPath: not valid {}", path);
             return false;
         }
 
@@ -853,13 +858,13 @@ public class MapEntries implements
         if ( this.factory.getVanityPathConfig() != null ) {
             boolean allowed = false;
             for(final VanityPathConfig config : this.factory.getVanityPathConfig()) {
-                if ( resource.getPath().startsWith(config.prefix) ) {
+                if ( path.startsWith(config.prefix) ) {
                     allowed = !config.isExclude;
                     break;
                 }
             }
             if ( !allowed ) {
-                log.debug("isValidVanityPath: not valid as not in white list {}", resource);
+                log.debug("isValidVanityPath: not valid as not in white list {}", path);
                 return false;
             }
         }
@@ -977,13 +982,13 @@ public class MapEntries implements
 
         List<MapEntry> entries = entryMap.get(key);
         if (entries == null) {
-            entries = new ArrayList<MapEntry>();
+            entries = new ArrayList<>();
             entries.add(entry);
             // and finally sort list
             Collections.sort(entries);
             entryMap.put(key, entries);
         } else {
-            List<MapEntry> entriesCopy =new ArrayList<MapEntry>(entries);
+            List<MapEntry> entriesCopy =new ArrayList<>(entries);
             entriesCopy.add(entry);
             // and finally sort list
             Collections.sort( entriesCopy);
@@ -997,7 +1002,7 @@ public class MapEntries implements
      * property
      */
     private Map<String, Map<String, String>> loadAliases(final ResourceResolver resolver) {
-        final Map<String, Map<String, String>> map = new ConcurrentHashMap<String, Map<String, String>>();
+        final Map<String, Map<String, String>> map = new ConcurrentHashMap<>();
         final String queryString = "SELECT sling:alias FROM nt:base WHERE sling:alias IS NOT NULL";
         final Iterator<Resource> i = resolver.findResources(queryString, "sql");
         while (i.hasNext()) {
@@ -1077,7 +1082,7 @@ public class MapEntries implements
                                     alias, parentPath);
                         } else {
                             if (parentMap == null) {
-                                parentMap = new LinkedHashMap<String, String>();
+                                parentMap = new LinkedHashMap<>();
                                 map.put(parentPath, parentMap);
                             }
                             parentMap.put(alias, resourceName);
@@ -1096,7 +1101,7 @@ public class MapEntries implements
      */
     private Map <String, List<String>> loadVanityPaths(boolean createVanityBloomFilter) {
         // sling:vanityPath (lowercase) is the property name
-        final Map <String, List<String>> targetPaths = new ConcurrentHashMap <String, List<String>>();
+        final Map <String, List<String>> targetPaths = new ConcurrentHashMap <>();
         final String queryString = "SELECT sling:vanityPath, sling:redirect, sling:redirectStatus FROM nt:base WHERE sling:vanityPath IS NOT NULL";
         final Iterator<Resource> i = resolver.findResources(queryString, "sql");
 
@@ -1132,7 +1137,7 @@ public class MapEntries implements
      */
     private boolean loadVanityPath(final Resource resource, final Map<String, List<MapEntry>> entryMap, final Map <String, List<String>> targetPaths, boolean addToCache, boolean newVanity) {
 
-        if (!isValidVanityPath(resource)) {
+        if (!isValidVanityPath(resource.getPath())) {
             return false;
         }
 
@@ -1221,7 +1226,7 @@ public class MapEntries implements
         }
         List<String> entries = targetPaths.get(key);
         if (entries == null) {
-            entries = new ArrayList<String>();
+            entries = new ArrayList<>();
             targetPaths.put(key, entries);
         }
         entries.add(entry);
@@ -1293,7 +1298,7 @@ public class MapEntries implements
         // URL Mappings
         final Mapping[] mappings = factory.getMappings();
         if (mappings != null) {
-            final Map<String, List<String>> map = new HashMap<String, List<String>>();
+            final Map<String, List<String>> map = new HashMap<>();
             for (final Mapping mapping : mappings) {
                 if (mapping.mapsInbound()) {
                     final String url = mapping.getTo();
@@ -1301,7 +1306,7 @@ public class MapEntries implements
                     if (url.length() > 0) {
                         List<String> aliasList = map.get(url);
                         if (aliasList == null) {
-                            aliasList = new ArrayList<String>();
+                            aliasList = new ArrayList<>();
                             map.put(url, aliasList);
                         }
                         aliasList.add(alias);

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=1788490&r1=1788489&r2=1788490&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 Fri Mar 24 15:59:58 2017
@@ -101,7 +101,7 @@ public class MapEntriesTest {
     public void setup() throws Exception {
         MockitoAnnotations.initMocks(this);
 
-        final List<VanityPathConfig> configs = new ArrayList<MapConfigurationProvider.VanityPathConfig>();
+        final List<VanityPathConfig> configs = new ArrayList<>();
         configs.add(new VanityPathConfig("/libs/", false));
         configs.add(new VanityPathConfig("/libs/denied", true));
         configs.add(new VanityPathConfig("/foo/", false));
@@ -218,7 +218,7 @@ public class MapEntriesTest {
 
         when(resourceResolverFactory.getDefaultVanityPathRedirectStatus()).thenReturn(DEFAULT_VANITY_STATUS);
 
-        final List<Resource> resources = new ArrayList<Resource>();
+        final List<Resource> resources = new ArrayList<>();
 
         Resource justVanityPath = mock(Resource.class, "justVanityPath");
         when(justVanityPath.getPath()).thenReturn("/justVanityPath");
@@ -298,7 +298,7 @@ public class MapEntriesTest {
     }
 
     private ValueMap buildValueMap(Object... string) {
-        final Map<String, Object> data = new HashMap<String, Object>();
+        final Map<String, Object> data = new HashMap<>();
         for (int i = 0; i < string.length; i = i + 2) {
             data.put((String) string[i], string[i+1]);
         }
@@ -318,7 +318,7 @@ public class MapEntriesTest {
         final String[] validPaths = {"/libs/somewhere", "/libs/a/b", "/foo/a", "/baa/a"};
         final String[] invalidPaths = {"/libs/denied/a", "/libs/denied/b/c", "/nowhere"};
 
-        final List<Resource> resources = new ArrayList<Resource>();
+        final List<Resource> resources = new ArrayList<>();
         for(final String val : validPaths) {
             resources.add(getVanityPathResource(val));
         }
@@ -346,7 +346,7 @@ public class MapEntriesTest {
         // each valid resource results in 2 entries
         assertEquals(validPaths.length * 2, entries.size());
 
-        final Set<String> resultSet = new HashSet<String>();
+        final Set<String> resultSet = new HashSet<>();
         for(final String p : validPaths) {
             resultSet.add(p + "$1");
             resultSet.add(p + ".html");
@@ -1426,18 +1426,12 @@ public class MapEntriesTest {
 
     @Test
     public void test_isValidVanityPath() throws Exception {
-        Method method = MapEntries.class.getDeclaredMethod("isValidVanityPath", Resource.class);
+        Method method = MapEntries.class.getDeclaredMethod("isValidVanityPath", String.class);
         method.setAccessible(true);
 
-        final Resource resource = mock(Resource.class);
-        when(resource.getPath()).thenReturn("/jcr:system/node");
+        assertFalse((Boolean)method.invoke(mapEntries, "/jcr:system/node"));
 
-        assertFalse((Boolean)method.invoke(mapEntries, resource));
-
-        when(resource.getPath()).thenReturn("/justVanityPath");
-        when(resource.getValueMap()).thenReturn(mock(ValueMap.class));
-
-        assertTrue((Boolean)method.invoke(mapEntries, resource));
+        assertTrue((Boolean)method.invoke(mapEntries, "/justVanityPath"));
     }
 
     @Test
@@ -1803,7 +1797,7 @@ public class MapEntriesTest {
 
         when(this.resourceResolverFactory.getMaxCachedVanityPathEntries()).thenReturn(2L);
 
-        ArrayList<DataFuture> list = new ArrayList<DataFuture>();
+        ArrayList<DataFuture> list = new ArrayList<>();
         for (int i =0;i<10;i++) {
             list.add(createDataFuture(pool, mapEntries));
 
@@ -1814,7 +1808,7 @@ public class MapEntriesTest {
         }
 
     }
-    
+
     // tests SLING-6542
     @Test
     public void sessionConcurrency() throws Exception {
@@ -1822,7 +1816,7 @@ public class MapEntriesTest {
         addResource.setAccessible(true);
         final Method updateResource = MapEntries.class.getDeclaredMethod("updateResource", String.class, AtomicBoolean.class);
         updateResource.setAccessible(true);
-        final Method handleConfigurationUpdate = MapEntries.class.getDeclaredMethod("handleConfigurationUpdate", 
+        final Method handleConfigurationUpdate = MapEntries.class.getDeclaredMethod("handleConfigurationUpdate",
                 String.class, AtomicBoolean.class, AtomicBoolean.class, boolean.class);
         handleConfigurationUpdate.setAccessible(true);
 
@@ -1837,7 +1831,7 @@ public class MapEntriesTest {
                 simulateSomewhatSlowSessionOperation(sessionLock);
                 return null;
             }
-            
+
         }).when(resourceResolver).refresh();
         Mockito.doAnswer(new Answer<Resource>() {
 
@@ -1846,13 +1840,13 @@ public class MapEntriesTest {
                 simulateSomewhatSlowSessionOperation(sessionLock);
                 return null;
             }
-            
+
         }).when(resourceResolver).getResource(any(String.class));
-        
+
         when(resourceResolverFactory.isMapConfiguration(any(String.class))).thenReturn(true);
-        
+
         final AtomicInteger failureCnt = new AtomicInteger(0);
-        final List<Exception> exceptions = new LinkedList<Exception>();
+        final List<Exception> exceptions = new LinkedList<>();
         final Semaphore done = new Semaphore(0);
         final int NUM_THREADS = 30;
         final Random random = new Random(12321);
@@ -1925,5 +1919,5 @@ public class MapEntriesTest {
             this.future = future;
         }
     }
-    
+
 }
\ No newline at end of file