You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by pa...@apache.org on 2020/04/29 19:50:40 UTC

[sling-org-apache-sling-scripting-core] branch issues/SLING-9406 updated: SLING-9406: Add bundled script support to the servlets resolver

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

pauls pushed a commit to branch issues/SLING-9406
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-core.git


The following commit(s) were added to refs/heads/issues/SLING-9406 by this push:
     new 276d5c8  SLING-9406: Add bundled script support to the servlets resolver
276d5c8 is described below

commit 276d5c8299009f5693046c3ae6f2e40b302543ce
Author: Karl Pauls <ka...@gmail.com>
AuthorDate: Wed Apr 29 21:50:24 2020 +0200

    SLING-9406: Add bundled script support to the servlets resolver
---
 pom.xml                                            |   4 +-
 .../tracker/BundledRenderUnitCapability.java       |  91 -----
 .../scripting/bundle/tracker/ResourceType.java     | 161 --------
 .../scripting/bundle/tracker/TypeProvider.java     |  45 ---
 .../bundle/tracker/internal/BundledHooks.java      |  57 ---
 .../internal/BundledRenderUnitCapabilityImpl.java  | 159 --------
 .../tracker/internal/BundledScriptServlet.java     |  92 -----
 .../tracker/internal/BundledScriptTracker.java     | 429 ---------------------
 .../bundle/tracker/internal/TypeProviderImpl.java  |  70 ----
 .../tracker/internal/request/OnDemandReader.java   |  97 -----
 .../tracker/internal/request/OnDemandWriter.java   | 103 -----
 .../tracker/internal/request/RequestWrapper.java   |  94 -----
 .../tracker/internal/request/ResponseWrapper.java  |  50 ---
 .../scripting/bundle/tracker/package-info.java     |  22 --
 .../tracker => core}/BundledRenderUnit.java        |   3 +-
 .../impl/bundled}/AbstractBundledRenderUnit.java   |   6 +-
 .../impl/bundled/BundleScriptFinderImpl.java}      |  79 ++--
 .../impl/bundled}/BundledScriptContext.java        |   2 +-
 .../impl/bundled/ExecutableUnit.java}              |   8 +-
 .../core/impl/bundled/ExecutableWrapper.java       |  58 +++
 .../internal => core/impl/bundled}/LogWriter.java  |   2 +-
 .../impl/bundled}/PrecompiledScript.java           |   4 +-
 .../impl/bundled}/ProtectedBindings.java           |   2 +-
 .../internal => core/impl/bundled}/Script.java     |   4 +-
 .../impl/bundled}/ScriptContextProvider.java       |  10 +-
 .../apache/sling/scripting/core/package-info.java  |   2 +-
 .../scripting/bundle/tracker/ResourceTypeTest.java |  87 -----
 .../bundle/tracker/internal/BundledHooksTest.java  | 130 -------
 .../tracker/internal/BundledScriptTrackerTest.java |  47 ---
 .../impl/bundled}/BundledScriptContextTest.java    |   3 +-
 .../impl/bundled}/LogWriterTest.java               |   3 +-
 .../impl/bundled}/ProtectedBindingsTest.java       |   3 +-
 .../core/it/ScriptingCoreTestSupport.java          |   1 +
 33 files changed, 130 insertions(+), 1798 deletions(-)

diff --git a/pom.xml b/pom.xml
index 56f4789..2af7831 100644
--- a/pom.xml
+++ b/pom.xml
@@ -341,8 +341,8 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.servlets.resolver</artifactId>
-            <version>2.6.4</version>
-            <scope>test</scope>
+            <version>2.6.5-SNAPSHOT</version>
+            <scope>provided</scope>
         </dependency>
     </dependencies>
 </project>
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
deleted file mode 100644
index dbda3d6..0000000
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/BundledRenderUnitCapability.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ~ 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/ResourceType.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/ResourceType.java
deleted file mode 100644
index b1399f1..0000000
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/ResourceType.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ~ 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.Objects;
-import java.util.regex.Pattern;
-
-import org.apache.commons.lang3.StringUtils;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.osgi.framework.Version;
-
-/**
- * The {@code ResourceTypeParser} provides methods for parsing resource type strings.
- *
- * <p>The following patterns are supported:</p>
- * <ol>
- * <li><tt>a/b/c</tt> - path-based</li>
- * <li><tt>a/b/c/1.0.0</tt> - path-based, versioned</li>
- * <li><tt>a.b.c</tt> - Java package name</li>
- * <li><tt>a.b.c/1.0.0</tt> - Java package name, versioned</li>
- * <li><tt>a</tt> - flat (sub-set of path-based)</li>
- * </ol>
- */
-public final class ResourceType {
-
-    private static final Pattern versionPattern = Pattern.compile("[\\d\\.]+(-.*)*$");
-
-    private final String type;
-    private final String version;
-    private final String resourceLabel;
-    private final String toString;
-
-    private ResourceType(@NotNull String type, @Nullable String version) {
-        this.type = type;
-        this.version = version;
-        if (type.lastIndexOf('/') != -1) {
-            resourceLabel = type.substring(type.lastIndexOf('/') + 1);
-        } else if (type.lastIndexOf('.') != -1) {
-            resourceLabel = type.substring(type.lastIndexOf('.') + 1);
-        } else {
-            resourceLabel = type;
-        }
-        toString = type + (version == null ? "" : "/" + version);
-    }
-
-    /**
-     * Returns a resource type's label. The label is important for script selection, since it will provide the name of the main script
-     * for this resource type. For more details check the Apache Sling
-     * <a href="https://sling.apache.org/documentation/the-sling-engine/url-to-script-resolution.html#scripts-for-get-requests">URL to
-     * Script Resolution</a> page
-     *
-     * @return the resource type label
-     */
-    @NotNull
-    public String getResourceLabel() {
-        return resourceLabel;
-    }
-
-    /**
-     * Returns the resource type string, without any version information.
-     *
-     * @return the resource type string
-     */
-    @NotNull
-    public String getType() {
-        return type;
-    }
-
-    /**
-     * Returns the version, if available.
-     *
-     * @return the version, if available; {@code null} otherwise
-     */
-    @Nullable
-    public String getVersion() {
-        return version;
-    }
-
-    @Override
-    public String toString() {
-        return toString;
-    }
-
-    /**
-     * Given a {@code resourceTypeString}, this method will extract a {@link ResourceType} object.
-     * <p>The accepted patterns are:</p>
-     * <ol>
-     * <li><tt>a/b/c</tt> - path-based</li>
-     * <li><tt>a/b/c/1.0.0</tt> - path-based, versioned</li>
-     * <li><tt>a.b.c</tt> - Java package name</li>
-     * <li><tt>a.b.c/1.0.0</tt> - Java package name, versioned</li>
-     * <li><tt>a</tt> - flat (sub-set of path-based)</li>
-     * </ol>
-     *
-     * @param resourceTypeString the resource type string to parse
-     * @return a {@link ResourceType} object
-     * @throws IllegalArgumentException if the {@code resourceTypeString} cannot be parsed
-     */
-    @NotNull
-    public static ResourceType parseResourceType(@NotNull String resourceTypeString) {
-        String type = StringUtils.EMPTY;
-        String version = null;
-        if (StringUtils.isNotEmpty(resourceTypeString)) {
-            int lastSlash = resourceTypeString.lastIndexOf('/');
-            if (lastSlash != -1 && !resourceTypeString.endsWith("/")) {
-                String versionString = resourceTypeString.substring(lastSlash + 1);
-                if (versionPattern.matcher(versionString).matches()) {
-                    try {
-                        version = Version.parseVersion(versionString).toString();
-                        type = resourceTypeString.substring(0, lastSlash);
-                    } catch (IllegalArgumentException e) {
-                        type = resourceTypeString;
-                    }
-                } else {
-                    type = resourceTypeString;
-                }
-            } else {
-                type = resourceTypeString;
-            }
-        }
-        if (StringUtils.isEmpty(type)) {
-            throw new IllegalArgumentException(String.format("Cannot extract a type for the resourceTypeString %s.", resourceTypeString));
-        }
-        return new ResourceType(type, version);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(type, version, resourceLabel);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj instanceof ResourceType) {
-            ResourceType other = (ResourceType) obj;
-            return Objects.equals(type, other.type) && Objects.equals(version, other.version) && Objects.equals(resourceLabel,
-                    other.resourceLabel);
-        }
-        return false;
-    }
-}
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/TypeProvider.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/TypeProvider.java
deleted file mode 100644
index f508c52..0000000
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/TypeProvider.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ~ 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 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();
-
-}
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledHooks.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledHooks.java
deleted file mode 100644
index 371df4b..0000000
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledHooks.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ~ 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.internal;
-
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.Map;
-
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceEvent;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.hooks.service.EventListenerHook;
-import org.osgi.framework.hooks.service.FindHook;
-import org.osgi.framework.hooks.service.ListenerHook;
-import org.osgi.service.component.annotations.Component;
-
-@Component
-public class BundledHooks implements FindHook, EventListenerHook {
-    @Override
-    public void find(BundleContext context, String name, String filter, boolean allServices, Collection<ServiceReference<?>> references) {
-        if (!context.getBundle().getSymbolicName().equals("org.apache.sling.servlets.resolver")) {
-            for (Iterator<ServiceReference<?>> iter = references.iterator(); iter.hasNext();) {
-                if (iter.next().getProperty(BundledHooks.class.getName()) != null) {
-                    iter.remove();
-                }
-            }
-        }
-    }
-
-
-    @Override
-    public void event(ServiceEvent event, Map<BundleContext, Collection<ListenerHook.ListenerInfo>> listeners) {
-        if (event.getServiceReference().getProperty(BundledHooks.class.getName()) != null) {
-            for (Iterator<Map.Entry<BundleContext, Collection<ListenerHook.ListenerInfo>>> entries = listeners.entrySet().iterator(); entries.hasNext();) {
-                if (!entries.next().getKey().getBundle().getSymbolicName().equals("org.apache.sling.servlets.resolver")) {
-                    entries.remove();
-                }
-            }
-        }
-    }
-}
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledRenderUnitCapabilityImpl.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledRenderUnitCapabilityImpl.java
deleted file mode 100644
index 469f1e5..0000000
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledRenderUnitCapabilityImpl.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ~ 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.internal;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-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 BundledRenderUnitCapabilityImpl  implements BundledRenderUnitCapability {
-
-    private final Set<ResourceType> resourceTypes;
-    private final String path;
-    private final List<String> selectors;
-    private final String extension;
-    private final String method;
-    private final String extendedResourceType;
-    private final String scriptEngineName;
-    private final 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;
-        this.extension = extension;
-        this.method = method;
-        this.extendedResourceType = extendedResourceType;
-        this.scriptEngineName = scriptEngineName;
-        this.scriptExtension = scriptExtension;
-    }
-
-    @Override
-    @NotNull
-    public Set<ResourceType> getResourceTypes() {
-        return Collections.unmodifiableSet(resourceTypes);
-    }
-
-    @Override
-    @Nullable
-    public String getPath() {
-        return path;
-    }
-
-    @Override
-    @NotNull
-    public List<String> getSelectors() {
-        return Collections.unmodifiableList(selectors);
-    }
-
-    @Override
-    @Nullable
-    public String getExtension() {
-        return extension;
-    }
-
-    @Override
-    @Nullable
-    public String getExtendedResourceType() {
-        return extendedResourceType;
-    }
-
-    @Override
-    @Nullable
-    public String getMethod() {
-        return method;
-    }
-
-    @Override
-    @Nullable
-    public String getScriptEngineName() {
-        return scriptEngineName;
-    }
-
-    @Override
-    @Nullable
-    public String getScriptExtension() {
-        return scriptExtension;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(resourceTypes, path, selectors, extension, method, extendedResourceType, scriptEngineName, scriptExtension);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        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;
-    }
-
-    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]);
-        Version version = (Version) attributes.get(BundledScriptTracker.AT_VERSION);
-        for (String rt : capabilityResourceTypes) {
-            if (version == null) {
-                resourceTypes.add(ResourceType.parseResourceType(rt));
-            } else {
-                resourceTypes.add(ResourceType.parseResourceType(rt + "/" + version.toString()));
-            }
-        }
-        return new BundledRenderUnitCapabilityImpl(
-                resourceTypes,
-                (String) attributes.get(ServletResolverConstants.SLING_SERVLET_PATHS),
-                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),
-                (String) attributes.get(BundledScriptTracker.AT_SCRIPT_ENGINE),
-                (String) attributes.get(BundledScriptTracker.AT_SCRIPT_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
deleted file mode 100644
index bfdb35e..0000000
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptServlet.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ~ 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.internal;
-
-import java.io.IOException;
-import java.util.Collection;
-import java.util.LinkedHashSet;
-import java.util.stream.Collectors;
-
-import javax.script.ScriptException;
-import javax.servlet.GenericServlet;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-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.apache.sling.scripting.bundle.tracker.internal.request.ResponseWrapper;
-import org.jetbrains.annotations.NotNull;
-
-class BundledScriptServlet extends GenericServlet {
-
-    private final ScriptContextProvider scriptContextProvider;
-    private final LinkedHashSet<TypeProvider> wiredTypeProviders;
-    private final Executable executable;
-
-
-    BundledScriptServlet(@NotNull ScriptContextProvider scriptContextProvider,
-                         @NotNull LinkedHashSet<TypeProvider> wiredTypeProviders,
-                         @NotNull Executable executable) {
-        this.scriptContextProvider = scriptContextProvider;
-        this.wiredTypeProviders = wiredTypeProviders;
-        this.executable = executable;
-    }
-
-    @Override
-    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
-        if ((req instanceof SlingHttpServletRequest) && (res instanceof SlingHttpServletResponse)) {
-            SlingHttpServletRequest request = (SlingHttpServletRequest) req;
-            SlingHttpServletResponse response = (SlingHttpServletResponse) res;
-
-            if (request.getAttribute(SlingConstants.ATTR_INCLUDE_SERVLET_PATH) == null) {
-                final String contentType = request.getResponseContentType();
-                if (contentType != null) {
-                    response.setContentType(contentType);
-                    if (contentType.startsWith("text/")) {
-                        response.setCharacterEncoding("UTF-8");
-                    }
-                }
-            }
-
-            RequestWrapper requestWrapper = new RequestWrapper(request,
-                    wiredTypeProviders.stream().map(typeProvider -> typeProvider.getBundledRenderUnitCapability().getResourceTypes()
-            ).flatMap(Collection::stream).collect(Collectors.toSet()));
-            ScriptContextProvider.ExecutableContext executableContext = scriptContextProvider
-                    .prepareScriptContext(requestWrapper, new ResponseWrapper(response), executable);
-            try {
-                executableContext.eval();
-            } catch (ScriptException se) {
-                Throwable cause = (se.getCause() == null) ? se : se.getCause();
-                throw new ServletException(String.format("Failed executing script %s: %s", executable.getName(), se.getMessage()), cause);
-            } finally {
-                executableContext.clean();
-            }
-        } else {
-            throw new ServletException("Not a Sling HTTP request/response");
-        }
-    }
-
-    public String toString() {
-        return getClass().getSimpleName() + "(" + executable.getName() + ")";
-    }
-}
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
deleted file mode 100644
index f23c9bd..0000000
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptTracker.java
+++ /dev/null
@@ -1,429 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ~ 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.internal;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.function.Supplier;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import javax.servlet.GenericServlet;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.Servlet;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.sling.api.SlingConstants;
-import org.apache.sling.api.SlingHttpServletRequest;
-import org.apache.sling.api.SlingHttpServletResponse;
-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;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleEvent;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
-import org.osgi.framework.Version;
-import org.osgi.framework.wiring.BundleCapability;
-import org.osgi.framework.wiring.BundleRevision;
-import org.osgi.framework.wiring.BundleWire;
-import org.osgi.framework.wiring.BundleWiring;
-import org.osgi.namespace.extender.ExtenderNamespace;
-import org.osgi.service.component.annotations.Activate;
-import org.osgi.service.component.annotations.Component;
-import org.osgi.service.component.annotations.Deactivate;
-import org.osgi.service.component.annotations.Reference;
-import org.osgi.util.tracker.BundleTracker;
-import org.osgi.util.tracker.BundleTrackerCustomizer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Component(
-        service = {}
-)
-@Capability(namespace = ExtenderNamespace.EXTENDER_NAMESPACE,
-            name = BundledScriptTracker.NS_SLING_SCRIPTING_EXTENDER,
-            version = "1.0.0")
-public class BundledScriptTracker implements BundleTrackerCustomizer<List<ServiceRegistration<Servlet>>> {
-    static final String NS_SLING_SCRIPTING_EXTENDER = "sling.scripting";
-
-    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";
-    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;
-
-    @Reference
-    private ScriptContextProvider scriptContextProvider;
-
-
-    private volatile BundleContext m_context;
-    private volatile BundleTracker<List<ServiceRegistration<Servlet>>> m_tracker;
-    private volatile Map<Set<String>, ServiceRegistration<Servlet>> m_dispatchers = new HashMap<>();
-
-    @Activate
-    protected void activate(BundleContext context) {
-        m_context = context;
-        m_tracker = new BundleTracker<>(context, Bundle.ACTIVE, this);
-        m_tracker.open();
-    }
-
-    @Deactivate
-    protected void deactivate() {
-        m_tracker.close();
-    }
-
-    @Override
-    public List<ServiceRegistration<Servlet>> addingBundle(Bundle bundle, BundleEvent event) {
-        BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);
-        if (bundleWiring.getRequiredWires("osgi.extender").stream().map(BundleWire::getProvider).map(BundleRevision::getBundle)
-                .anyMatch(m_context.getBundle()::equals)) {
-            LOGGER.debug("Inspecting bundle {} for {} capability.", bundle.getSymbolicName(), NS_SLING_SERVLET);
-            List<BundleCapability> capabilities = bundleWiring.getCapabilities(NS_SLING_SERVLET);
-            Set<TypeProvider> requiresChain = collectRequiresChain(bundleWiring);
-            if (!capabilities.isEmpty()) {
-                List<ServiceRegistration<Servlet>> serviceRegistrations = capabilities.stream().flatMap(cap ->
-                {
-                    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());
-                    BundledRenderUnitCapability bundledRenderUnitCapability = BundledRenderUnitCapabilityImpl.fromBundleCapability(cap);
-                    Executable executable = null;
-                    TypeProvider baseTypeProvider = new TypeProviderImpl(bundledRenderUnitCapability, bundle);
-                    LinkedHashSet<TypeProvider> inheritanceChain = new LinkedHashSet<>();
-                    inheritanceChain.add(baseTypeProvider);
-                    if (!bundledRenderUnitCapability.getResourceTypes().isEmpty()) {
-                        String[] resourceTypesRegistrationValue = new String[bundledRenderUnitCapability.getResourceTypes().size()];
-                        int rtIndex = 0;
-                        for (ResourceType resourceType : bundledRenderUnitCapability.getResourceTypes()) {
-                            resourceTypesRegistrationValue[rtIndex++] = resourceType.toString();
-                        }
-                        properties.put(ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES, resourceTypesRegistrationValue);
-
-                        String extension = bundledRenderUnitCapability.getExtension();
-                        if (StringUtils.isEmpty(extension)) {
-                            extension = "html";
-                        }
-                        properties.put(ServletResolverConstants.SLING_SERVLET_EXTENSIONS, extension);
-
-                        if (!bundledRenderUnitCapability.getSelectors().isEmpty()) {
-                            properties.put(ServletResolverConstants.SLING_SERVLET_SELECTORS, bundledRenderUnitCapability.getSelectors().toArray());
-                        }
-
-                        if (StringUtils.isNotEmpty(bundledRenderUnitCapability.getMethod())) {
-                            properties.put(ServletResolverConstants.SLING_SERVLET_METHODS, bundledRenderUnitCapability.getMethod());
-                        }
-
-                        String extendedResourceTypeString = bundledRenderUnitCapability.getExtendedResourceType();
-                        if (StringUtils.isNotEmpty(extendedResourceTypeString)) {
-                            collectInheritanceChain(inheritanceChain, bundleWiring, extendedResourceTypeString);
-                            inheritanceChain.stream().filter(typeProvider -> typeProvider.getBundledRenderUnitCapability().getResourceTypes().stream()
-                                    .anyMatch(resourceType -> resourceType.getType().equals(extendedResourceTypeString))).findFirst()
-                                    .ifPresent(typeProvider -> {
-                                        for (ResourceType type : typeProvider.getBundledRenderUnitCapability().getResourceTypes()) {
-                                            if (type.getType().equals(extendedResourceTypeString)) {
-                                                properties.put(ServletResolverConstants.SLING_SERVLET_RESOURCE_SUPER_TYPE, type.toString());
-                                            }
-                                        }
-                                    });
-                        }
-                        Set<TypeProvider> aggregate =
-                                Stream.concat(inheritanceChain.stream(), requiresChain.stream()).collect(Collectors.toCollection(LinkedHashSet::new));
-                        executable = bundledScriptFinder.getScript(inheritanceChain, aggregate);
-                    } else if (StringUtils.isNotEmpty(bundledRenderUnitCapability.getPath()) && StringUtils.isNotEmpty(
-                            bundledRenderUnitCapability.getScriptEngineName())) {
-                        Set<TypeProvider> aggregate =
-                                Stream.concat(inheritanceChain.stream(), requiresChain.stream()).collect(Collectors.toCollection(LinkedHashSet::new));
-                        executable = bundledScriptFinder.getScript(baseTypeProvider.getBundle(),
-                                bundledRenderUnitCapability.getPath(), bundledRenderUnitCapability.getScriptEngineName(), aggregate);
-                    }
-                    List<ServiceRegistration<Servlet>> regs = new ArrayList<>();
-
-                    if (executable != null) {
-                        Executable finalExecutable = executable;
-                        bundledRenderUnitCapability.getResourceTypes().forEach(resourceType -> {
-                            if (finalExecutable.getPath().startsWith(resourceType.toString() + "/")) {
-                                properties.put(ServletResolverConstants.SLING_SERVLET_PATHS, finalExecutable.getPath());
-                            }
-                        });
-                        if (executable.getPath().equals(bundledRenderUnitCapability.getPath())) {
-                            properties.put(ServletResolverConstants.SLING_SERVLET_PATHS, executable.getPath());
-                        }
-                        properties.put(BundledHooks.class.getName(), "true");
-                        regs.add(
-                                bundle.getBundleContext().registerService(
-                                        Servlet.class,
-                                        new BundledScriptServlet(scriptContextProvider, inheritanceChain, executable),
-                                        properties
-                                )
-                        );
-                    } else {
-                        LOGGER.error(String.format("Unable to locate an executable for capability %s.", cap));
-                    }
-
-                    return regs.stream();
-                }).collect(Collectors.toList());
-                refreshDispatcher(serviceRegistrations);
-                return serviceRegistrations;
-            } else {
-                return Collections.emptyList();
-            }
-        } else {
-            return Collections.emptyList();
-        }
-    }
-
-    private void refreshDispatcher(List<ServiceRegistration<Servlet>> regs) {
-        Map<Set<String>, ServiceRegistration<Servlet>> dispatchers = new HashMap<>();
-        Stream.concat(m_tracker.getTracked().values().stream(), Stream.of(regs)).flatMap(List::stream)
-            .filter(ref -> getResourceTypeVersion(ref.getReference()) != null)
-            .map(this::toProperties)
-            .collect(Collectors.groupingBy(BundledScriptTracker::getResourceTypes)).forEach((rt, propList) -> {
-            Hashtable<String, Object> properties = new Hashtable<>();
-            properties.put(ServletResolverConstants.SLING_SERVLET_NAME, DispatcherServlet.class.getName());
-            properties.put(ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES, rt.toArray());
-            Set<String> methods = propList.stream()
-                    .map(props -> props.getOrDefault(ServletResolverConstants.SLING_SERVLET_METHODS, new String[]{"GET", "HEAD"}))
-                    .map(PropertiesUtil::toStringArray).map(Arrays::asList).flatMap(List::stream).collect(Collectors.toSet());
-            Set<String> extensions = propList.stream().map(props -> props.getOrDefault(ServletResolverConstants
-                    .SLING_SERVLET_EXTENSIONS, new String[]{"html"})).map(PropertiesUtil::toStringArray).map(Arrays::asList).flatMap
-                    (List::stream).collect(Collectors.toSet());
-            properties.put(ServletResolverConstants.SLING_SERVLET_EXTENSIONS, extensions.toArray(new String[0]));
-            if (!methods.equals(new HashSet<>(Arrays.asList("GET", "HEAD")))) {
-                properties.put(ServletResolverConstants.SLING_SERVLET_METHODS, methods.toArray(new String[0]));
-            }
-            ServiceRegistration<Servlet> reg = m_dispatchers.remove(rt);
-            if (reg == null) {
-                Optional<BundleContext> registeringBundle = propList.stream().map(props -> {
-                    Bundle bundle = (Bundle) props.get(REGISTERING_BUNDLE);
-                    if (bundle != null) {
-                        return bundle.getBundleContext();
-                    }
-                    return null;
-                }).findFirst();
-                properties.put(Constants.SERVICE_DESCRIPTION,
-                        DispatcherServlet.class.getName() + "{" + ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES +
-                        "=" + rt + "; " +
-                        ServletResolverConstants.SLING_SERVLET_EXTENSIONS + "=" + extensions + "; " +
-                        ServletResolverConstants.SLING_SERVLET_METHODS + "=" + methods  + "}");
-                properties.put(BundledHooks.class.getName(), "true");
-
-                reg = registeringBundle.orElse(m_context).registerService(Servlet.class, new DispatcherServlet(rt), properties);
-            } else {
-                if (!new HashSet<>(Arrays.asList(PropertiesUtil
-                        .toStringArray(reg.getReference().getProperty(ServletResolverConstants.SLING_SERVLET_METHODS), new String[0])))
-                        .equals(methods)) {
-                    reg.setProperties(properties);
-                }
-            }
-            dispatchers.put(rt, reg);
-        });
-        m_dispatchers.values().forEach(ServiceRegistration::unregister);
-        m_dispatchers = dispatchers;
-    }
-
-    private Hashtable<String, Object> toProperties(ServiceRegistration<?> reg) {
-        Hashtable<String, Object> result = new Hashtable<>();
-        ServiceReference<?> ref = reg.getReference();
-
-        set(ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES, ref, result);
-        set(ServletResolverConstants.SLING_SERVLET_EXTENSIONS, ref, result);
-        set(ServletResolverConstants.SLING_SERVLET_SELECTORS, ref, result);
-        set(ServletResolverConstants.SLING_SERVLET_METHODS, ref, result);
-        result.put(REGISTERING_BUNDLE, reg.getReference().getBundle());
-
-        return result;
-    }
-
-    private void set(String key, ServiceReference<?> ref, Hashtable<String, Object> props) {
-        Object value = ref.getProperty(key);
-        if (value != null) {
-            props.put(key, value);
-        }
-    }
-
-    @Override
-    public void modifiedBundle(Bundle bundle, BundleEvent event, List<ServiceRegistration<Servlet>> regs) {
-        LOGGER.warn("Unexpected modified event {} for bundle {}.", event.toString(), bundle.toString());
-    }
-
-    @Override
-    public void removedBundle(Bundle bundle, BundleEvent event, List<ServiceRegistration<Servlet>> regs) {
-        LOGGER.debug("Bundle {} removed", bundle.getSymbolicName());
-        regs.forEach(ServiceRegistration::unregister);
-        refreshDispatcher(Collections.emptyList());
-    }
-
-    private class DispatcherServlet extends GenericServlet {
-        private final Set<String> m_rt;
-
-        DispatcherServlet(Set<String> rt) {
-            m_rt = rt;
-        }
-
-        @Override
-        public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
-
-            SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) req;
-
-            Optional<ServiceRegistration<Servlet>> target = m_tracker.getTracked().values().stream().flatMap(List::stream)
-                    .filter(
-                            reg -> !reg.getReference().getBundle().equals(m_context.getBundle())
-                    )
-                    .filter(reg -> getResourceTypeVersion(reg.getReference()) != null)
-                    .filter(reg ->
-                    {
-                        Hashtable<String, Object> props = toProperties(reg);
-                        return getResourceTypes(props).equals(m_rt) &&
-                                Arrays.asList(PropertiesUtil
-                                        .toStringArray(props.get(ServletResolverConstants.SLING_SERVLET_METHODS),
-                                                new String[]{"GET", "HEAD"}))
-                                        .contains(slingRequest.getMethod()) &&
-                                Arrays.asList(PropertiesUtil
-                                        .toStringArray(props.get(ServletResolverConstants.SLING_SERVLET_EXTENSIONS), new String[]{"html"}))
-                                        .contains(slingRequest.getRequestPathInfo().getExtension() == null ? "html" :
-                                                slingRequest.getRequestPathInfo().getExtension());
-                    }).min((left, right) ->
-                    {
-                        boolean la = Arrays.asList(PropertiesUtil
-                                .toStringArray(toProperties(left).get(ServletResolverConstants.SLING_SERVLET_SELECTORS), new String[0]))
-                                .containsAll(Arrays.asList(slingRequest.getRequestPathInfo().getSelectors()));
-                        boolean ra = Arrays.asList(PropertiesUtil
-                                .toStringArray(toProperties(right).get(ServletResolverConstants.SLING_SERVLET_SELECTORS), new String[0]))
-                                .containsAll(Arrays.asList(slingRequest.getRequestPathInfo().getSelectors()));
-                        if ((la && ra) || (!la && !ra)) {
-                            return new Version(getResourceTypeVersion(right.getReference()))
-                                    .compareTo(new Version(getResourceTypeVersion(left.getReference())));
-                        } else if (la) {
-                            return -1;
-                        } else {
-                            return 1;
-                        }
-
-                    });
-
-            if (target.isPresent()) {
-                String[] targetRT =
-                        PropertiesUtil.toStringArray(target.get().getReference().getProperty(ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES));
-                if (targetRT == null || targetRT.length == 0) {
-                    ((SlingHttpServletResponse) res).sendError(HttpServletResponse.SC_NOT_FOUND);
-                } else {
-                    String rt = targetRT[0];
-                    RequestDispatcherOptions options = new RequestDispatcherOptions();
-                    options.setForceResourceType(rt);
-
-                    RequestDispatcher dispatcher = slingRequest.getRequestDispatcher(slingRequest.getResource(), options);
-                    if (dispatcher != null) {
-                        if (slingRequest.getAttribute(SlingConstants.ATTR_INCLUDE_SERVLET_PATH) == null) {
-                            final String contentType = slingRequest.getResponseContentType();
-                            if (contentType != null) {
-                                res.setContentType(contentType);
-                                if (contentType.startsWith("text/")) {
-                                    res.setCharacterEncoding("UTF-8");
-                                }
-                            }
-                        }
-                        dispatcher.include(req, res);
-                    } else {
-                        ((SlingHttpServletResponse) res).sendError(HttpServletResponse.SC_NOT_FOUND);
-                    }
-                }
-            } else {
-                ((SlingHttpServletResponse) res).sendError(HttpServletResponse.SC_NOT_FOUND);
-            }
-        }
-    }
-
-    private static String getResourceTypeVersion(ServiceReference<?> ref) {
-        String[] values = PropertiesUtil.toStringArray(ref.getProperty(ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES));
-        if (values != null) {
-            String resourceTypeValue = values[0];
-            ResourceType resourceType = ResourceType.parseResourceType(resourceTypeValue);
-            return resourceType.getVersion();
-        }
-        return null;
-    }
-
-    private static Set<String> getResourceTypes(Hashtable<String, Object> props) {
-        Set<String> resourceTypes = new HashSet<>();
-        String[] values = PropertiesUtil.toStringArray(props.get(ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES));
-        for (String resourceTypeValue : values) {
-            resourceTypes.add(ResourceType.parseResourceType(resourceTypeValue).getType());
-        }
-        return resourceTypes;
-    }
-
-    private void collectInheritanceChain(@NotNull Set<TypeProvider> providers, @NotNull BundleWiring wiring,
-                                         @NotNull String extendedResourceType) {
-        for (BundleWire wire : wiring.getRequiredWires(NS_SLING_SERVLET)) {
-            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 TypeProviderImpl(wiredCapability, providingBundle));
-                        String wiredExtends = wiredCapability.getExtendedResourceType();
-                        if (StringUtils.isNotEmpty(wiredExtends)) {
-                            collectInheritanceChain(providers, wire.getProviderWiring(), wiredExtends);
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    private Set<TypeProvider> collectRequiresChain(@NotNull BundleWiring wiring) {
-        Set<TypeProvider> requiresChain = new LinkedHashSet<>();
-        for (BundleWire wire : wiring.getRequiredWires(NS_SLING_SERVLET)) {
-            BundledRenderUnitCapability wiredCapability = BundledRenderUnitCapabilityImpl.fromBundleCapability(wire.getCapability());
-            if (wiredCapability.getSelectors().isEmpty()) {
-                Bundle providingBundle = wire.getProvider().getBundle();
-                requiresChain.add(new TypeProviderImpl(wiredCapability, providingBundle));
-            }
-        }
-        return requiresChain;
-    }
-}
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/TypeProviderImpl.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/TypeProviderImpl.java
deleted file mode 100644
index fe04d66..0000000
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/TypeProviderImpl.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ~ 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.internal;
-
-import java.util.Objects;
-
-import org.apache.sling.scripting.bundle.tracker.BundledRenderUnitCapability;
-import org.jetbrains.annotations.NotNull;
-import org.osgi.framework.Bundle;
-
-class TypeProviderImpl implements org.apache.sling.scripting.bundle.tracker.TypeProvider {
-
-    private final BundledRenderUnitCapability bundledRenderUnitCapability;
-    private final Bundle bundle;
-
-    TypeProviderImpl(BundledRenderUnitCapability bundledRenderUnitCapability, Bundle bundle) {
-        this.bundledRenderUnitCapability = bundledRenderUnitCapability;
-        this.bundle = bundle;
-    }
-
-    @NotNull
-    @Override
-    public BundledRenderUnitCapability getBundledRenderUnitCapability() {
-        return bundledRenderUnitCapability;
-    }
-
-    @NotNull
-    @Override
-    public Bundle getBundle() {
-        return bundle;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(bundle, bundledRenderUnitCapability);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj instanceof TypeProviderImpl) {
-            TypeProviderImpl other = (TypeProviderImpl) obj;
-            return Objects.equals(bundle, other.bundle) && Objects.equals(bundledRenderUnitCapability, other.bundledRenderUnitCapability);
-        }
-        return false;
-    }
-
-    @Override
-    public String toString() {
-        return String.format("TypeProvider{ bundledRenderUnitCapability=%s; bundle=%s }", bundledRenderUnitCapability, bundle.getSymbolicName());
-    }
-}
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/request/OnDemandReader.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/request/OnDemandReader.java
deleted file mode 100644
index 7af2e7c..0000000
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/request/OnDemandReader.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ~ 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.internal.request;
-
-import java.io.IOException;
-import java.io.Reader;
-import java.nio.CharBuffer;
-
-import javax.servlet.ServletRequest;
-
-class OnDemandReader extends Reader {
-
-    private final ServletRequest request;
-
-    private Reader delegate;
-
-    OnDemandReader(ServletRequest request) {
-        this.request = request;
-    }
-
-    @Override
-    public void close() throws IOException {
-        if (delegate != null) {
-            delegate.close();
-        }
-    }
-
-    @Override
-    public void mark(int readAheadLimit) throws IOException {
-        getReader().mark(readAheadLimit);
-    }
-
-    @Override
-    public boolean markSupported() {
-        return (delegate != null) && delegate.markSupported();
-    }
-
-    @Override
-    public int read() throws IOException {
-        return getReader().read();
-    }
-
-    @Override
-    public int read(char[] cbuf, int off, int len) throws IOException {
-        return getReader().read(cbuf, off, len);
-    }
-
-    @Override
-    public int read(char[] cbuf) throws IOException {
-        return getReader().read(cbuf);
-    }
-
-    @Override
-    public int read(CharBuffer target) throws IOException {
-        return getReader().read(target);
-    }
-
-    @Override
-    public boolean ready() throws IOException {
-        return getReader().ready();
-    }
-
-    @Override
-    public void reset() throws IOException {
-        if (delegate != null) {
-            delegate.reset();
-        }
-    }
-
-    @Override
-    public long skip(long n) throws IOException {
-        return getReader().skip(n);
-    }
-
-    private Reader getReader() throws IOException {
-        if (delegate == null) {
-            delegate = request.getReader();
-        }
-        return delegate;
-    }
-}
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/request/OnDemandWriter.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/request/OnDemandWriter.java
deleted file mode 100644
index c26ebba..0000000
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/request/OnDemandWriter.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * 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.internal.request;
-
-import java.io.IOException;
-import java.io.Writer;
-
-import javax.servlet.ServletResponse;
-
-class OnDemandWriter extends Writer {
-
-    private final ServletResponse response;
-
-    private Writer delegate;
-
-    OnDemandWriter(ServletResponse response) {
-        this.response = response;
-    }
-
-    private Writer getWriter() throws IOException {
-        if (delegate == null) {
-            delegate = response.getWriter();
-        }
-
-        return delegate;
-    }
-
-    @Override
-    public void write(int c) throws IOException {
-        synchronized (lock) {
-            getWriter().write(c);
-        }
-    }
-
-    @Override
-    public void write(char[] cbuf) throws IOException {
-        synchronized (lock) {
-            getWriter().write(cbuf);
-        }
-    }
-
-    @Override
-    public void write(char[] cbuf, int off, int len) throws IOException {
-        synchronized (lock) {
-            getWriter().write(cbuf, off, len);
-        }
-    }
-
-    @Override
-    public void write(String str) throws IOException {
-        synchronized (lock) {
-            getWriter().write(str);
-        }
-    }
-
-    @Override
-    public void write(String str, int off, int len) throws IOException {
-        synchronized (lock) {
-            getWriter().write(str, off, len);
-        }
-    }
-
-    @Override
-    public void flush() throws IOException {
-        synchronized (lock) {
-            Writer writer = delegate;
-            if (writer != null) {
-                writer.flush();
-            }
-        }
-    }
-
-    @Override
-    public void close() throws IOException {
-        synchronized (lock) {
-            // flush and close the delegate if existing, otherwise ignore
-            Writer writer = delegate;
-            if (writer != null) {
-                writer.flush();
-                writer.close();
-
-                // drop the delegate now
-                delegate = null;
-            }
-        }
-    }
-}
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/request/RequestWrapper.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/request/RequestWrapper.java
deleted file mode 100644
index e80663a..0000000
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/request/RequestWrapper.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ~ 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.internal.request;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.util.Set;
-
-import javax.servlet.RequestDispatcher;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.sling.api.SlingHttpServletRequest;
-import org.apache.sling.api.request.RequestDispatcherOptions;
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.wrappers.SlingHttpServletRequestWrapper;
-import org.apache.sling.scripting.bundle.tracker.ResourceType;
-
-public class RequestWrapper extends SlingHttpServletRequestWrapper {
-
-    private final Set<ResourceType> wiredResourceTypes;
-    private BufferedReader reader;
-
-    public RequestWrapper(SlingHttpServletRequest wrappedRequest, Set<ResourceType> wiredResourceTypes) {
-        super(wrappedRequest);
-        this.wiredResourceTypes = wiredResourceTypes;
-    }
-
-    @Override
-    public RequestDispatcher getRequestDispatcher(Resource resource, RequestDispatcherOptions options) {
-        if (resource == null) {
-            return null;
-        }
-        if (options != null && StringUtils.isEmpty(options.getForceResourceType())) {
-            options.setForceResourceType(resource.getResourceType());
-        }
-        RequestDispatcherOptions processedOptions = processOptions(options);
-        return super.getRequestDispatcher(resource, processedOptions);
-    }
-
-    @Override
-    public RequestDispatcher getRequestDispatcher(String path, RequestDispatcherOptions options) {
-        if (path == null) {
-            return null;
-        }
-        RequestDispatcherOptions processedOptions = processOptions(options);
-        return super.getRequestDispatcher(path, processedOptions);
-    }
-
-    @Override
-    public BufferedReader getReader() {
-        if (reader == null) {
-            reader = new BufferedReader(new OnDemandReader(getRequest()));
-        }
-        return reader;
-    }
-
-    private RequestDispatcherOptions processOptions(RequestDispatcherOptions options) {
-        if (options != null) {
-            RequestDispatcherOptions requestDispatcherOptions = new RequestDispatcherOptions();
-            requestDispatcherOptions.setForceResourceType(options.getForceResourceType());
-            requestDispatcherOptions.setAddSelectors(options.getAddSelectors());
-            requestDispatcherOptions.setReplaceSelectors(options.getReplaceSelectors());
-            requestDispatcherOptions.setReplaceSuffix(options.getReplaceSuffix());
-            String forcedResourceType = options.getForceResourceType();
-            if (StringUtils.isNotEmpty(forcedResourceType)) {
-                for (ResourceType wiredResourceType : wiredResourceTypes) {
-                    String type = wiredResourceType.getType();
-                    if (type.equals(forcedResourceType)) {
-                        requestDispatcherOptions.setForceResourceType(wiredResourceType.toString());
-                        break;
-                    }
-                }
-            }
-            return requestDispatcherOptions;
-        }
-        return null;
-    }
-}
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/request/ResponseWrapper.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/request/ResponseWrapper.java
deleted file mode 100644
index 88714ef..0000000
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/request/ResponseWrapper.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ~ 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.internal.request;
-
-import java.io.PrintWriter;
-import java.util.concurrent.atomic.AtomicReference;
-
-import org.apache.sling.api.SlingHttpServletResponse;
-import org.apache.sling.api.wrappers.SlingHttpServletResponseWrapper;
-
-public class ResponseWrapper extends SlingHttpServletResponseWrapper {
-    private final AtomicReference<PrintWriter> writer = new AtomicReference<>();
-
-    /**
-     * Create a wrapper for the supplied wrappedRequest
-     *
-     * @param wrappedResponse The response
-     */
-    public ResponseWrapper(SlingHttpServletResponse wrappedResponse) {
-        super(wrappedResponse);
-    }
-
-    @Override
-    public PrintWriter getWriter() {
-        PrintWriter result = writer.get();
-        if (result == null) {
-            result = new PrintWriter(new OnDemandWriter(getResponse()));
-            if (!writer.compareAndSet(null, result)) {
-                result = writer.get();
-            }
-        }
-        return result;
-    }
-}
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
deleted file mode 100644
index 66d51bb..0000000
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/package-info.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ~ 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.
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-@Version("0.2.0")
-package org.apache.sling.scripting.bundle.tracker;
-
-import org.osgi.annotation.versioning.Version;
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/BundledRenderUnit.java b/src/main/java/org/apache/sling/scripting/core/BundledRenderUnit.java
similarity index 97%
rename from src/main/java/org/apache/sling/scripting/bundle/tracker/BundledRenderUnit.java
rename to src/main/java/org/apache/sling/scripting/core/BundledRenderUnit.java
index 3849a36..024104d 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/BundledRenderUnit.java
+++ b/src/main/java/org/apache/sling/scripting/core/BundledRenderUnit.java
@@ -16,10 +16,11 @@
  ~ specific language governing permissions and limitations
  ~ under the License.
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-package org.apache.sling.scripting.bundle.tracker;
+package org.apache.sling.scripting.core;
 
 import java.util.Set;
 
+import org.apache.sling.servlets.resolver.bundle.tracker.TypeProvider;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.osgi.annotation.versioning.ProviderType;
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/AbstractBundledRenderUnit.java b/src/main/java/org/apache/sling/scripting/core/impl/bundled/AbstractBundledRenderUnit.java
similarity index 96%
rename from src/main/java/org/apache/sling/scripting/bundle/tracker/internal/AbstractBundledRenderUnit.java
rename to src/main/java/org/apache/sling/scripting/core/impl/bundled/AbstractBundledRenderUnit.java
index 9362b32..fc87aae 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/AbstractBundledRenderUnit.java
+++ b/src/main/java/org/apache/sling/scripting/core/impl/bundled/AbstractBundledRenderUnit.java
@@ -16,7 +16,7 @@
  ~ specific language governing permissions and limitations
  ~ under the License.
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-package org.apache.sling.scripting.bundle.tracker.internal;
+package org.apache.sling.scripting.core.impl.bundled;
 
 import java.lang.reflect.Array;
 import java.util.ArrayList;
@@ -27,7 +27,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import org.apache.sling.scripting.bundle.tracker.TypeProvider;
+import org.apache.sling.servlets.resolver.bundle.tracker.TypeProvider;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.osgi.framework.Bundle;
@@ -36,7 +36,7 @@ import org.osgi.framework.ServiceReference;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-abstract class AbstractBundledRenderUnit implements Executable {
+abstract class AbstractBundledRenderUnit implements ExecutableUnit {
 
     private static final Logger LOG = LoggerFactory.getLogger(AbstractBundledRenderUnit.class.getName());
 
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java b/src/main/java/org/apache/sling/scripting/core/impl/bundled/BundleScriptFinderImpl.java
similarity index 58%
rename from src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java
rename to src/main/java/org/apache/sling/scripting/core/impl/bundled/BundleScriptFinderImpl.java
index f4f44e2..8b566bd 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java
+++ b/src/main/java/org/apache/sling/scripting/core/impl/bundled/BundleScriptFinderImpl.java
@@ -1,22 +1,22 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ~ 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.internal;
+/*******************************************************************************
+ * 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.core.impl.bundled;
 
 import java.net.URL;
 import java.util.ArrayList;
@@ -27,28 +27,31 @@ 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.apache.sling.servlets.resolver.bundle.tracker.BundledRenderUnitCapability;
+import org.apache.sling.servlets.resolver.bundle.tracker.BundledScriptFinder;
+import org.apache.sling.servlets.resolver.bundle.tracker.Executable;
+import org.apache.sling.servlets.resolver.bundle.tracker.ResourceType;
+import org.apache.sling.servlets.resolver.bundle.tracker.TypeProvider;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.osgi.framework.Bundle;
 import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
 
-@Component(
-        service = BundledScriptFinder.class
-)
-public class BundledScriptFinder {
+@Component
+public class BundleScriptFinderImpl implements BundledScriptFinder {
+    @Reference
+    ScriptContextProvider scriptContextProvider;
 
     private static final String NS_JAVAX_SCRIPT_CAPABILITY = "javax.script";
     private static final String SLASH = "/";
     private static final String DOT = ".";
 
-    Executable getScript(Set<TypeProvider> providers, Set<TypeProvider> allProviders) {
+    public Executable getScript(Set<TypeProvider> providers, Set<TypeProvider> allProviders) {
         for (TypeProvider provider : providers) {
             BundledRenderUnitCapability capability = provider.getBundledRenderUnitCapability();
             for (String match : buildScriptMatches(capability.getResourceTypes(),
-                    capability.getSelectors().toArray(new String[0]), capability.getMethod(), capability.getExtension())) {
+                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)) {
@@ -62,16 +65,16 @@ public class BundledScriptFinder {
         return null;
     }
 
-    Executable getScript(@NotNull Bundle bundle, @NotNull String path, @NotNull String scriptEngineName,
-                         @NotNull Set<TypeProvider> providers) {
+    public Executable getScript(@NotNull Bundle bundle, @NotNull String path, @NotNull String scriptEngineName,
+        @NotNull Set<TypeProvider> providers) {
         String className = JavaEscapeHelper.makeJavaPackage(path);
         try {
             Class<?> clazz = bundle.loadClass(className);
-            return new PrecompiledScript(providers, bundle, path, clazz, scriptEngineName);
+            return new ExecutableWrapper(scriptContextProvider, new PrecompiledScript(providers, bundle, path, clazz, scriptEngineName));
         } catch (ClassNotFoundException ignored) {
             URL bundledScriptURL = bundle.getEntry(NS_JAVAX_SCRIPT_CAPABILITY + (path.startsWith("/") ? "" : SLASH) + path);
             if (bundledScriptURL != null) {
-                return new Script(providers, bundle, path, bundledScriptURL, scriptEngineName);
+                return new ExecutableWrapper(scriptContextProvider, new Script(providers, bundle, path, bundledScriptURL, scriptEngineName));
             }    // do nothing here
         }
 
@@ -80,7 +83,7 @@ public class BundledScriptFinder {
 
     @Nullable
     private Executable getExecutable(@NotNull Bundle bundle, @NotNull String match, @NotNull String scriptEngineName,
-                                     @NotNull String scriptExtension, @NotNull Set<TypeProvider> providers) {
+        @NotNull String scriptExtension, @NotNull Set<TypeProvider> providers) {
         String path = match + DOT + scriptExtension;
         return getScript(bundle, path, scriptEngineName, providers);
     }
@@ -91,10 +94,10 @@ public class BundledScriptFinder {
             if (selectors.length > 0) {
                 for (int i = selectors.length - 1; i >= 0; i--) {
                     String base =
-                            resourceType.getType() +
-                                    (StringUtils.isNotEmpty(resourceType.getVersion()) ? SLASH + resourceType.getVersion() + SLASH :
-                                            SLASH) +
-                                    String.join(SLASH, Arrays.copyOf(selectors, i + 1));
+                        resourceType.getType() +
+                            (StringUtils.isNotEmpty(resourceType.getVersion()) ? SLASH + resourceType.getVersion() + SLASH :
+                                SLASH) +
+                            String.join(SLASH, Arrays.copyOf(selectors, i + 1));
                     if (StringUtils.isNotEmpty(extension)) {
                         if (StringUtils.isNotEmpty(method)) {
                             matches.add(base + DOT + extension + DOT + method);
@@ -108,7 +111,7 @@ public class BundledScriptFinder {
                 }
             }
             String base = resourceType.getType() +
-                    (StringUtils.isNotEmpty(resourceType.getVersion()) ? SLASH + resourceType.getVersion() : StringUtils.EMPTY);
+                (StringUtils.isNotEmpty(resourceType.getVersion()) ? SLASH + resourceType.getVersion() : StringUtils.EMPTY);
 
             if (StringUtils.isNotEmpty(extension)) {
                 if (StringUtils.isNotEmpty(method)) {
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptContext.java b/src/main/java/org/apache/sling/scripting/core/impl/bundled/BundledScriptContext.java
similarity index 98%
rename from src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptContext.java
rename to src/main/java/org/apache/sling/scripting/core/impl/bundled/BundledScriptContext.java
index 43c5fde..30d85be 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptContext.java
+++ b/src/main/java/org/apache/sling/scripting/core/impl/bundled/BundledScriptContext.java
@@ -16,7 +16,7 @@
  ~ specific language governing permissions and limitations
  ~ under the License.
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-package org.apache.sling.scripting.bundle.tracker.internal;
+package org.apache.sling.scripting.core.impl.bundled;
 
 import java.io.Reader;
 import java.io.Writer;
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/Executable.java b/src/main/java/org/apache/sling/scripting/core/impl/bundled/ExecutableUnit.java
similarity index 91%
rename from src/main/java/org/apache/sling/scripting/bundle/tracker/internal/Executable.java
rename to src/main/java/org/apache/sling/scripting/core/impl/bundled/ExecutableUnit.java
index 8797103..5d09e69 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/Executable.java
+++ b/src/main/java/org/apache/sling/scripting/core/impl/bundled/ExecutableUnit.java
@@ -16,16 +16,16 @@
  ~ specific language governing permissions and limitations
  ~ under the License.
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-package org.apache.sling.scripting.bundle.tracker.internal;
+package org.apache.sling.scripting.core.impl.bundled;
 
 import javax.script.ScriptContext;
 import javax.script.ScriptEngine;
 import javax.script.ScriptException;
 
-import org.apache.sling.scripting.bundle.tracker.BundledRenderUnit;
+import org.apache.sling.scripting.core.BundledRenderUnit;
 import org.jetbrains.annotations.NotNull;
 
-interface Executable extends BundledRenderUnit {
+interface ExecutableUnit extends BundledRenderUnit {
 
     /**
      * Releases all acquired dependencies which were retrieved through {@link #getService(String)} or {@link #getServices(String, String)}.
@@ -41,7 +41,7 @@ interface Executable extends BundledRenderUnit {
     String getPath();
 
     /**
-     * Returns the short name of the {@link ScriptEngine} with which {@code this Executable} can be evaluated.
+     * Returns the short name of the {@link ScriptEngine} with which {@code this ExecutableUnit} can be evaluated.
      *
      * @return the short name of the script engine
      * @see #eval(ScriptEngine, ScriptContext)
diff --git a/src/main/java/org/apache/sling/scripting/core/impl/bundled/ExecutableWrapper.java b/src/main/java/org/apache/sling/scripting/core/impl/bundled/ExecutableWrapper.java
new file mode 100644
index 0000000..593d55c
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/core/impl/bundled/ExecutableWrapper.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * 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.core.impl.bundled;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.scripting.core.impl.helper.OnDemandReaderRequest;
+import org.apache.sling.scripting.core.impl.helper.OnDemandWriterResponse;
+import org.apache.sling.servlets.resolver.bundle.tracker.Executable;
+import org.jetbrains.annotations.NotNull;
+
+class ExecutableWrapper implements Executable {
+    private final ScriptContextProvider scriptContextProvider;
+    private final ExecutableUnit executable;
+
+    ExecutableWrapper(ScriptContextProvider scriptContextProvider, ExecutableUnit executable) {
+        this.scriptContextProvider = scriptContextProvider;
+        this.executable = executable;
+    }
+
+    @Override
+    public @NotNull String getPath()
+    {
+        return this.executable.getPath();
+    }
+
+    @Override
+    public void eval(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response) throws Exception {
+        ScriptContextProvider.ExecutableContext executableContext = scriptContextProvider
+            .prepareScriptContext(new OnDemandReaderRequest((SlingHttpServletRequest) request),
+                new OnDemandWriterResponse((SlingHttpServletResponse) response), this.executable);
+        try {
+            executableContext.eval();
+        }
+        finally {
+            executableContext.clean();
+        }
+    }
+}
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/LogWriter.java b/src/main/java/org/apache/sling/scripting/core/impl/bundled/LogWriter.java
similarity index 98%
rename from src/main/java/org/apache/sling/scripting/bundle/tracker/internal/LogWriter.java
rename to src/main/java/org/apache/sling/scripting/core/impl/bundled/LogWriter.java
index 4988a2f..a55b450 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/LogWriter.java
+++ b/src/main/java/org/apache/sling/scripting/core/impl/bundled/LogWriter.java
@@ -16,7 +16,7 @@
  ~ specific language governing permissions and limitations
  ~ under the License.
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-package org.apache.sling.scripting.bundle.tracker.internal;
+package org.apache.sling.scripting.core.impl.bundled;
 
 import java.io.Writer;
 
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/PrecompiledScript.java b/src/main/java/org/apache/sling/scripting/core/impl/bundled/PrecompiledScript.java
similarity index 95%
rename from src/main/java/org/apache/sling/scripting/bundle/tracker/internal/PrecompiledScript.java
rename to src/main/java/org/apache/sling/scripting/core/impl/bundled/PrecompiledScript.java
index 980c640..6c45cba 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/PrecompiledScript.java
+++ b/src/main/java/org/apache/sling/scripting/core/impl/bundled/PrecompiledScript.java
@@ -16,7 +16,7 @@
  ~ specific language governing permissions and limitations
  ~ under the License.
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-package org.apache.sling.scripting.bundle.tracker.internal;
+package org.apache.sling.scripting.core.impl.bundled;
 
 import java.io.StringReader;
 import java.util.Set;
@@ -26,7 +26,7 @@ import javax.script.ScriptEngine;
 import javax.script.ScriptException;
 
 import org.apache.commons.lang3.StringUtils;
-import org.apache.sling.scripting.bundle.tracker.TypeProvider;
+import org.apache.sling.servlets.resolver.bundle.tracker.TypeProvider;
 import org.jetbrains.annotations.NotNull;
 import org.osgi.framework.Bundle;
 
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/ProtectedBindings.java b/src/main/java/org/apache/sling/scripting/core/impl/bundled/ProtectedBindings.java
similarity index 98%
rename from src/main/java/org/apache/sling/scripting/bundle/tracker/internal/ProtectedBindings.java
rename to src/main/java/org/apache/sling/scripting/core/impl/bundled/ProtectedBindings.java
index 3376b48..6328a13 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/ProtectedBindings.java
+++ b/src/main/java/org/apache/sling/scripting/core/impl/bundled/ProtectedBindings.java
@@ -16,7 +16,7 @@
  ~ specific language governing permissions and limitations
  ~ under the License.
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-package org.apache.sling.scripting.bundle.tracker.internal;
+package org.apache.sling.scripting.core.impl.bundled;
 
 import java.util.Collection;
 import java.util.Collections;
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/Script.java b/src/main/java/org/apache/sling/scripting/core/impl/bundled/Script.java
similarity index 96%
rename from src/main/java/org/apache/sling/scripting/bundle/tracker/internal/Script.java
rename to src/main/java/org/apache/sling/scripting/core/impl/bundled/Script.java
index bd274b3..b902cb8 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/Script.java
+++ b/src/main/java/org/apache/sling/scripting/core/impl/bundled/Script.java
@@ -16,7 +16,7 @@
  ~ specific language governing permissions and limitations
  ~ under the License.
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-package org.apache.sling.scripting.bundle.tracker.internal;
+package org.apache.sling.scripting.core.impl.bundled;
 
 import java.io.IOException;
 import java.io.StringReader;
@@ -33,7 +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.servlets.resolver.bundle.tracker.TypeProvider;
 import org.apache.sling.scripting.core.ScriptNameAwareReader;
 import org.jetbrains.annotations.NotNull;
 import org.osgi.framework.Bundle;
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/ScriptContextProvider.java b/src/main/java/org/apache/sling/scripting/core/impl/bundled/ScriptContextProvider.java
similarity index 94%
rename from src/main/java/org/apache/sling/scripting/bundle/tracker/internal/ScriptContextProvider.java
rename to src/main/java/org/apache/sling/scripting/core/impl/bundled/ScriptContextProvider.java
index caee87e..ba166b2 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/ScriptContextProvider.java
+++ b/src/main/java/org/apache/sling/scripting/core/impl/bundled/ScriptContextProvider.java
@@ -16,7 +16,7 @@
  ~ specific language governing permissions and limitations
  ~ under the License.
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-package org.apache.sling.scripting.bundle.tracker.internal;
+package org.apache.sling.scripting.core.impl.bundled;
 
 import java.io.IOException;
 import java.util.Arrays;
@@ -40,7 +40,7 @@ import org.apache.sling.api.scripting.SlingScriptConstants;
 import org.apache.sling.scripting.api.BindingsValuesProvider;
 import org.apache.sling.scripting.api.BindingsValuesProvidersByContext;
 import org.apache.sling.scripting.api.resource.ScriptingResourceResolverProvider;
-import org.apache.sling.scripting.bundle.tracker.BundledRenderUnit;
+import org.apache.sling.scripting.core.BundledRenderUnit;
 import org.apache.sling.scripting.core.ScriptHelper;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Reference;
@@ -74,7 +74,7 @@ public class ScriptContextProvider {
     @Reference
     private ScriptingResourceResolverProvider scriptingResourceResolverProvider;
 
-    ExecutableContext prepareScriptContext(SlingHttpServletRequest request, SlingHttpServletResponse response, Executable executable)
+    public ExecutableContext prepareScriptContext(SlingHttpServletRequest request, SlingHttpServletResponse response, ExecutableUnit executable)
             throws IOException {
         ScriptEngine scriptEngine = scriptEngineManager.getEngineByName(executable.getScriptEngineName());
         if (scriptEngine == null) {
@@ -117,10 +117,10 @@ public class ScriptContextProvider {
 
     static class ExecutableContext {
         private final ScriptContext scriptContext;
-        private final Executable executable;
+        private final ExecutableUnit executable;
         private final ScriptEngine scriptEngine;
 
-        private ExecutableContext(ScriptContext scriptContext, Executable executable, ScriptEngine scriptEngine) {
+        private ExecutableContext(ScriptContext scriptContext, ExecutableUnit executable, ScriptEngine scriptEngine) {
             this.scriptContext = scriptContext;
             this.executable = executable;
             this.scriptEngine = scriptEngine;
diff --git a/src/main/java/org/apache/sling/scripting/core/package-info.java b/src/main/java/org/apache/sling/scripting/core/package-info.java
index 77883c8..8fabe3f 100644
--- a/src/main/java/org/apache/sling/scripting/core/package-info.java
+++ b/src/main/java/org/apache/sling/scripting/core/package-info.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-@Version("2.1.0")
+@Version("2.2.0")
 package org.apache.sling.scripting.core;
 
 import org.osgi.annotation.versioning.Version;
diff --git a/src/test/java/org/apache/sling/scripting/bundle/tracker/ResourceTypeTest.java b/src/test/java/org/apache/sling/scripting/bundle/tracker/ResourceTypeTest.java
deleted file mode 100644
index 8f102e9..0000000
--- a/src/test/java/org/apache/sling/scripting/bundle/tracker/ResourceTypeTest.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ~ 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 org.apache.commons.lang3.StringUtils;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-
-public class ResourceTypeTest {
-
-    @Test
-    public void testSlashNoVersion() {
-        ResourceType t1 = ResourceType.parseResourceType("a/b/c");
-        assertEquals("a/b/c", t1.getType());
-        assertEquals("c", t1.getResourceLabel());
-        assertNull(t1.getVersion());
-    }
-
-    @Test
-    public void testSlashVersion() {
-        ResourceType t1 = ResourceType.parseResourceType("a/b/c/1.0.0");
-        assertEquals("a/b/c", t1.getType());
-        assertEquals("c", t1.getResourceLabel());
-        assertEquals("1.0.0", t1.getVersion());
-    }
-
-    @Test
-    public void testOneSegmentNoVersion() {
-        ResourceType t1 = ResourceType.parseResourceType("a");
-        assertEquals("a", t1.getType());
-        assertEquals("a", t1.getResourceLabel());
-        assertNull(t1.getVersion());
-    }
-
-    @Test
-    public void testOneSegmentVersion() {
-        ResourceType t1 = ResourceType.parseResourceType("a/1.2.3");
-        assertEquals("a", t1.getType());
-        assertEquals("a", t1.getResourceLabel());
-        assertEquals("1.2.3", t1.getVersion());
-    }
-
-    @Test
-    public void testDotNoVersion() {
-        ResourceType t1 = ResourceType.parseResourceType("a.b.c");
-        assertEquals("a.b.c", t1.getType());
-        assertEquals("c", t1.getResourceLabel());
-        assertNull(t1.getVersion());
-    }
-
-    @Test
-    public void testDotVersion() {
-        ResourceType t1 = ResourceType.parseResourceType("a.b.c/42.0.0");
-        assertEquals("a.b.c", t1.getType());
-        assertEquals("c", t1.getResourceLabel());
-        assertEquals("42.0.0", t1.getVersion());
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testEmptyString() {
-        ResourceType t1 = ResourceType.parseResourceType(StringUtils.EMPTY);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testNull() {
-        ResourceType t1 = ResourceType.parseResourceType(null);
-    }
-
-}
diff --git a/src/test/java/org/apache/sling/scripting/bundle/tracker/internal/BundledHooksTest.java b/src/test/java/org/apache/sling/scripting/bundle/tracker/internal/BundledHooksTest.java
deleted file mode 100644
index 1b974fb..0000000
--- a/src/test/java/org/apache/sling/scripting/bundle/tracker/internal/BundledHooksTest.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ~ 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.internal;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceEvent;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.hooks.service.ListenerHook;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class BundledHooksTest {
-    @Test
-    public void testFindHookFiltersOther() {
-        BundledHooks hooks = new BundledHooks();
-
-        BundleContext context = mock(BundleContext.class);
-        Bundle bundle = mock(Bundle.class);
-        ServiceReference<?> ref = mock(ServiceReference.class);
-
-        when(context.getBundle()).thenReturn(bundle);
-        when(bundle.getSymbolicName()).thenReturn("org.apache.sling.foo.bar");
-        when(ref.getProperty(BundledHooks.class.getName())).thenReturn("true");
-        List<ServiceReference<?>> services = new ArrayList<>();
-
-        services.add(ref);
-        hooks.find(context, null, null, true, services);
-
-        Assert.assertTrue(services.isEmpty());
-    }
-
-    @Test
-    public void testFindHookDoesNotFilterResolver() {
-        BundledHooks hooks = new BundledHooks();
-
-        BundleContext context = mock(BundleContext.class);
-        Bundle bundle = mock(Bundle.class);
-        ServiceReference<?> ref = mock(ServiceReference.class);
-
-        when(context.getBundle()).thenReturn(bundle);
-        when(bundle.getSymbolicName()).thenReturn("org.apache.sling.servlets.resolver");
-        when(ref.getProperty(BundledHooks.class.getName())).thenReturn("true");
-        List<ServiceReference<?>> services = new ArrayList<>();
-
-        services.add(ref);
-        hooks.find(context, null, null, true, services);
-
-        Assert.assertEquals(1, services.size());
-    }
-
-    @Test
-    public void testEventHookFiltersOther() {
-        BundledHooks hooks = new BundledHooks();
-
-        ServiceEvent event = mock(ServiceEvent.class);
-
-        BundleContext context = mock(BundleContext.class);
-        Bundle bundle = mock(Bundle.class);
-        ServiceReference ref = mock(ServiceReference.class);
-
-        when(event.getServiceReference()).thenReturn(ref);
-
-        when(context.getBundle()).thenReturn(bundle);
-        when(bundle.getSymbolicName()).thenReturn("org.apache.sling.foo.bar");
-        when(ref.getProperty(BundledHooks.class.getName())).thenReturn("true");
-
-        ListenerHook.ListenerInfo info = mock(ListenerHook.ListenerInfo.class);
-        when(info.getBundleContext()).thenReturn(context);
-        Map<BundleContext, Collection<ListenerHook.ListenerInfo>> listeners = new HashMap<>();
-        listeners.put(context, new ArrayList<>(Arrays.asList(info)));
-
-        hooks.event(event, listeners);
-
-        Assert.assertTrue(listeners.isEmpty());
-    }
-
-    @Test
-    public void testEventHookDoesNotFilterResolver() {
-        BundledHooks hooks = new BundledHooks();
-
-        ServiceEvent event = mock(ServiceEvent.class);
-
-        BundleContext context = mock(BundleContext.class);
-        Bundle bundle = mock(Bundle.class);
-        ServiceReference ref = mock(ServiceReference.class);
-
-        when(event.getServiceReference()).thenReturn(ref);
-
-        when(context.getBundle()).thenReturn(bundle);
-        when(bundle.getSymbolicName()).thenReturn("org.apache.sling.servlets.resolver");
-        when(ref.getProperty(BundledHooks.class.getName())).thenReturn("true");
-
-        ListenerHook.ListenerInfo info = mock(ListenerHook.ListenerInfo.class);
-        when(info.getBundleContext()).thenReturn(context);
-        Map<BundleContext, Collection<ListenerHook.ListenerInfo>> listeners = new HashMap<>();
-        listeners.put(context, new ArrayList<>(Arrays.asList(info)));
-
-        hooks.event(event, listeners);
-
-        Assert.assertEquals(1, listeners.size());
-
-        Assert.assertEquals(1, listeners.get(context).size());
-    }
-}
diff --git a/src/test/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptTrackerTest.java b/src/test/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptTrackerTest.java
deleted file mode 100644
index 022ff35..0000000
--- a/src/test/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptTrackerTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ~ 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.internal;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.servlet.Servlet;
-
-import org.junit.Test;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleEvent;
-import org.osgi.framework.ServiceRegistration;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-public class BundledScriptTrackerTest {
-
-    @Test
-    public void removedBundle() {
-        BundledScriptTracker tracker = new BundledScriptTracker();
-        tracker.activate(mock(BundleContext.class));
-        List<ServiceRegistration<Servlet>> registrations = new ArrayList<>();
-        ServiceRegistration<Servlet> registration = mock(ServiceRegistration.class);
-        registrations.add(registration);
-        tracker.removedBundle(mock(Bundle.class), mock(BundleEvent.class), registrations);
-        verify(registration).unregister();
-    }
-}
diff --git a/src/test/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptContextTest.java b/src/test/java/org/apache/sling/scripting/core/impl/bundled/BundledScriptContextTest.java
similarity index 98%
rename from src/test/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptContextTest.java
rename to src/test/java/org/apache/sling/scripting/core/impl/bundled/BundledScriptContextTest.java
index 0a26503..342c385 100644
--- a/src/test/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptContextTest.java
+++ b/src/test/java/org/apache/sling/scripting/core/impl/bundled/BundledScriptContextTest.java
@@ -16,13 +16,14 @@
  ~ specific language governing permissions and limitations
  ~ under the License.
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-package org.apache.sling.scripting.bundle.tracker.internal;
+package org.apache.sling.scripting.core.impl.bundled;
 
 import javax.script.Bindings;
 import javax.script.ScriptContext;
 import javax.script.SimpleBindings;
 
 import org.apache.sling.api.scripting.SlingScriptConstants;
+import org.apache.sling.scripting.core.impl.bundled.BundledScriptContext;
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
diff --git a/src/test/java/org/apache/sling/scripting/bundle/tracker/internal/LogWriterTest.java b/src/test/java/org/apache/sling/scripting/core/impl/bundled/LogWriterTest.java
similarity index 94%
rename from src/test/java/org/apache/sling/scripting/bundle/tracker/internal/LogWriterTest.java
rename to src/test/java/org/apache/sling/scripting/core/impl/bundled/LogWriterTest.java
index bb5fe26..850a0e0 100644
--- a/src/test/java/org/apache/sling/scripting/bundle/tracker/internal/LogWriterTest.java
+++ b/src/test/java/org/apache/sling/scripting/core/impl/bundled/LogWriterTest.java
@@ -16,8 +16,9 @@
  ~ specific language governing permissions and limitations
  ~ under the License.
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-package org.apache.sling.scripting.bundle.tracker.internal;
+package org.apache.sling.scripting.core.impl.bundled;
 
+import org.apache.sling.scripting.core.impl.bundled.LogWriter;
 import org.junit.Test;
 import org.slf4j.Logger;
 
diff --git a/src/test/java/org/apache/sling/scripting/bundle/tracker/internal/ProtectedBindingsTest.java b/src/test/java/org/apache/sling/scripting/core/impl/bundled/ProtectedBindingsTest.java
similarity index 98%
rename from src/test/java/org/apache/sling/scripting/bundle/tracker/internal/ProtectedBindingsTest.java
rename to src/test/java/org/apache/sling/scripting/core/impl/bundled/ProtectedBindingsTest.java
index 82d2a9a..6a185ec 100644
--- a/src/test/java/org/apache/sling/scripting/bundle/tracker/internal/ProtectedBindingsTest.java
+++ b/src/test/java/org/apache/sling/scripting/core/impl/bundled/ProtectedBindingsTest.java
@@ -16,7 +16,7 @@
  ~ specific language governing permissions and limitations
  ~ under the License.
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-package org.apache.sling.scripting.bundle.tracker.internal;
+package org.apache.sling.scripting.core.impl.bundled;
 
 import java.util.Arrays;
 import java.util.Collection;
@@ -29,6 +29,7 @@ import java.util.Set;
 import javax.script.Bindings;
 import javax.script.SimpleBindings;
 
+import org.apache.sling.scripting.core.impl.bundled.ProtectedBindings;
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
diff --git a/src/test/java/org/apache/sling/scripting/core/it/ScriptingCoreTestSupport.java b/src/test/java/org/apache/sling/scripting/core/it/ScriptingCoreTestSupport.java
index 9b7bb15..3e07466 100644
--- a/src/test/java/org/apache/sling/scripting/core/it/ScriptingCoreTestSupport.java
+++ b/src/test/java/org/apache/sling/scripting/core/it/ScriptingCoreTestSupport.java
@@ -58,6 +58,7 @@ public class ScriptingCoreTestSupport extends TestSupport {
             mavenBundle().groupId("org.jsoup").artifactId("jsoup").versionAsInProject(),
             mavenBundle().groupId("org.apache.servicemix.bundles").artifactId("org.apache.servicemix.bundles.hamcrest").versionAsInProject(),
             mavenBundle().groupId("org.apache.sling").artifactId("org.apache.sling.commons.compiler").versionAsInProject(),
+            mavenBundle().groupId("org.apache.sling").artifactId("org.apache.sling.servlets.resolver").versionAsInProject(),
             junitBundles(),
             awaitility()
         ).add(