You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ra...@apache.org on 2020/04/09 16:27:23 UTC

[sling-org-apache-sling-scripting-bundle-tracker] 01/03: SLING-9349 - Provide the list of TypeProviders for a BundledRenderUnit

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-scripting-bundle-tracker.git

commit 70542e31d3716796b71ff16d4014280b04d969d9
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Thu Apr 9 18:00:46 2020 +0200

    SLING-9349 - Provide the list of TypeProviders for a BundledRenderUnit
    
    * exposed the TypeProvider and BundledRenderUnitCapability APIs
---
 .../bundle/tracker/BundledRenderUnit.java          | 10 +++
 .../tracker/BundledRenderUnitCapability.java       | 91 ++++++++++++++++++++++
 .../{package-info.java => TypeProvider.java}       | 33 +++++++-
 .../internal/AbstractBundledRenderUnit.java        | 12 ++-
 ...y.java => BundledRenderUnitCapabilityImpl.java} | 61 +++++++++------
 .../tracker/internal/BundledScriptFinder.java      | 20 +++--
 .../tracker/internal/BundledScriptServlet.java     |  3 +-
 .../tracker/internal/BundledScriptTracker.java     | 71 ++++++++++-------
 .../bundle/tracker/internal/PrecompiledScript.java |  7 +-
 .../scripting/bundle/tracker/internal/Script.java  |  7 +-
 .../{TypeProvider.java => TypeProviderImpl.java}   | 55 +++++--------
 .../scripting/bundle/tracker/package-info.java     |  2 +-
 12 files changed, 266 insertions(+), 106 deletions(-)

diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/BundledRenderUnit.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/BundledRenderUnit.java
index eda9d58..3849a36 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/BundledRenderUnit.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/BundledRenderUnit.java
@@ -18,6 +18,8 @@
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 package org.apache.sling.scripting.bundle.tracker;
 
+import java.util.Set;
+
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.osgi.annotation.versioning.ProviderType;
@@ -72,6 +74,14 @@ public interface BundledRenderUnit {
     @NotNull Bundle getBundle();
 
     /**
+     * Returns the {@code Set} of {@link TypeProvider}s which are related to this unit.
+     *
+     * @return the set of providers; if the unit doesn't have any inheritance chains, then the set will contain only one {@link
+     * TypeProvider}
+     */
+    @NotNull Set<TypeProvider> getTypeProviders();
+
+    /**
      * Retrieves an OSGi runtime dependency of the wrapped script identified by the passed {@code className} parameter.
      *
      * @param className the fully qualified class name
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/BundledRenderUnitCapability.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/BundledRenderUnitCapability.java
new file mode 100644
index 0000000..dbda3d6
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/BundledRenderUnitCapability.java
@@ -0,0 +1,91 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements.  See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership.  The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License.  You may obtain a copy of the License at
+ ~
+ ~   http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied.  See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+package org.apache.sling.scripting.bundle.tracker;
+
+import java.util.List;
+import java.util.Set;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.osgi.annotation.versioning.ProviderType;
+
+/**
+ * A {@code BundledRenderUnitCapability} encapsulates the values of a {@code Provided-Capability}, based on which {@link BundledRenderUnit}s
+ * are generated.
+ */
+@ProviderType
+public interface BundledRenderUnitCapability {
+
+    /**
+     * Returns the resource types to which a {@link BundledRenderUnit} described by this capability will be bound to.
+     *
+     * @return the resource types to which a {@link BundledRenderUnit} described by this capability will be bound to
+     */
+    @NotNull Set<ResourceType> getResourceTypes();
+
+    /**
+     * Returns the path to which a {@link BundledRenderUnit} described by this capability will be bound to.
+     *
+     * @return the path to which a {@link BundledRenderUnit} described by this capability will be bound to; this can be {@code null} if the
+     * {@link #getResourceTypes()} doesn't return an empty set
+     */
+    @Nullable String getPath();
+
+    /**
+     * Returns the selectors to which a {@link BundledRenderUnit} described by this capability will be bound to.
+     *
+     * @return the selectors to which a {@link BundledRenderUnit} described by this capability will be bound to
+     */
+    @NotNull List<String> getSelectors();
+
+    /**
+     * Returns the extension to which a {@link BundledRenderUnit} described by this capability will be bound to.
+     *
+     * @return the extension to which a {@link BundledRenderUnit} described by this capability will be bound to
+     */
+    @Nullable String getExtension();
+
+    /**
+     * Returns the resource type extended by this capability.
+     *
+     * @return the extended resource type or {@code null}
+     */
+    @Nullable String getExtendedResourceType();
+
+    /**
+     * Returns the request method to which a {@link BundledRenderUnit} described by this capability will be bound to.
+     *
+     * @return the request method to which a {@link BundledRenderUnit} described by this capability will be bound to
+     */
+    @Nullable String getMethod();
+
+    /**
+     * Returns the script engine short name which can be used to evaluate the {@link BundledRenderUnit} described by this capability.
+     *
+     * @return the script engine short name which can be used to evaluate the {@link BundledRenderUnit} described by this capability.
+     */
+    @Nullable String getScriptEngineName();
+
+    /**
+     * Returns the original's script extension that was used to generate this capability.
+     *
+     * @return the original's script extension that was used to generate this capability.
+     */
+    @Nullable String getScriptExtension();
+}
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/package-info.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/TypeProvider.java
similarity index 53%
copy from src/main/java/org/apache/sling/scripting/bundle/tracker/package-info.java
copy to src/main/java/org/apache/sling/scripting/bundle/tracker/TypeProvider.java
index 3f59450..cbb89fb 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/package-info.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/TypeProvider.java
@@ -16,7 +16,36 @@
  ~ specific language governing permissions and limitations
  ~ under the License.
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-@Version("0.1.0")
 package org.apache.sling.scripting.bundle.tracker;
 
-import org.osgi.annotation.versioning.Version;
+import org.jetbrains.annotations.NotNull;
+import org.osgi.annotation.versioning.ProviderType;
+import org.osgi.framework.Bundle;
+
+/**
+ * A {@code TypeProvider} keeps an association between a {@link BundledRenderUnitCapability} and the bundle that provides it.
+ */
+@ProviderType
+public interface TypeProvider {
+
+    /**
+     * Returns the {@link BundledRenderUnitCapability}.
+     *
+     * @return the {@link BundledRenderUnitCapability}
+     */
+    @NotNull BundledRenderUnitCapability getBundledRenderUnitCapability();
+
+    /**
+     * Returns the providing bundle.
+     *
+     * @return the providing bundle
+     */
+    @NotNull Bundle getBundle();
+
+    /**
+     * Returns {@code true} if the bundle provides precompiled scripts.
+     *
+     * @return {@code true} if the bundle provides precompiled scripts, {@code false} otherwise
+     */
+    boolean isPrecompiled();
+}
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/AbstractBundledRenderUnit.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/AbstractBundledRenderUnit.java
index b82a4f8..9362b32 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/AbstractBundledRenderUnit.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/AbstractBundledRenderUnit.java
@@ -25,7 +25,9 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
+import org.apache.sling.scripting.bundle.tracker.TypeProvider;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.osgi.framework.Bundle;
@@ -38,6 +40,7 @@ abstract class AbstractBundledRenderUnit implements Executable {
 
     private static final Logger LOG = LoggerFactory.getLogger(AbstractBundledRenderUnit.class.getName());
 
+    private final Set<TypeProvider> providers;
     private final Bundle bundle;
     private final BundleContext bundleContext;
     private final String path;
@@ -46,7 +49,9 @@ abstract class AbstractBundledRenderUnit implements Executable {
     private Map<String, Object> services;
 
 
-    AbstractBundledRenderUnit(@NotNull Bundle bundle, @NotNull String path, @NotNull String scriptEngineName) {
+    AbstractBundledRenderUnit(@NotNull Set<TypeProvider> providers, @NotNull Bundle bundle, @NotNull String path,
+                              @NotNull String scriptEngineName) {
+        this.providers = providers;
         this.bundle = bundle;
         this.path = path;
         this.scriptEngineName = scriptEngineName;
@@ -60,6 +65,11 @@ abstract class AbstractBundledRenderUnit implements Executable {
     }
 
     @Override
+    public @NotNull Set<TypeProvider> getTypeProviders() {
+        return providers;
+    }
+
+    @Override
     public @NotNull String getPath() {
         return path;
     }
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/ServletCapability.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledRenderUnitCapabilityImpl.java
similarity index 64%
rename from src/main/java/org/apache/sling/scripting/bundle/tracker/internal/ServletCapability.java
rename to src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledRenderUnitCapabilityImpl.java
index 1d7d2c5..917d535 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/ServletCapability.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledRenderUnitCapabilityImpl.java
@@ -20,7 +20,6 @@ package org.apache.sling.scripting.bundle.tracker.internal;
 
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
@@ -29,13 +28,14 @@ import java.util.Set;
 
 import org.apache.sling.api.servlets.ServletResolverConstants;
 import org.apache.sling.commons.osgi.PropertiesUtil;
+import org.apache.sling.scripting.bundle.tracker.BundledRenderUnitCapability;
 import org.apache.sling.scripting.bundle.tracker.ResourceType;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.osgi.framework.Version;
 import org.osgi.framework.wiring.BundleCapability;
 
-class ServletCapability {
+public class BundledRenderUnitCapabilityImpl  implements BundledRenderUnitCapability {
 
     private final Set<ResourceType> resourceTypes;
     private final String path;
@@ -46,10 +46,11 @@ class ServletCapability {
     private final String scriptEngineName;
     private final String scriptExtension;
 
-    private ServletCapability(@NotNull Set<ResourceType> resourceTypes, @Nullable String path, @NotNull List<String> selectors,
-                              @Nullable String extension, @Nullable String method,
-                              @Nullable String extendedResourceType, @Nullable String scriptEngineName,
-                              @Nullable String scriptExtension) {
+    private BundledRenderUnitCapabilityImpl(@NotNull Set<ResourceType> resourceTypes, @Nullable String path,
+                                            @NotNull List<String> selectors,
+                                        @Nullable String extension, @Nullable String method,
+                                        @Nullable String extendedResourceType, @Nullable String scriptEngineName,
+                                        @Nullable String scriptExtension) {
         this.resourceTypes = resourceTypes;
         this.path = path;
         this.selectors = selectors;
@@ -60,43 +61,51 @@ class ServletCapability {
         this.scriptExtension = scriptExtension;
     }
 
+    @Override
     @NotNull
-    Set<ResourceType> getResourceTypes() {
+    public Set<ResourceType> getResourceTypes() {
         return Collections.unmodifiableSet(resourceTypes);
     }
 
+    @Override
     @Nullable
     public String getPath() {
         return path;
     }
 
+    @Override
     @NotNull
-    List<String> getSelectors() {
+    public List<String> getSelectors() {
         return Collections.unmodifiableList(selectors);
     }
 
+    @Override
     @Nullable
-    String getExtension() {
+    public String getExtension() {
         return extension;
     }
 
+    @Override
     @Nullable
-    String getExtendedResourceType() {
+    public String getExtendedResourceType() {
         return extendedResourceType;
     }
 
+    @Override
     @Nullable
-    String getMethod() {
+    public String getMethod() {
         return method;
     }
 
+    @Override
     @Nullable
-    String getScriptEngineName() {
+    public String getScriptEngineName() {
         return scriptEngineName;
     }
 
+    @Override
     @Nullable
-    String getScriptExtension() {
+    public String getScriptExtension() {
         return scriptExtension;
     }
 
@@ -110,22 +119,23 @@ class ServletCapability {
         if (this == obj) {
             return true;
         }
-        if (obj instanceof ServletCapability) {
-            ServletCapability other = (ServletCapability) obj;
-            return Objects.equals(resourceTypes, other.resourceTypes) && Objects.equals(path, other.path) &&
-                    Objects.equals(selectors, other.selectors) &&
-                    Objects.equals(extension, other.extension) && Objects.equals(method, other.method) &&
-                    Objects.equals(extendedResourceType, other.extendedResourceType) &&
-                    Objects.equals(scriptEngineName, other.scriptEngineName) && Objects.equals(scriptExtension, other.scriptExtension);
+        if (obj instanceof BundledRenderUnitCapability) {
+            BundledRenderUnitCapability other = (BundledRenderUnitCapability) obj;
+            return Objects.equals(resourceTypes, other.getResourceTypes()) && Objects.equals(path, other.getPath()) &&
+                    Objects.equals(selectors, other.getSelectors()) &&
+                    Objects.equals(extension, other.getExtension()) && Objects.equals(method, other.getMethod()) &&
+                    Objects.equals(extendedResourceType, other.getExtendedResourceType()) &&
+                    Objects.equals(scriptEngineName, other.getScriptEngineName()) &&
+                    Objects.equals(scriptExtension, other.getScriptExtension());
         }
         return false;
     }
 
-    static ServletCapability fromBundleCapability(@NotNull BundleCapability capability) {
+    public static BundledRenderUnitCapability fromBundleCapability(@NotNull BundleCapability capability) {
         Map<String, Object> attributes = capability.getAttributes();
         Set<ResourceType> resourceTypes = new LinkedHashSet<>();
-        String[] capabilityResourceTypes = PropertiesUtil.toStringArray(attributes.get(ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES),
-                new String[0]);
+        String[] capabilityResourceTypes =
+                PropertiesUtil.toStringArray(attributes.get(ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES), new String[0]);
         Version version = (Version) attributes.get(BundledScriptTracker.AT_VERSION);
         for (String rt : capabilityResourceTypes) {
             if (version == null) {
@@ -134,10 +144,11 @@ class ServletCapability {
                 resourceTypes.add(ResourceType.parseResourceType(rt + "/" + version.toString()));
             }
         }
-        return new ServletCapability(
+        return new BundledRenderUnitCapabilityImpl(
                 resourceTypes,
                 (String) attributes.get(ServletResolverConstants.SLING_SERVLET_PATHS),
-                Arrays.asList(PropertiesUtil.toStringArray(attributes.get(ServletResolverConstants.SLING_SERVLET_SELECTORS), new String[0])),
+                Arrays.asList(
+                        PropertiesUtil.toStringArray(attributes.get(ServletResolverConstants.SLING_SERVLET_SELECTORS), new String[0])),
                 (String) attributes.get(ServletResolverConstants.SLING_SERVLET_EXTENSIONS),
                 (String) attributes.get(ServletResolverConstants.SLING_SERVLET_METHODS),
                 (String) attributes.get(BundledScriptTracker.AT_EXTENDS),
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java
index a9adcd5..6cf351c 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java
@@ -27,7 +27,9 @@ import java.util.Set;
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.sling.commons.compiler.source.JavaEscapeHelper;
+import org.apache.sling.scripting.bundle.tracker.BundledRenderUnitCapability;
 import org.apache.sling.scripting.bundle.tracker.ResourceType;
+import org.apache.sling.scripting.bundle.tracker.TypeProvider;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.osgi.framework.Bundle;
@@ -44,14 +46,15 @@ public class BundledScriptFinder {
 
     Executable getScript(Set<TypeProvider> providers) {
         for (TypeProvider provider : providers) {
-            ServletCapability capability = provider.getServletCapability();
+            BundledRenderUnitCapability capability = provider.getBundledRenderUnitCapability();
             for (String match : buildScriptMatches(capability.getResourceTypes(),
                     capability.getSelectors().toArray(new String[0]), capability.getMethod(), capability.getExtension())) {
                 String scriptExtension = capability.getScriptExtension();
                 String scriptEngineName = capability.getScriptEngineName();
                 if (StringUtils.isNotEmpty(scriptExtension) && StringUtils.isNotEmpty(scriptEngineName)) {
                     Executable executable =
-                            getExecutable(provider.getBundle(), provider.isPrecompiled(), match, scriptEngineName, scriptExtension);
+                            getExecutable(provider.getBundle(), provider.isPrecompiled(), match, scriptEngineName, scriptExtension,
+                                    providers);
                     if (executable != null) {
                         return executable;
                     }
@@ -61,29 +64,30 @@ public class BundledScriptFinder {
         return null;
     }
 
-    Executable getScript(@NotNull Bundle bundle, boolean precompiled, @NotNull String path, @NotNull String scriptEngineName) {
+    Executable getScript(@NotNull Bundle bundle, boolean precompiled, @NotNull String path, @NotNull String scriptEngineName,
+                         @NotNull Set<TypeProvider> providers) {
         if (precompiled) {
             String className = JavaEscapeHelper.makeJavaPackage(path);
             try {
                 Class<?> clazz = bundle.loadClass(className);
-                return new PrecompiledScript(bundle, path, clazz, scriptEngineName);
+                return new PrecompiledScript(providers, bundle, path, clazz, scriptEngineName);
             } catch (ClassNotFoundException ignored) {
                 // do nothing here
             }
         } else {
             URL bundledScriptURL = bundle.getEntry(NS_JAVAX_SCRIPT_CAPABILITY + (path.startsWith("/") ? "" : SLASH) + path);
             if (bundledScriptURL != null) {
-                return new Script(bundle, path, bundledScriptURL, scriptEngineName);
+                return new Script(providers, bundle, path, bundledScriptURL, scriptEngineName);
             }
         }
         return null;
     }
 
     @Nullable
-    private Executable getExecutable(@NotNull Bundle bundle, boolean precompiled, @NotNull String match,
-                                     @NotNull String scriptEngineName, @NotNull String scriptExtension) {
+    private Executable getExecutable(@NotNull Bundle bundle, boolean precompiled, @NotNull String match, @NotNull String scriptEngineName,
+                                     @NotNull String scriptExtension, @NotNull Set<TypeProvider> providers) {
         String path = match + DOT + scriptExtension;
-        return getScript(bundle, precompiled, path, scriptEngineName);
+        return getScript(bundle, precompiled, path, scriptEngineName, providers);
     }
 
     private List<String> buildScriptMatches(Set<ResourceType> resourceTypes, String[] selectors, String method, String extension) {
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptServlet.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptServlet.java
index d3270d0..bcdad99 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptServlet.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptServlet.java
@@ -32,6 +32,7 @@ import javax.servlet.ServletResponse;
 import org.apache.sling.api.SlingConstants;
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.scripting.bundle.tracker.TypeProvider;
 import org.apache.sling.scripting.bundle.tracker.internal.request.RequestWrapper;
 import org.jetbrains.annotations.NotNull;
 
@@ -67,7 +68,7 @@ class BundledScriptServlet extends GenericServlet {
             }
 
             RequestWrapper requestWrapper = new RequestWrapper(request,
-                    wiredTypeProviders.stream().map(typeProvider -> typeProvider.getServletCapability().getResourceTypes()
+                    wiredTypeProviders.stream().map(typeProvider -> typeProvider.getBundledRenderUnitCapability().getResourceTypes()
             ).flatMap(Collection::stream).collect(Collectors.toSet()));
             ScriptContextProvider.ExecutableContext executableContext = scriptContextProvider
                     .prepareScriptContext(requestWrapper, response, executable);
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptTracker.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptTracker.java
index fd995e6..0401053 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptTracker.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptTracker.java
@@ -49,6 +49,8 @@ import org.apache.sling.api.request.RequestDispatcherOptions;
 import org.apache.sling.api.servlets.ServletResolverConstants;
 import org.apache.sling.commons.osgi.PropertiesUtil;
 import org.apache.sling.scripting.bundle.tracker.ResourceType;
+import org.apache.sling.scripting.bundle.tracker.BundledRenderUnitCapability;
+import org.apache.sling.scripting.bundle.tracker.TypeProvider;
 import org.jetbrains.annotations.NotNull;
 import org.osgi.annotation.bundle.Capability;
 import org.osgi.framework.Bundle;
@@ -81,13 +83,13 @@ import org.slf4j.LoggerFactory;
 public class BundledScriptTracker implements BundleTrackerCustomizer<List<ServiceRegistration<Servlet>>> {
     static final String NS_SLING_SCRIPTING_EXTENDER = "sling.scripting";
 
-    static final String NS_SLING_SERVLET = "sling.servlet";
     private static final Logger LOGGER = LoggerFactory.getLogger(BundledScriptTracker.class);
     private static final String REGISTERING_BUNDLE = "org.apache.sling.scripting.bundle.tracker.internal.BundledScriptTracker.registering_bundle";
-    static final String AT_VERSION = "version";
-    static final String AT_SCRIPT_ENGINE = "scriptEngine";
-    static final String AT_SCRIPT_EXTENSION = "scriptExtension";
-    static final String AT_EXTENDS = "extends";
+    public static final String NS_SLING_SERVLET = "sling.servlet";
+    public static final String AT_VERSION = "version";
+    public static final String AT_SCRIPT_ENGINE = "scriptEngine";
+    public static final String AT_SCRIPT_EXTENSION = "scriptExtension";
+    public static final String AT_EXTENDS = "extends";
 
     @Reference
     private BundledScriptFinder bundledScriptFinder;
@@ -125,61 +127,64 @@ public class BundledScriptTracker implements BundleTrackerCustomizer<List<Servic
                     Hashtable<String, Object> properties = new Hashtable<>();
                     properties.put(ServletResolverConstants.SLING_SERVLET_NAME, BundledScriptServlet.class.getName());
                     properties.put(Constants.SERVICE_DESCRIPTION, BundledScriptServlet.class.getName() + cap.getAttributes());
-                    ServletCapability servletCapability = ServletCapability.fromBundleCapability(cap);
+                    BundledRenderUnitCapability bundledRenderUnitCapability = BundledRenderUnitCapabilityImpl.fromBundleCapability(cap);
                     Executable executable = null;
-                    TypeProvider baseTypeProvider = new TypeProvider(servletCapability, bundle);
+                    TypeProvider baseTypeProvider = new TypeProviderImpl(bundledRenderUnitCapability, bundle);
                     LinkedHashSet<TypeProvider> wiredProviders = new LinkedHashSet<>();
                     wiredProviders.add(baseTypeProvider);
-                    if (!servletCapability.getResourceTypes().isEmpty()) {
-                        String[] resourceTypesRegistrationValue = new String[servletCapability.getResourceTypes().size()];
+                    if (!bundledRenderUnitCapability.getResourceTypes().isEmpty()) {
+                        String[] resourceTypesRegistrationValue = new String[bundledRenderUnitCapability.getResourceTypes().size()];
                         int rtIndex = 0;
-                        for (ResourceType resourceType : servletCapability.getResourceTypes()) {
+                        for (ResourceType resourceType : bundledRenderUnitCapability.getResourceTypes()) {
                             resourceTypesRegistrationValue[rtIndex++] = resourceType.toString();
                         }
                         properties.put(ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES, resourceTypesRegistrationValue);
 
-                        String extension = servletCapability.getExtension();
+                        String extension = bundledRenderUnitCapability.getExtension();
                         if (StringUtils.isEmpty(extension)) {
                             extension = "html";
                         }
                         properties.put(ServletResolverConstants.SLING_SERVLET_EXTENSIONS, extension);
 
-                        if (!servletCapability.getSelectors().isEmpty()) {
-                            properties.put(ServletResolverConstants.SLING_SERVLET_SELECTORS, servletCapability.getSelectors().toArray());
+                        if (!bundledRenderUnitCapability.getSelectors().isEmpty()) {
+                            properties.put(ServletResolverConstants.SLING_SERVLET_SELECTORS, bundledRenderUnitCapability.getSelectors().toArray());
                         }
 
-                        if (StringUtils.isNotEmpty(servletCapability.getMethod())) {
-                            properties.put(ServletResolverConstants.SLING_SERVLET_METHODS, servletCapability.getMethod());
+                        if (StringUtils.isNotEmpty(bundledRenderUnitCapability.getMethod())) {
+                            properties.put(ServletResolverConstants.SLING_SERVLET_METHODS, bundledRenderUnitCapability.getMethod());
                         }
 
-                        String extendedResourceTypeString = servletCapability.getExtendedResourceType();
+                        String extendedResourceTypeString = bundledRenderUnitCapability.getExtendedResourceType();
                         if (StringUtils.isNotEmpty(extendedResourceTypeString)) {
-                            collectProvidersChain(wiredProviders, bundleWiring, extendedResourceTypeString);
-                            wiredProviders.stream().filter(typeProvider -> typeProvider.getServletCapability().getResourceTypes().stream()
+                            collectInheritanceChain(wiredProviders, bundleWiring, extendedResourceTypeString);
+                            wiredProviders.stream().filter(typeProvider -> typeProvider.getBundledRenderUnitCapability().getResourceTypes().stream()
                                     .anyMatch(resourceType -> resourceType.getType().equals(extendedResourceTypeString))).findFirst()
                                     .ifPresent(typeProvider -> {
-                                        for (ResourceType type : typeProvider.getServletCapability().getResourceTypes()) {
+                                        for (ResourceType type : typeProvider.getBundledRenderUnitCapability().getResourceTypes()) {
                                             if (type.getType().equals(extendedResourceTypeString)) {
                                                 properties.put(ServletResolverConstants.SLING_SERVLET_RESOURCE_SUPER_TYPE, type.toString());
                                             }
                                         }
                                     });
                         }
+                        collectRequiresChain(wiredProviders, bundleWiring);
                         executable = bundledScriptFinder.getScript(wiredProviders);
-                    } else if (StringUtils.isNotEmpty(servletCapability.getPath()) && StringUtils.isNotEmpty(servletCapability.getScriptEngineName())) {
+                    } else if (StringUtils.isNotEmpty(bundledRenderUnitCapability.getPath()) && StringUtils.isNotEmpty(
+                            bundledRenderUnitCapability.getScriptEngineName())) {
+                        collectRequiresChain(wiredProviders, bundleWiring);
                         executable = bundledScriptFinder.getScript(baseTypeProvider.getBundle(), baseTypeProvider.isPrecompiled(),
-                                servletCapability.getPath(), servletCapability.getScriptEngineName());
+                                bundledRenderUnitCapability.getPath(), bundledRenderUnitCapability.getScriptEngineName(), wiredProviders);
                     }
                     List<ServiceRegistration<Servlet>> regs = new ArrayList<>();
 
                     if (executable != null) {
                         Executable finalExecutable = executable;
-                        servletCapability.getResourceTypes().forEach(resourceType -> {
+                        bundledRenderUnitCapability.getResourceTypes().forEach(resourceType -> {
                             if (finalExecutable.getPath().startsWith(resourceType.toString() + "/")) {
                                 properties.put(ServletResolverConstants.SLING_SERVLET_PATHS, finalExecutable.getPath());
                             }
                         });
-                        if (executable.getPath().equals(servletCapability.getPath())) {
+                        if (executable.getPath().equals(bundledRenderUnitCapability.getPath())) {
                             properties.put(ServletResolverConstants.SLING_SERVLET_PATHS, executable.getPath());
                         }
                         properties.put(BundledHooks.class.getName(), "true");
@@ -386,22 +391,32 @@ public class BundledScriptTracker implements BundleTrackerCustomizer<List<Servic
         return resourceTypes;
     }
 
-    private void collectProvidersChain(@NotNull Set<TypeProvider> providers, @NotNull BundleWiring wiring,
-                                       @NotNull String extendedResourceType) {
+    private void collectInheritanceChain(@NotNull Set<TypeProvider> providers, @NotNull BundleWiring wiring,
+                                         @NotNull String extendedResourceType) {
         for (BundleWire wire : wiring.getRequiredWires(NS_SLING_SERVLET)) {
-            ServletCapability wiredCapability = ServletCapability.fromBundleCapability(wire.getCapability());
+            BundledRenderUnitCapability wiredCapability = BundledRenderUnitCapabilityImpl.fromBundleCapability(wire.getCapability());
             if (wiredCapability.getSelectors().isEmpty()) {
                 for (ResourceType resourceType : wiredCapability.getResourceTypes()) {
                     if (extendedResourceType.equals(resourceType.getType())) {
                         Bundle providingBundle = wire.getProvider().getBundle();
-                        providers.add(new TypeProvider(wiredCapability, providingBundle));
+                        providers.add(new TypeProviderImpl(wiredCapability, providingBundle));
                         String wiredExtends = wiredCapability.getExtendedResourceType();
                         if (StringUtils.isNotEmpty(wiredExtends)) {
-                            collectProvidersChain(providers, wire.getProviderWiring(), wiredExtends);
+                            collectInheritanceChain(providers, wire.getProviderWiring(), wiredExtends);
                         }
                     }
                 }
             }
         }
     }
+
+    private void collectRequiresChain(@NotNull Set<TypeProvider> providers, @NotNull BundleWiring wiring) {
+        for (BundleWire wire : wiring.getRequiredWires(NS_SLING_SERVLET)) {
+            BundledRenderUnitCapability wiredCapability = BundledRenderUnitCapabilityImpl.fromBundleCapability(wire.getCapability());
+            if (wiredCapability.getSelectors().isEmpty()) {
+                Bundle providingBundle = wire.getProvider().getBundle();
+                providers.add(new TypeProviderImpl(wiredCapability, providingBundle));
+            }
+        }
+    }
 }
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/PrecompiledScript.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/PrecompiledScript.java
index 565e3ce..19d0525 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/PrecompiledScript.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/PrecompiledScript.java
@@ -19,12 +19,14 @@
 package org.apache.sling.scripting.bundle.tracker.internal;
 
 import java.io.StringReader;
+import java.util.Set;
 
 import javax.script.ScriptContext;
 import javax.script.ScriptEngine;
 import javax.script.ScriptException;
 
 import org.apache.commons.lang3.StringUtils;
+import org.apache.sling.scripting.bundle.tracker.TypeProvider;
 import org.jetbrains.annotations.NotNull;
 import org.osgi.framework.Bundle;
 
@@ -34,8 +36,9 @@ public class PrecompiledScript extends AbstractBundledRenderUnit {
     private final Class<?> clazz;
     private volatile Object instance;
 
-    PrecompiledScript(@NotNull Bundle bundle, @NotNull String path, @NotNull Class<?> clazz, @NotNull String scriptEngineName) {
-        super(bundle, path, scriptEngineName);
+    PrecompiledScript(@NotNull Set<TypeProvider> providers, @NotNull Bundle bundle, @NotNull String path, @NotNull Class<?> clazz,
+                      @NotNull String scriptEngineName) {
+        super(providers, bundle, path, scriptEngineName);
         this.clazz = clazz;
     }
 
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/Script.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/Script.java
index ed20fbc..c541e59 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/Script.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/Script.java
@@ -22,6 +22,7 @@ import java.io.IOException;
 import java.io.StringReader;
 import java.net.URL;
 import java.nio.charset.StandardCharsets;
+import java.util.Set;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 
@@ -32,6 +33,7 @@ import javax.script.ScriptEngine;
 import javax.script.ScriptException;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.sling.scripting.bundle.tracker.TypeProvider;
 import org.apache.sling.scripting.core.ScriptNameAwareReader;
 import org.jetbrains.annotations.NotNull;
 import org.osgi.framework.Bundle;
@@ -45,8 +47,9 @@ class Script extends AbstractBundledRenderUnit {
     private Lock readLock = new ReentrantLock();
 
 
-    Script(@NotNull Bundle bundle, @NotNull String path, @NotNull URL url, @NotNull String scriptEngineName) {
-        super(bundle, path, scriptEngineName);
+    Script(@NotNull Set<TypeProvider> providers, @NotNull Bundle bundle, @NotNull String path, @NotNull URL url,
+           @NotNull String scriptEngineName) {
+        super(providers, bundle, path, scriptEngineName);
         this.url = url;
     }
 
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/TypeProvider.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/TypeProviderImpl.java
similarity index 57%
rename from src/main/java/org/apache/sling/scripting/bundle/tracker/internal/TypeProvider.java
rename to src/main/java/org/apache/sling/scripting/bundle/tracker/internal/TypeProviderImpl.java
index ee6c643..27fb136 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/TypeProvider.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/TypeProviderImpl.java
@@ -20,59 +20,42 @@ package org.apache.sling.scripting.bundle.tracker.internal;
 
 import java.util.Objects;
 
+import org.apache.sling.scripting.bundle.tracker.BundledRenderUnitCapability;
+import org.jetbrains.annotations.NotNull;
 import org.osgi.framework.Bundle;
 
-/**
- * A {@code TypeProvider} keeps an association between a versioned resource type and the bundle that provides it.
- */
-public class TypeProvider {
+class TypeProviderImpl implements org.apache.sling.scripting.bundle.tracker.TypeProvider {
 
-    private final ServletCapability servletCapability;
+    private final BundledRenderUnitCapability bundledRenderUnitCapability;
     private final Bundle bundle;
     private final boolean precompiled;
 
-    /**
-     * Builds a {@code TypeProvider}.
-     *
-     * @param servletCapability  the resource type capability
-     * @param bundle the bundle that provides the resource type
-     */
-    TypeProvider(ServletCapability servletCapability, Bundle bundle) {
-        this.servletCapability = servletCapability;
+    TypeProviderImpl(BundledRenderUnitCapability bundledRenderUnitCapability, Bundle bundle) {
+        this.bundledRenderUnitCapability = bundledRenderUnitCapability;
         this.bundle = bundle;
         precompiled = Boolean.parseBoolean(bundle.getHeaders().get("Sling-ResourceType-Precompiled"));
     }
 
-    /**
-     * Returns the resource type capabilities.
-     *
-     * @return the resource type capabilities
-     */
-    ServletCapability getServletCapability() {
-        return servletCapability;
+    @NotNull
+    @Override
+    public BundledRenderUnitCapability getBundledRenderUnitCapability() {
+        return bundledRenderUnitCapability;
     }
 
-    /**
-     * Returns the providing bundle.
-     *
-     * @return the providing bundle
-     */
-    Bundle getBundle() {
+    @NotNull
+    @Override
+    public Bundle getBundle() {
         return bundle;
     }
 
-    /**
-     * Returns {@code true} if the bundle provides precompiled scripts.
-     *
-     * @return {@code true} if the bundle provides precompiled scripts, {@code false} otherwise
-     */
+    @Override
     public boolean isPrecompiled() {
         return precompiled;
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(bundle, servletCapability, precompiled);
+        return Objects.hash(bundle, bundledRenderUnitCapability, precompiled);
     }
 
     @Override
@@ -80,9 +63,9 @@ public class TypeProvider {
         if (this == obj) {
             return true;
         }
-        if (obj instanceof TypeProvider) {
-            TypeProvider other = (TypeProvider) obj;
-            return Objects.equals(bundle, other.bundle) && Objects.equals(servletCapability, other.servletCapability) &&
+        if (obj instanceof TypeProviderImpl) {
+            TypeProviderImpl other = (TypeProviderImpl) obj;
+            return Objects.equals(bundle, other.bundle) && Objects.equals(bundledRenderUnitCapability, other.bundledRenderUnitCapability) &&
                     Objects.equals(precompiled, other.precompiled);
         }
         return false;
@@ -90,7 +73,7 @@ public class TypeProvider {
 
     @Override
     public String toString() {
-        return String.format("TypeProvider{ resourceTypeCapability=%s; bundle=%s; precompiled=%s }", servletCapability,
+        return String.format("TypeProvider{ bundledRenderUnitCapability=%s; bundle=%s; precompiled=%s }", bundledRenderUnitCapability,
                 bundle.getSymbolicName(), precompiled);
     }
 }
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/package-info.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/package-info.java
index 3f59450..66d51bb 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/package-info.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/package-info.java
@@ -16,7 +16,7 @@
  ~ specific language governing permissions and limitations
  ~ under the License.
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-@Version("0.1.0")
+@Version("0.2.0")
 package org.apache.sling.scripting.bundle.tracker;
 
 import org.osgi.annotation.versioning.Version;