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

joerghoh pushed a commit to branch SLING-11982-avoid-repo-access
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-servlets-resolver.git

commit 1f9372f37a28ea1e7d04d009c22bb5f626f36558
Author: Joerg Hoh <[email protected]>
AuthorDate: Sun Jul 23 11:54:56 2023 +0200

    SLING-11982 use a cache avoid repo access
---
 .../internal/helper/AbstractResourceCollector.java | 59 ++++++++++++++++++++++
 .../helper/NamedScriptResourceCollector.java       |  6 +--
 .../internal/helper/ResourceCollector.java         |  6 +--
 3 files changed, 65 insertions(+), 6 deletions(-)

diff --git 
a/src/main/java/org/apache/sling/servlets/resolver/internal/helper/AbstractResourceCollector.java
 
b/src/main/java/org/apache/sling/servlets/resolver/internal/helper/AbstractResourceCollector.java
index 4f90c97..77ac48b 100644
--- 
a/src/main/java/org/apache/sling/servlets/resolver/internal/helper/AbstractResourceCollector.java
+++ 
b/src/main/java/org/apache/sling/servlets/resolver/internal/helper/AbstractResourceCollector.java
@@ -20,7 +20,10 @@ package org.apache.sling.servlets.resolver.internal.helper;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
@@ -30,6 +33,8 @@ import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.resource.ResourceUtil;
 import org.apache.sling.api.resource.SyntheticResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * The <code>ResourceCollector</code> class provides a single public method -
@@ -38,6 +43,13 @@ import org.apache.sling.api.resource.SyntheticResource;
  * script to handle a request to the given resource.
  */
 public abstract class AbstractResourceCollector {
+    
+    
+    
+    private static final Logger LOG = 
LoggerFactory.getLogger(AbstractResourceCollector.class);
+    
+    
+    protected final static String CACHE_KEY_CHILDREN_LIST = 
AbstractResourceCollector.class.getName() + ".childrenList";
 
     // the most generic resource type to use. This may be null in which
     // case the default servlet name will be used as the base name
@@ -197,5 +209,52 @@ public abstract class AbstractResourceCollector {
         }
         return null;
     }
+    
+    /**
+     * Retrieves the list of children for a resource
+     * @param parent the resource for which the children should be retrieved
+     * @param useCaching if true try to read the list from the cache
+     * @return the children (or an empty list of no children are present)
+     */
+    static List<Resource> getChildrenList(Resource parent, boolean useCaching) 
{
+        
+        List<Resource> childList = new ArrayList<Resource>();
+        if (useCaching) {
+            
+            // init the caching structure
+            Map<String,List<Resource>> childrenListMap = new 
HashMap<String,List<Resource>>();
+            Map<String,Object> cache = 
parent.getResourceResolver().getPropertyMap();
+            if (!cache.containsKey(CACHE_KEY_CHILDREN_LIST)) {
+                childrenListMap = new HashMap<String,List<Resource>>();
+                cache.put(CACHE_KEY_CHILDREN_LIST, childrenListMap);
+               
+            } else {
+                Object entry = cache.get(CACHE_KEY_CHILDREN_LIST);
+                if (entry instanceof HashMap) {
+                    childrenListMap = (Map<String,List<Resource>>) 
cache.get(CACHE_KEY_CHILDREN_LIST); 
+                } else {
+                    // unexpected type
+                    LOG.debug("Found key '{}' used with the unexpected type 
'{}', not caching the resource children list", 
+                            CACHE_KEY_CHILDREN_LIST, 
entry.getClass().getName());
+                }
+            }
+            
+            // lookup
+            if (childrenListMap.containsKey(parent.getPath())) {
+                // this is a cache hit
+                List<Resource> result = childrenListMap.get(parent.getPath());
+                LOG.trace("getChildrenList cache-hit for {} with {} child 
resources", parent.getPath(), result.size());
+                return result;
+            }
+            // it's a cache miss
+            childrenListMap.put(parent.getPath(),childList);
+        }
+        Iterator<Resource> childrenIterator = parent.listChildren();
+        while (childrenIterator.hasNext()) {
+            childList.add(childrenIterator.next());
+        }
+        LOG.trace("getChildrenList cache-miss for {} with {} child resources", 
parent.getPath(),childList.size());
+        return childList;   
+    }
 
 }
diff --git 
a/src/main/java/org/apache/sling/servlets/resolver/internal/helper/NamedScriptResourceCollector.java
 
b/src/main/java/org/apache/sling/servlets/resolver/internal/helper/NamedScriptResourceCollector.java
index 07c32b4..2df58e5 100644
--- 
a/src/main/java/org/apache/sling/servlets/resolver/internal/helper/NamedScriptResourceCollector.java
+++ 
b/src/main/java/org/apache/sling/servlets/resolver/internal/helper/NamedScriptResourceCollector.java
@@ -19,6 +19,7 @@
 package org.apache.sling.servlets.resolver.internal.helper;
 
 import java.util.Iterator;
+import java.util.List;
 import java.util.Set;
 
 import org.apache.sling.api.resource.Resource;
@@ -113,9 +114,8 @@ public class NamedScriptResourceCollector extends 
AbstractResourceCollector {
             current = getResource(resolver, location.getPath() + '/' + 
this.scriptName.substring(0, pos));
             name = this.scriptName.substring(pos + 1);
         }
-        final Iterator<Resource> children = resolver.listChildren(current);
-        while (children.hasNext()) {
-            final Resource child = children.next();
+        final List<Resource> children = getChildrenList(current, 
useResourceCaching);
+        for (Resource child: children) {
 
             if ( SlingServletResolver.isPathAllowed(child.getPath(), 
this.executionPaths) ) {
                 final String currentScriptName = child.getName();
diff --git 
a/src/main/java/org/apache/sling/servlets/resolver/internal/helper/ResourceCollector.java
 
b/src/main/java/org/apache/sling/servlets/resolver/internal/helper/ResourceCollector.java
index df70b15..0d436de 100644
--- 
a/src/main/java/org/apache/sling/servlets/resolver/internal/helper/ResourceCollector.java
+++ 
b/src/main/java/org/apache/sling/servlets/resolver/internal/helper/ResourceCollector.java
@@ -20,6 +20,7 @@ package org.apache.sling.servlets.resolver.internal.helper;
 
 import java.util.Arrays;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Set;
 
 import org.apache.commons.lang3.ArrayUtils;
@@ -228,9 +229,8 @@ public class ResourceCollector extends 
AbstractResourceCollector {
                     ? requestSelectors[selIdx]
                     : null;
 
-            Iterator<Resource> children = resolver.listChildren(current);
-            while (children.hasNext()) { // NOSONAR
-                Resource child = children.next();
+            List<Resource> children = getChildrenList(current, 
isDefaultExtension);
+            for (Resource child: children) {
 
                 if (!SlingServletResolver.isPathAllowed(child.getPath(), 
this.executionPaths)) {
                     continue;

Reply via email to