This is an automated email from the ASF dual-hosted git repository. royteeuwen pushed a commit to branch backport/SLING-13275-1.x in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-resourceresolver.git
commit 3dca30ed9205c9552aeaa534ce6eaa80b28ed7d1 Author: Jörg Hoh <[email protected]> AuthorDate: Tue Jul 28 23:16:51 2026 +0200 SLING-13275: cache the result of the getParentResourceType call (backport to 1.x) Cherry-picked from master since this fix was never backported to the 1.x maintenance branch. Co-authored-by: Julian Sedding <[email protected]> (cherry picked from commit 3abb019aa7c242ebbac5bac756f07845f774b080) --- .../impl/ResourceResolverImpl.java | 22 +++++++++++++++++++--- .../impl/ResourceResolverImplTest.java | 17 +++++++++++++++++ 2 files changed, 36 insertions(+), 3 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 5f2cb049..1871edeb 100644 --- a/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverImpl.java +++ b/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverImpl.java @@ -97,6 +97,9 @@ public class ResourceResolverImpl extends SlingAdaptable implements ResourceReso protected final Map<ResourceTypeInformation, Boolean> resourceTypeLookupCache = new ConcurrentHashMap<>(); + // Store the resourceSupertype mapping (supertype can be null) + protected final Map<String, Optional<String>> parentResourceTypeMap = new ConcurrentHashMap<>(); + private Map<String, Object> propertyMap; private volatile Exception closedResolverException; @@ -1098,14 +1101,26 @@ public class ResourceResolverImpl extends SlingAdaptable implements ResourceReso checkClosed(); String resourceSuperType = null; if (resource != null) { - resourceSuperType = resource.getResourceSuperType(); - if (resourceSuperType == null) { - resourceSuperType = this.getParentResourceType(resource.getResourceType()); + if (parentResourceTypeMap.containsKey(resource.getPath())) { + resourceSuperType = + parentResourceTypeMap.get(resource.getPath()).orElse(null); + } else { + resourceSuperType = getParentResourceTypeInternal(resource); + parentResourceTypeMap.put(resource.getPath(), Optional.ofNullable(resourceSuperType)); } } return resourceSuperType; } + String getParentResourceTypeInternal(final Resource resource) { + String resourceSuperType; + resourceSuperType = resource.getResourceSuperType(); + if (resourceSuperType == null) { + resourceSuperType = this.getParentResourceType(resource.getResourceType()); + } + return resourceSuperType; + } + /** * @see org.apache.sling.api.resource.ResourceResolver#getParentResourceType(java.lang.String) */ @@ -1176,6 +1191,7 @@ public class ResourceResolverImpl extends SlingAdaptable implements ResourceReso checkClosed(); this.control.refresh(this.context); resourceTypeLookupCache.clear(); + parentResourceTypeMap.clear(); } @Override diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/ResourceResolverImplTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/ResourceResolverImplTest.java index 8ef66213..b1ded34e 100644 --- a/src/test/java/org/apache/sling/resourceresolver/impl/ResourceResolverImplTest.java +++ b/src/test/java/org/apache/sling/resourceresolver/impl/ResourceResolverImplTest.java @@ -62,9 +62,11 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.when; public class ResourceResolverImplTest { @@ -753,6 +755,21 @@ public class ResourceResolverImplTest { Mockito.verify(valueWithException, Mockito.times(1)).close(); } + @Test + public void testGetParentResourceType() { + final PathBasedResourceResolverImpl resolver = Mockito.spy(getPathBasedResourceResolver()); + + resolver.add(new SyntheticResourceWithSupertype(resolver, "/types/1", "/types/component", "/types/2")); + resolver.add(new SyntheticResourceWithSupertype(resolver, "/content/type1", "/types/1", null)); + + assertEquals("/types/2", resolver.getParentResourceType(resolver.getResource("/types/1"))); + assertEquals("/types/2", resolver.getParentResourceType(resolver.getResource("/content/type1"))); + + // Ensure that the next call will be served from the cache + resolver.getParentResourceType(resolver.getResource("/types/1")); + Mockito.verify(resolver, times(2)).getParentResourceTypeInternal(any(Resource.class)); + } + private PathBasedResourceResolverImpl getPathBasedResourceResolver() { return getPathBasedResourceResolver(new String[] {""}); }
