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;
