This is an automated email from the ASF dual-hosted git repository. pauls pushed a commit to branch issues/SLING-11373-passthrough in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-servlets-resolver.git
commit 9b3831301ad759faad3e97a22d210fbc7809c680 Author: Karl Pauls <[email protected]> AuthorDate: Wed Jun 15 09:45:38 2022 +0200 SLING-11373: use passthrough to mount the providers --- .../servlets/resolver/internal/ResolverConfig.java | 9 ++- .../resource/MergingServletResourceProvider.java | 29 ++++--- .../resolver/internal/resource/ServletMounter.java | 94 ++++++++++++++++------ 3 files changed, 93 insertions(+), 39 deletions(-) diff --git a/src/main/java/org/apache/sling/servlets/resolver/internal/ResolverConfig.java b/src/main/java/org/apache/sling/servlets/resolver/internal/ResolverConfig.java index 330f115..9cefe49 100644 --- a/src/main/java/org/apache/sling/servlets/resolver/internal/ResolverConfig.java +++ b/src/main/java/org/apache/sling/servlets/resolver/internal/ResolverConfig.java @@ -60,7 +60,12 @@ public @interface ResolverConfig { String[] servletresolver_defaultExtensions() default "html"; // NOSONAR @AttributeDefinition(name = "Mount Providers", description = "Should servlets be mounted as resource providers?" + - " If true (the default), servlets will be represented in the content tree using resource provider -" + - " otherwise, servlets will be decorated back into the content tree using a decorator.") + " If true (the default), servlets will be represented in the content tree using resource providers -" + + " otherwise, servlets will be decorated back into the content tree using a decorator unless mount path providers is true.") boolean servletresolver_mountProviders() default true; // NOSONAR + + @AttributeDefinition(name = "Mount Path Providers", description = "Should servlets be mounted via a single resource provider per search path entry?" + + " If false (the default), servlets will be represented in the content tree using individual resource providers -" + + " otherwise, servlets will be mounted into the content tree using one resource provider per search path entry. This effectively overrides mount providers.") + boolean servletresolver_mountPathProviders() default false; // NOSONAR } diff --git a/src/main/java/org/apache/sling/servlets/resolver/internal/resource/MergingServletResourceProvider.java b/src/main/java/org/apache/sling/servlets/resolver/internal/resource/MergingServletResourceProvider.java index 8f2dcf9..c5925e1 100644 --- a/src/main/java/org/apache/sling/servlets/resolver/internal/resource/MergingServletResourceProvider.java +++ b/src/main/java/org/apache/sling/servlets/resolver/internal/resource/MergingServletResourceProvider.java @@ -18,6 +18,18 @@ */ package org.apache.sling.servlets.resolver.internal.resource; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.sling.api.resource.NonExistingResource; +import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.SyntheticResource; +import org.apache.sling.spi.resource.provider.ResolveContext; +import org.apache.sling.spi.resource.provider.ResourceContext; +import org.apache.sling.spi.resource.provider.ResourceProvider; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.osgi.framework.Bundle; +import org.osgi.framework.ServiceReference; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -30,17 +42,7 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicReference; -import org.apache.commons.lang3.tuple.Pair; -import org.apache.sling.api.resource.NonExistingResource; -import org.apache.sling.api.resource.Resource; -import org.apache.sling.api.resource.SyntheticResource; -import org.apache.sling.spi.resource.provider.ResolveContext; -import org.apache.sling.spi.resource.provider.ResourceContext; -import org.apache.sling.spi.resource.provider.ResourceProvider; -import org.osgi.framework.Bundle; -import org.osgi.framework.ServiceReference; - -public class MergingServletResourceProvider { +public class MergingServletResourceProvider extends ResourceProvider<Object> { private final List<Pair<ServletResourceProvider, ServiceReference<?>>> registrations = new ArrayList<>(); private final AtomicReference<ConcurrentHashMap<String, Set<String>>> tree = new AtomicReference<>(new ConcurrentHashMap<>()); @@ -126,6 +128,11 @@ public class MergingServletResourceProvider { } } + @Override + public @Nullable Resource getResource(@NotNull ResolveContext<Object> resolveContext, @NotNull String s, @NotNull ResourceContext resourceContext, @Nullable Resource resource) { + return getResource(resolveContext, s); + } + @SuppressWarnings("unchecked") public Resource getResource(@SuppressWarnings("rawtypes") ResolveContext resolveContext, String path) { Resource wrapped = null; diff --git a/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletMounter.java b/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletMounter.java index f7c9ba0..fbd452b 100644 --- a/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletMounter.java +++ b/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletMounter.java @@ -18,24 +18,6 @@ */ package org.apache.sling.servlets.resolver.internal.resource; -import static org.apache.sling.api.servlets.ServletResolverConstants.SLING_SERVLET_NAME; -import static org.osgi.framework.Constants.SERVICE_ID; -import static org.osgi.framework.Constants.SERVICE_PID; -import static org.osgi.service.component.ComponentConstants.COMPONENT_NAME; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Dictionary; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import javax.servlet.Servlet; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; - import org.apache.sling.api.request.RequestUtil; import org.apache.sling.api.resource.ResourceResolverFactory; import org.apache.sling.api.servlets.ServletResolver; @@ -57,6 +39,25 @@ import org.osgi.service.component.annotations.ReferencePolicy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.servlet.Servlet; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Dictionary; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import static org.apache.sling.api.servlets.ServletResolverConstants.SLING_SERVLET_NAME; +import static org.osgi.framework.Constants.SERVICE_ID; +import static org.osgi.framework.Constants.SERVICE_PID; +import static org.osgi.service.component.ComponentConstants.COMPONENT_NAME; + /** * The <code>SlingServletResolver</code> resolves a * servlet for a request by implementing the {@link ServletResolver} interface. @@ -84,10 +85,15 @@ public class ServletMounter { private final MergingServletResourceProvider provider; - private final ServiceRegistration<MergingServletResourceProvider> providerReg; + private final Set<ServiceRegistration<?>> providerRegs; private final ConcurrentHashMap<ResolutionCache, ResolutionCache> resolutionCaches = new ConcurrentHashMap<>(); + private final BundleContext context; + + private final boolean pathProviders; + + /** * Activate this component. */ @@ -96,16 +102,30 @@ public class ServletMounter { @Reference(target = "(name=org.apache.sling)") ServletContext servletContext, final ResolverConfig config) { this.servletContext = servletContext; + this.context = context; servletResourceProviderFactory = new ServletResourceProviderFactory(config.servletresolver_servletRoot(), resourceResolverFactory.getSearchPath()); - if (!config.servletresolver_mountProviders()) { + if (config.servletresolver_mountPathProviders()) { provider = new MergingServletResourceProvider(); - providerReg = context.registerService(MergingServletResourceProvider.class, provider, null); - } - else { + providerRegs = new HashSet<>(); + pathProviders = true; + for (String path : resourceResolverFactory.getSearchPath()) { + final Dictionary<String, Object> params = new Hashtable<>(); + params.put(ResourceProvider.PROPERTY_ROOT, path); + params.put(Constants.SERVICE_DESCRIPTION, "ServletResourceProvider for Servlets"); + params.put("provider.mode", "passthrough"); + providerRegs.add(context.registerService(ResourceProvider.class, provider, params)); + } + } else if (!config.servletresolver_mountProviders()) { + provider = new MergingServletResourceProvider(); + providerRegs = new HashSet<>(); + pathProviders = false; + providerRegs.add(context.registerService(MergingServletResourceProvider.class, provider, null)); + } else { provider = null; - providerReg = null; + providerRegs = null; + pathProviders = false; } } @@ -127,8 +147,15 @@ public class ServletMounter { // destroy all servlets destroyAllServlets(refs); - if (providerReg != null) { - providerReg.unregister(); + if (providerRegs != null) { + for (ServiceRegistration reg : providerRegs) { + try { + reg.unregister(); + } catch (IllegalStateException ex) { + // Can happen during shutdown + } + } + providerRegs.clear(); } // sanity check: clear array (it should be empty now anyway) @@ -208,6 +235,21 @@ public class ServletMounter { try { if (this.provider != null) { this.provider.add(srProvider, reference); + if (pathProviders) { + outer: for (final String path : srProvider.getServletPaths()) { + String root = path.indexOf('/', 1) != -1 ? path.substring(0, path.indexOf('/', 1) + 1) : path; + for (ServiceRegistration reg : providerRegs) { + if (root.equals(reg.getReference().getProperty(ResourceProvider.PROPERTY_ROOT))) { + continue outer; + } + } + final Dictionary<String, Object> params = new Hashtable<>(); + params.put(ResourceProvider.PROPERTY_ROOT, root); + params.put(Constants.SERVICE_DESCRIPTION, "ServletResourceProvider for Servlets"); + params.put("provider.mode", "passthrough"); + providerRegs.add(context.registerService(ResourceProvider.class, provider, params)); + } + } resolutionCaches.values().forEach(ResolutionCache::flushCache); } else {
