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

radu pushed a commit to branch master
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-servlets-resolver.git


The following commit(s) were added to refs/heads/master by this push:
     new 9e7a3da  SLING-10188 - Reduce the number of service registrations for 
inheriting BundledScriptServlets
9e7a3da is described below

commit 9e7a3daeca72e3939fb404b3503d75c4c2ad99c1
Author: Radu Cotescu <[email protected]>
AuthorDate: Fri Mar 12 18:19:18 2021 +0100

    SLING-10188 - Reduce the number of service registrations for inheriting 
BundledScriptServlets
    
    * merge capabilities that provide only extend info with other capabilities 
with the same
    resource type
---
 .../bundle/BundledRenderUnitCapabilityImpl.java    | 104 +++++++++++++++++++++
 .../internal/bundle/BundledScriptTracker.java      |  64 ++++++++++++-
 2 files changed, 164 insertions(+), 4 deletions(-)

diff --git 
a/src/main/java/org/apache/sling/servlets/resolver/internal/bundle/BundledRenderUnitCapabilityImpl.java
 
b/src/main/java/org/apache/sling/servlets/resolver/internal/bundle/BundledRenderUnitCapabilityImpl.java
index 645d83e..b54c47d 100644
--- 
a/src/main/java/org/apache/sling/servlets/resolver/internal/bundle/BundledRenderUnitCapabilityImpl.java
+++ 
b/src/main/java/org/apache/sling/servlets/resolver/internal/bundle/BundledRenderUnitCapabilityImpl.java
@@ -26,6 +26,7 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 
+import org.apache.commons.lang3.StringUtils;
 import org.apache.sling.api.servlets.ServletResolverConstants;
 import org.apache.sling.commons.osgi.PropertiesUtil;
 import org.apache.sling.scripting.spi.bundle.BundledRenderUnitCapability;
@@ -131,6 +132,37 @@ class BundledRenderUnitCapabilityImpl  implements 
BundledRenderUnitCapability {
         return false;
     }
 
+    @Override
+    public String toString() {
+        StringBuilder sb = new 
StringBuilder(BundledRenderUnitCapability.class.getSimpleName()).append("[");
+        if (!resourceTypes.isEmpty()) {
+            
sb.append(ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES).append("=").append(resourceTypes);
+        }
+        if (!selectors.isEmpty()) {
+            sb.append("; 
").append(ServletResolverConstants.SLING_SERVLET_SELECTORS).append("=").append(selectors);
+        }
+        if (StringUtils.isNotEmpty(extension)) {
+            sb.append("; 
").append(ServletResolverConstants.SLING_SERVLET_EXTENSIONS).append("=").append(extension);
+        }
+        if (StringUtils.isNotEmpty(method)) {
+            sb.append("; 
").append(ServletResolverConstants.SLING_SERVLET_METHODS).append("=").append(method);
+        }
+        if (StringUtils.isNotEmpty(path)) {
+            sb.append("; 
").append(ServletResolverConstants.SLING_SERVLET_PATHS).append("=").append(path);
+        }
+        if (StringUtils.isNotEmpty(extendedResourceType)) {
+            sb.append("; 
").append(BundledScriptTracker.AT_EXTENDS).append("=").append(extendedResourceType);
+        }
+        if (StringUtils.isNotEmpty(scriptEngineName)) {
+            sb.append("; 
").append(BundledScriptTracker.AT_SCRIPT_ENGINE).append("=").append(scriptEngineName);
+        }
+        if (StringUtils.isNotEmpty(scriptExtension)) {
+            sb.append("; 
").append(BundledScriptTracker.AT_SCRIPT_EXTENSION).append("=").append(scriptExtension);
+        }
+        sb.append("]");
+        return sb.toString();
+    }
+
     public static BundledRenderUnitCapability fromBundleCapability(@NotNull 
BundleCapability capability) {
         Map<String, Object> attributes = capability.getAttributes();
         Set<ResourceType> resourceTypes = new LinkedHashSet<>();
@@ -156,4 +188,76 @@ class BundledRenderUnitCapabilityImpl  implements 
BundledRenderUnitCapability {
                 (String) 
attributes.get(BundledScriptTracker.AT_SCRIPT_EXTENSION)
         );
     }
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public static class Builder {
+        private Set<ResourceType> resourceTypes;
+        private String path;
+        private List<String> selectors;
+        private String extension;
+        private String method;
+        private String extendedResourceType;
+        private String scriptEngineName;
+        private String scriptExtension;
+
+        public Builder withResourceTypes(@NotNull Set<ResourceType> 
resourceTypes) {
+            this.resourceTypes = resourceTypes;
+            return this;
+        }
+
+        public Builder withPath(@Nullable String path) {
+            this.path = path;
+            return this;
+        }
+
+        public Builder withSelectors(@NotNull List<String> selectors) {
+            this.selectors = selectors;
+            return this;
+        }
+
+        public Builder withExtension(@Nullable String extension) {
+            this.extension = extension;
+            return this;
+        }
+
+        public Builder withMethod(@Nullable String method) {
+            this.method = method;
+            return this;
+        }
+
+        public Builder withExtendedResourceType(@Nullable String 
extendedResourceType) {
+            this.extendedResourceType = extendedResourceType;
+            return this;
+        }
+
+        public Builder withScriptEngineName(@Nullable String scriptEngineName) 
{
+            this.scriptEngineName = scriptEngineName;
+            return this;
+        }
+
+        public Builder withScriptEngineExtension(@Nullable String 
scriptExtension) {
+            this.scriptExtension = scriptExtension;
+            return this;
+        }
+
+        public Builder fromCapability(@NotNull BundledRenderUnitCapability 
capability) {
+            this.extendedResourceType = capability.getExtendedResourceType();
+            this.extension = capability.getExtension();
+            this.method = capability.getMethod();
+            this.path = capability.getPath();
+            this.resourceTypes = capability.getResourceTypes();
+            this.scriptEngineName = capability.getScriptEngineName();
+            this.scriptExtension = capability.getScriptExtension();
+            this.selectors = capability.getSelectors();
+            return this;
+        }
+
+        public BundledRenderUnitCapability build() {
+            return new BundledRenderUnitCapabilityImpl(resourceTypes, path, 
selectors, extension, method, extendedResourceType,
+                    scriptEngineName, scriptExtension);
+        }
+    }
 }
diff --git 
a/src/main/java/org/apache/sling/servlets/resolver/internal/bundle/BundledScriptTracker.java
 
b/src/main/java/org/apache/sling/servlets/resolver/internal/bundle/BundledScriptTracker.java
index 6883088..d785b76 100644
--- 
a/src/main/java/org/apache/sling/servlets/resolver/internal/bundle/BundledScriptTracker.java
+++ 
b/src/main/java/org/apache/sling/servlets/resolver/internal/bundle/BundledScriptTracker.java
@@ -29,6 +29,7 @@ import java.util.Dictionary;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Hashtable;
+import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
@@ -134,13 +135,18 @@ public class BundledScriptTracker implements 
BundleTrackerCustomizer<List<Servic
             LOGGER.debug("Inspecting bundle {} for {} capability.", 
bundle.getSymbolicName(), NS_SLING_SERVLET);
             List<BundleCapability> capabilities = 
bundleWiring.getCapabilities(NS_SLING_SERVLET);
             Map<BundleCapability, BundledRenderUnitCapability> cache = new 
HashMap<>();
+            capabilities.forEach(bundleCapability -> {
+                BundledRenderUnitCapability bundledRenderUnitCapability =
+                        
BundledRenderUnitCapabilityImpl.fromBundleCapability(bundleCapability);
+                cache.put(bundleCapability, bundledRenderUnitCapability);
+            });
             Set<TypeProvider> requiresChain = 
collectRequiresChain(bundleWiring, cache);
             if (!capabilities.isEmpty()) {
-                List<ServiceRegistration<Servlet>> serviceRegistrations = 
capabilities.stream().flatMap(cap ->
+                Set<BundledRenderUnitCapability> bundledRenderUnitCapabilities 
= new HashSet<>(cache.values());
+                bundledRenderUnitCapabilities = 
reduce(bundledRenderUnitCapabilities);
+                List<ServiceRegistration<Servlet>> serviceRegistrations = 
bundledRenderUnitCapabilities.stream().flatMap(bundledRenderUnitCapability ->
                 {
                     Hashtable<String, Object> properties = new Hashtable<>();
-                    properties.put(Constants.SERVICE_DESCRIPTION, 
BundledScriptServlet.class.getName() + cap.getAttributes());
-                    BundledRenderUnitCapability bundledRenderUnitCapability = 
cache.computeIfAbsent(cap, 
BundledRenderUnitCapabilityImpl::fromBundleCapability);
                     BundledRenderUnit executable = null;
                     TypeProvider baseTypeProvider = new 
TypeProviderImpl(bundledRenderUnitCapability, bundle);
                     LinkedHashSet<TypeProvider> inheritanceChain = new 
LinkedHashSet<>();
@@ -242,11 +248,13 @@ public class BundledScriptTracker implements 
BundleTrackerCustomizer<List<Servic
                         }
                         
properties.put(ServletResolverConstants.SLING_SERVLET_NAME,
                                 String.format("%s (%s)", 
BundledScriptServlet.class.getSimpleName(), executablePath));
+                        properties.put(Constants.SERVICE_DESCRIPTION,
+                                BundledScriptServlet.class.getName() + "{" + 
bundledRenderUnitCapability + "}");
                         regs.add(
                             register(bundle.getBundleContext(), new 
BundledScriptServlet(inheritanceChain, executable), properties)
                         );
                     } else {
-                        LOGGER.warn(String.format("Unable to locate an 
executable for capability %s.", cap));
+                        LOGGER.warn(String.format("Unable to locate an 
executable for capability %s.", bundledRenderUnitCapability.toString()));
                     }
 
                     return regs.stream();
@@ -589,4 +597,52 @@ public class BundledScriptTracker implements 
BundleTrackerCustomizer<List<Servic
         }
         return requiresChain;
     }
+
+    /**
+     * Given a {@code capabilities} set, this method will merge a capability 
providing a non-null {@link
+     * BundledRenderUnitCapability#getExtendedResourceType()} and just a 
resource type information with the other capabilities describing
+     * the same resource type.
+     *
+     * @param capabilities the original capabilities set
+     * @return a new set with merged capabilities or the original set, if no 
merges had to be performed
+     */
+    private Set<BundledRenderUnitCapability> 
reduce(Set<BundledRenderUnitCapability> capabilities) {
+        Set<BundledRenderUnitCapability> extenders =
+                capabilities.stream().filter(cap -> 
cap.getExtendedResourceType() != null && !cap.getResourceTypes().isEmpty() &&
+                        cap.getSelectors().isEmpty() && cap.getMethod() == 
null && cap.getExtension() == null && cap.getScriptEngineName() == 
null).collect(Collectors.toSet());
+        if (extenders.isEmpty()) {
+            return capabilities;
+        }
+        Set<BundledRenderUnitCapability> originalCapabilities = new 
HashSet<>(capabilities);
+        Set<BundledRenderUnitCapability> newSet = new HashSet<>();
+        originalCapabilities.removeAll(extenders);
+        if (originalCapabilities.isEmpty()) {
+            return extenders;
+        }
+        Iterator<BundledRenderUnitCapability> extendersIterator = 
extenders.iterator();
+        while (extendersIterator.hasNext()) {
+            BundledRenderUnitCapability extender = extendersIterator.next();
+            Iterator<BundledRenderUnitCapability> mergeCandidates = 
originalCapabilities.iterator();
+            boolean processedExtender = false;
+            while (mergeCandidates.hasNext()) {
+                BundledRenderUnitCapability mergeCandidate = 
mergeCandidates.next();
+                if 
(extender.getResourceTypes().equals(mergeCandidate.getResourceTypes())) {
+                    BundledRenderUnitCapability mergedCapability =
+                            BundledRenderUnitCapabilityImpl.builder()
+                                    .fromCapability(mergeCandidate)
+                                    
.withExtendedResourceType(extender.getExtendedResourceType()).build();
+                    newSet.add(mergedCapability);
+                    mergeCandidates.remove();
+                    processedExtender = true;
+                }
+            }
+            if (processedExtender) {
+                extendersIterator.remove();
+            }
+        }
+        // add extenders for which we couldn't merge their properties
+        newSet.addAll(extenders);
+        newSet.addAll(originalCapabilities);
+        return newSet;
+    }
 }

Reply via email to