refactor

* extracted IT in separate module (need to re-add jacoco)
* made sure BRU dependencies are obtained with the correct bundle context
diff --git a/pom.xml b/pom.xml
index 40c5c9d..e8552a3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -84,6 +84,11 @@
             <version>3.5.0</version>
         </dependency>
         <dependency>
+            <groupId>org.jetbrains</groupId>
+            <artifactId>annotations</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.api</artifactId>
             <version>2.16.4</version>
@@ -150,56 +155,8 @@
             <artifactId>junit</artifactId>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>org.apache.sling</groupId>
-            <artifactId>org.apache.sling.scripting.examplebundle</artifactId>
-            <version>0.0.1-SNAPSHOT</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.sling</groupId>
-            <artifactId>org.apache.sling.scripting.examplebundle.precompiled</artifactId>
-            <version>0.0.1-SNAPSHOT</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.sling</groupId>
-            <artifactId>org.apache.sling.scripting.examplebundle.classic</artifactId>
-            <version>0.0.1-SNAPSHOT</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.sling</groupId>
-            <artifactId>org.apache.sling.scripting.examplebundle.hi</artifactId>
-            <version>0.0.1-SNAPSHOT</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.sling</groupId>
-            <artifactId>org.apache.sling.junit.teleporter</artifactId>
-            <version>1.0.16</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.sling</groupId>
-            <artifactId>org.apache.sling.testing.clients</artifactId>
-            <version>1.1.12</version>
-            <scope>test</scope>
-        </dependency>
 
         <dependency>
-            <groupId>org.jsoup</groupId>
-            <artifactId>jsoup</artifactId>
-            <version>1.7.3</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.sling</groupId>
-            <artifactId>org.apache.sling.testing.rules</artifactId>
-            <version>1.0.6</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
             <groupId>org.mockito</groupId>
             <artifactId>mockito-core</artifactId>
             <version>2.13.0</version>
@@ -213,256 +170,4 @@
         </dependency>
     </dependencies>
 
-    <profiles>
-        <profile>
-            <id>it</id>
-            <properties>
-                <http.host>localhost</http.host>
-                <sling.vm.options>-Xmx1024m -XX:MaxPermSize=256m -Djava.awt.headless=true</sling.vm.options>
-            </properties>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>build-helper-maven-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>reserve-network-port</id>
-                                <goals>
-                                    <!-- pre-integration-test is too late -->
-                                    <goal>reserve-network-port</goal>
-                                </goals>
-                                <phase>process-resources</phase>
-                                <configuration>
-                                    <portNames>
-                                        <portName>http.port.testing</portName>
-                                    </portNames>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <configuration>
-                            <argLine>@{argLine}</argLine>
-                        </configuration>
-                    </plugin>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-failsafe-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>integration-test</id>
-                                <phase>integration-test</phase>
-                                <goals>
-                                    <goal>integration-test</goal>
-                                </goals>
-                            </execution>
-                            <execution>
-                                <id>verify</id>
-                                <phase>integration-test</phase>
-                                <goals>
-                                    <goal>verify</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                        <configuration>
-                            <systemPropertyVariables>
-                                <launchpad.http.server.url>http://${http.host}:${http.port.testing}/</launchpad.http.server.url>
-                            </systemPropertyVariables>
-                        </configuration>
-                    </plugin>
-                    <plugin>
-                        <groupId>org.jacoco</groupId>
-                        <artifactId>jacoco-maven-plugin</artifactId>
-                        <version>${jacoco.maven.plugin.version}</version>
-                        <executions>
-                            <execution>
-                                <id>prepare-agent</id>
-                                <goals>
-                                    <goal>prepare-agent</goal>
-                                </goals>
-                                <configuration>
-                                    <destFile>${project.build.directory}/jacoco-unit.exec</destFile>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>prepare-agent-integration</id>
-                                <goals>
-                                    <goal>prepare-agent-integration</goal>
-                                </goals>
-                                <configuration>
-                                    <propertyName>jacoco.agent</propertyName>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>merge-reports</id>
-                                <phase>verify</phase>
-                                <goals>
-                                    <goal>merge</goal>
-                                </goals>
-                                <configuration>
-                                    <fileSets>
-                                        <fileSet>
-                                            <directory>${project.build.directory}</directory>
-                                            <includes>
-                                                <include>jacoco-unit.exec</include>
-                                                <include>jacoco-it.exec</include>
-                                            </includes>
-                                        </fileSet>
-                                    </fileSets>
-                                    <destFile>${project.build.directory}/jacoco.exec</destFile>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>final-report</id>
-                                <phase>verify</phase>
-                                <goals>
-                                    <goal>report</goal>
-                                </goals>
-                            </execution>
-                            <execution>
-                                <id>check-coverage</id>
-                                <goals>
-                                    <goal>check</goal>
-                                </goals>
-                                <configuration>
-                                    <rules>
-                                        <rule>
-                                            <element>BUNDLE</element>
-                                            <limits>
-                                                <limit>
-                                                    <counter>INSTRUCTION</counter>
-                                                    <value>COVEREDRATIO</value>
-                                                    <minimum>0.80</minimum>
-                                                </limit>
-                                            </limits>
-                                        </rule>
-                                        <rule>
-                                            <element>CLASS</element>
-                                            <limits>
-                                                <limit>
-                                                    <counter>INSTRUCTION</counter>
-                                                    <value>COVEREDRATIO</value>
-                                                    <minimum>0.80</minimum>
-                                                </limit>
-                                            </limits>
-                                        </rule>
-                                    </rules>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                    <plugin>
-                        <!-- the Sling instance is provisioned from the model in src/test/provisioning/it-model.txt -->
-                        <groupId>org.apache.sling</groupId>
-                        <artifactId>slingstart-maven-plugin</artifactId>
-                        <version>1.7.16</version>
-                        <extensions>true</extensions>
-                        <executions>
-                            <execution>
-                                <id>prepare-launchpad-package</id>
-                                <phase>pre-integration-test</phase>
-                                <goals>
-                                    <goal>prepare-package</goal>
-                                </goals>
-                            </execution>
-                            <execution>
-                                <id>build-launchpad-package</id>
-                                <phase>pre-integration-test</phase>
-                                <goals>
-                                    <goal>package</goal>
-                                </goals>
-                            </execution>
-                            <execution>
-                                <id>start-container-before-IT</id>
-                                <goals>
-                                    <goal>start</goal>
-                                </goals>
-                            </execution>
-                            <execution>
-                                <id>stop-container-after-IT</id>
-                                <goals>
-                                    <goal>stop</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                        <configuration>
-                            <usePomDependencies>true</usePomDependencies>
-                            <attachArtifact>false</attachArtifact>
-                             <!-- <shouldBlockUntilKeyIsPressed>true</shouldBlockUntilKeyIsPressed> -->
-                            <servers>
-                                <server>
-                                    <id>testinstance</id>
-                                    <port>${http.port.testing}</port>
-                                    <vmOpts>${sling.vm.options}</vmOpts>
-                                    <debug>${jacoco.agent}</debug>
-                                </server>
-                            </servers>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>example</id>
-            <properties>
-                <http.host>localhost</http.host>
-                <http.port>8080</http.port>
-                <sling.vm.options>-Xmx1024m -XX:MaxPermSize=256m -Djava.awt.headless=true -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000</sling.vm.options>
-            </properties>
-            <build>
-                <plugins>
-                    <plugin>
-                        <!-- the Sling instance is provisioned from the model in src/test/provisioning/it-model.txt -->
-                        <groupId>org.apache.sling</groupId>
-                        <artifactId>slingstart-maven-plugin</artifactId>
-                        <version>1.7.16</version>
-                        <extensions>true</extensions>
-                        <executions>
-                            <execution>
-                                <id>prepare-launchpad-package</id>
-                                <phase>pre-integration-test</phase>
-                                <goals>
-                                    <goal>prepare-package</goal>
-                                </goals>
-                            </execution>
-                            <execution>
-                                <id>build-launchpad-package</id>
-                                <phase>pre-integration-test</phase>
-                                <goals>
-                                    <goal>package</goal>
-                                </goals>
-                            </execution>
-                            <execution>
-                                <id>start-container-before-IT</id>
-                                <goals>
-                                    <goal>start</goal>
-                                </goals>
-                            </execution>
-                            <execution>
-                                <goals>
-                                    <goal>stop</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                        <configuration>
-                            <usePomDependencies>true</usePomDependencies>
-                            <attachArtifact>false</attachArtifact>
-                            <shouldBlockUntilKeyIsPressed>true</shouldBlockUntilKeyIsPressed>
-                            <servers>
-                                <server>
-                                    <id>exampleinstance</id>
-                                    <port>${http.port}</port>
-                                    <vmOpts>${sling.vm.options}</vmOpts>
-                                </server>
-                            </servers>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-    </profiles>
-
 </project>
diff --git a/src/main/java/org/apache/sling/scripting/resolver/BundledRenderUnit.java b/src/main/java/org/apache/sling/scripting/resolver/BundledRenderUnit.java
new file mode 100644
index 0000000..01ee566
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/resolver/BundledRenderUnit.java
@@ -0,0 +1,114 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.resolver;
+
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.osgi.annotation.versioning.ProviderType;
+import org.osgi.framework.Bundle;
+
+/**
+ * <p>
+ * A {@code BundledRenderUnit} represents a pre-packaged script or precompiled script that will be executed in order to render a
+ * {@link org.apache.sling.api.SlingHttpServletRequest}.
+ * </p>
+ * <p>
+ * If the current {@link org.apache.sling.api.SlingHttpServletRequest} is served by a {@code BundledRenderUnit}, the
+ * {@code org.apache.sling.scripting.resolver} will set the {@code BundledRenderUnit} in the {@link javax.script.Bindings} map associated to the request,
+ * under the {@link #VARIABLE} key.
+ * </p>
+ */
+@ProviderType
+public interface BundledRenderUnit {
+
+    /**
+     * The variable available in the {@link javax.script.Bindings} associated to a {@link org.apache.sling.api.SlingHttpServletRequest}
+     * if that request is served by a {@code BundledRenderUnit}.
+     */
+    String VARIABLE = BundledRenderUnit.class.getName();
+
+    /**
+     * In case this {@code BundledRenderUnit} wraps a precompiled script, this method will return an instance of that object.
+     *
+     * @return a precompiled unit, if {@code this} unit wraps a precompiled script; {@code null} otherwise
+     */
+    @Nullable
+    default Object getUnit() {
+        return null;
+    }
+
+    /**
+     * Returns the name of {@code this BundledRenderUnit}. This can be the name of the wrapped script or precompiled script.
+     *
+     * @return the name {@code this BundledRenderUnit}
+     */
+    @NotNull String getName();
+
+    /**
+     * Returns an instance of the {@link ScriptEngine} that can execute the wrapped script or precompiled script, if the latter needs a
+     * specific runtime.
+     *
+     * @return an instance of the script's or precompiled script's associated {@link ScriptEngine}
+     */
+    @NotNull ScriptEngine getScriptEngine();
+
+    /**
+     * Returns the {@link Bundle} in which the script or precompiled script is packaged. This method can be useful for getting an
+     * instance of the bundle's classloader, when needed to load dependencies at run time. To do so the following code example can help:
+     *
+     * <pre>
+     * Bundle bundle = bundledRenderUnit.getBundle();
+     * Classloader bundleClassloader = bundle.adapt(BundleWiring.class).getClassLoader();
+     * </pre>
+     */
+    @NotNull Bundle getBundle();
+
+    /**
+     * Provided a {@link ScriptContext}, this method will execute / evaluate the wrapped script or precompiled script.
+     *
+     * @param context the {@link ScriptContext}
+     * @throws ScriptException if the execution leads to an error
+     */
+    void eval(@NotNull ScriptContext context) throws ScriptException;
+
+    /**
+     * Retrieves an OSGi runtime dependency of the wrapped script identified by the passed {@code className} parameter.
+     *
+     * @param className     the fully qualified class name
+     * @param <ServiceType> the expected service type
+     * @return an instance of the {@link ServiceType} or {@code null}
+     */
+    @Nullable <ServiceType> ServiceType getService(@NotNull String className);
+
+    /**
+     * Retrieves multiple instances of an OSGi runtime dependency of the wrapped script identified by the passed {@code className}
+     * parameter, filtered according to the passed {@code filter}.
+     *
+     * @param className     the fully qualified class name
+     * @param filter        a filter expression or {@code null} if all the instances should be returned; for more details about the {@code
+     *                      filter}'s syntax check {@link org.osgi.framework.BundleContext#getServiceReferences(String, String)}
+     * @param <ServiceType> the expected service type
+     * @return an instance of the {@link ServiceType} or {@code null}
+     */
+    @Nullable <ServiceType> ServiceType[] getServices(@NotNull String className, @Nullable String filter);
+}
diff --git a/src/main/java/org/apache/sling/scripting/resolver/internal/AbstractBundledRenderUnit.java b/src/main/java/org/apache/sling/scripting/resolver/internal/AbstractBundledRenderUnit.java
new file mode 100644
index 0000000..8cdcf4c
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/resolver/internal/AbstractBundledRenderUnit.java
@@ -0,0 +1,133 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.resolver.internal;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+abstract class AbstractBundledRenderUnit implements Executable {
+
+    private static final Logger LOG = LoggerFactory.getLogger(AbstractBundledRenderUnit.class.getName());
+
+    private final Bundle bundle;
+    private final BundleContext bundleContext;
+    private List<ServiceReference> references;
+    private Map<String, Object> services;
+
+    AbstractBundledRenderUnit(@NotNull Bundle bundle) {
+        this.bundle = bundle;
+        bundleContext = bundle.getBundleContext();
+    }
+
+    @Override
+    @NotNull
+    public Bundle getBundle() {
+        return bundle;
+    }
+
+    @Override
+    @Nullable
+    @SuppressWarnings("unchecked")
+    public <ServiceType> ServiceType getService(@NotNull String className) {
+        LOG.debug("Attempting to load class {} as an OSGi service.", className);
+        ServiceType result = (this.services == null ? null : (ServiceType) this.services.get(className));
+        if (result == null) {
+            final ServiceReference ref = this.bundleContext.getServiceReference(className);
+            if (ref != null) {
+                result = (ServiceType) this.bundleContext.getService(ref);
+                if (result != null) {
+                    if (this.services == null) {
+                        this.services = new HashMap<>();
+                    }
+                    if (this.references == null) {
+                        this.references = new ArrayList<>();
+                    }
+                    this.references.add(ref);
+                    this.services.put(className, result);
+                    return result;
+                }
+            }
+        }
+        return null;
+    }
+
+    @Override
+    @Nullable
+    @SuppressWarnings("unchecked")
+    public <ServiceType> ServiceType[] getServices(@NotNull String className, @NotNull String filter) {
+        ServiceType[] result = null;
+        try {
+            final ServiceReference[] refs = this.bundleContext.getServiceReferences(className, filter);
+
+            if (refs != null) {
+                // sort by service ranking (lowest first) (see ServiceReference#compareTo(Object))
+                List<ServiceReference> references = Arrays.asList(refs);
+                Collections.sort(references);
+                // get the highest ranking first
+                Collections.reverse(references);
+
+                final List<ServiceType> objects = new ArrayList<>();
+                for (ServiceReference reference : references) {
+                    final ServiceType service = (ServiceType) this.bundleContext.getService(reference);
+                    if (service != null) {
+                        if (this.references == null) {
+                            this.references = new ArrayList<>();
+                        }
+                        this.references.add(reference);
+                        objects.add(service);
+                    }
+                }
+                if (objects.size() > 0) {
+                    ServiceType[] srv = (ServiceType[]) Array.newInstance(bundle.loadClass(className), objects.size());
+                    result = objects.toArray(srv);
+                }
+            }
+        } catch (Exception e) {
+            LOG.error(String.format("Unable to retrieve the services of type %s.", className), e);
+        }
+        return result;
+    }
+
+    @Override
+    public void releaseDependencies() {
+        if (references != null) {
+            for (ServiceReference reference : this.references) {
+                bundleContext.ungetService(reference);
+            }
+            references.clear();
+        }
+        if (services != null) {
+            services.clear();
+        }
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/scripting/resolver/internal/BundledScriptFinder.java b/src/main/java/org/apache/sling/scripting/resolver/internal/BundledScriptFinder.java
index 746b356..7493301 100644
--- a/src/main/java/org/apache/sling/scripting/resolver/internal/BundledScriptFinder.java
+++ b/src/main/java/org/apache/sling/scripting/resolver/internal/BundledScriptFinder.java
@@ -25,7 +25,6 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
-import java.util.regex.Pattern;
 
 import javax.script.ScriptEngineFactory;
 import javax.script.ScriptEngineManager;
@@ -49,11 +48,11 @@
     @Reference
     private ScriptEngineManager scriptEngineManager;
 
-    ScriptEngineExecutable getScript(SlingHttpServletRequest request, Bundle bundle, boolean precompiledScripts) {
+    Executable getScript(SlingHttpServletRequest request, Bundle bundle, boolean precompiledScripts) {
         return getScript(request, bundle, precompiledScripts,null);
     }
 
-    ScriptEngineExecutable getScript(SlingHttpServletRequest request, Bundle bundle, boolean precompiledScripts, String delegatedResourceType) {
+    Executable getScript(SlingHttpServletRequest request, Bundle bundle, boolean precompiledScripts, String delegatedResourceType) {
         List<String> scriptMatches;
         if (StringUtils.isEmpty(delegatedResourceType)) {
             scriptMatches = buildScriptMatches(request);
diff --git a/src/main/java/org/apache/sling/scripting/resolver/internal/BundledScriptServlet.java b/src/main/java/org/apache/sling/scripting/resolver/internal/BundledScriptServlet.java
index 8564120..e88004f 100644
--- a/src/main/java/org/apache/sling/scripting/resolver/internal/BundledScriptServlet.java
+++ b/src/main/java/org/apache/sling/scripting/resolver/internal/BundledScriptServlet.java
@@ -53,7 +53,7 @@
     private final Set<String> m_wiredResourceTypes;
     private final boolean m_precompiledScripts;
 
-    private Map<String, ScriptEngineExecutable> scriptsMap = new HashMap<>();
+    private Map<String, Executable> scriptsMap = new HashMap<>();
     private ReadWriteLock lock = new ReentrantReadWriteLock();
 
 
@@ -90,23 +90,23 @@
             }
 
             String scriptsMapKey = getScriptsMapKey(request);
-            ScriptEngineExecutable script;
+            Executable executable;
             lock.readLock().lock();
             try {
-                script = scriptsMap.get(scriptsMapKey);
-                if (script == null) {
+                executable = scriptsMap.get(scriptsMapKey);
+                if (executable == null) {
                     lock.readLock().unlock();
                     lock.writeLock().lock();
                     try {
-                        script = scriptsMap.get(scriptsMapKey);
-                        if (script == null) {
+                        executable = scriptsMap.get(scriptsMapKey);
+                        if (executable == null) {
                             if (StringUtils.isEmpty(m_delegatedResourceType)) {
-                                script = m_bundledScriptFinder.getScript(request, m_bundle, m_precompiledScripts);
+                                executable = m_bundledScriptFinder.getScript(request, m_bundle, m_precompiledScripts);
                             } else {
-                                script = m_bundledScriptFinder.getScript(request, m_bundle, m_precompiledScripts, m_delegatedResourceType);
+                                executable = m_bundledScriptFinder.getScript(request, m_bundle, m_precompiledScripts, m_delegatedResourceType);
                             }
-                            if (script != null) {
-                                scriptsMap.put(scriptsMapKey, script);
+                            if (executable != null) {
+                                scriptsMap.put(scriptsMapKey, executable);
                             }
                         }
                         lock.readLock().lock();
@@ -117,25 +117,23 @@
             } finally {
                 lock.readLock().unlock();
             }
-            if (script != null) {
+            if (executable != null) {
                 RequestWrapper requestWrapper = new RequestWrapper(request, m_wiredResourceTypes);
-                ScriptContext scriptContext = m_scriptContextProvider.prepareScriptContext(requestWrapper, response, script);
+                ScriptContext scriptContext = m_scriptContextProvider.prepareScriptContext(requestWrapper, response, executable);
                 try {
-                    script.eval(scriptContext);
+                    executable.eval(scriptContext);
                 } catch (ScriptException se) {
                     Throwable cause = (se.getCause() == null) ? se : se.getCause();
-                    throw new ScriptEvaluationException(script.getName(), se.getMessage(), cause);
+                    throw new ScriptEvaluationException(executable.getName(), se.getMessage(), cause);
                 } finally {
-                    if (scriptContext != null) {
-                        Bindings engineBindings = scriptContext.getBindings(ScriptContext.ENGINE_SCOPE);
-                        if (engineBindings != null && engineBindings.containsKey(SlingBindings.SLING)) {
-                            Object scriptHelper = engineBindings.get(SlingBindings.SLING);
-                            if (scriptHelper instanceof ScriptHelper) {
-                                ((ScriptHelper) scriptHelper).cleanup();
-                            }
+                    Bindings engineBindings = scriptContext.getBindings(ScriptContext.ENGINE_SCOPE);
+                    if (engineBindings != null && engineBindings.containsKey(SlingBindings.SLING)) {
+                        Object scriptHelper = engineBindings.get(SlingBindings.SLING);
+                        if (scriptHelper instanceof ScriptHelper) {
+                            ((ScriptHelper) scriptHelper).cleanup();
                         }
-
                     }
+                    executable.releaseDependencies();
                 }
             } else {
                 throw new ServletException("Unable to locate a " + (m_precompiledScripts ? "class" : "script") + " for rendering.");
diff --git a/src/main/java/org/apache/sling/scripting/resolver/internal/ScriptEngineExecutable.java b/src/main/java/org/apache/sling/scripting/resolver/internal/Executable.java
similarity index 76%
rename from src/main/java/org/apache/sling/scripting/resolver/internal/ScriptEngineExecutable.java
rename to src/main/java/org/apache/sling/scripting/resolver/internal/Executable.java
index a62188d..fd5616c 100644
--- a/src/main/java/org/apache/sling/scripting/resolver/internal/ScriptEngineExecutable.java
+++ b/src/main/java/org/apache/sling/scripting/resolver/internal/Executable.java
@@ -18,19 +18,10 @@
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 package org.apache.sling.scripting.resolver.internal;
 
-import javax.script.ScriptContext;
-import javax.script.ScriptEngine;
-import javax.script.ScriptException;
+import org.apache.sling.scripting.resolver.BundledRenderUnit;
 
-import org.osgi.framework.Bundle;
+interface Executable extends BundledRenderUnit {
 
-interface ScriptEngineExecutable {
+    void releaseDependencies();
 
-    String getName();
-
-    ScriptEngine getScriptEngine();
-
-    Bundle getBundle();
-
-    void eval(ScriptContext context) throws ScriptException;
 }
diff --git a/src/main/java/org/apache/sling/scripting/resolver/internal/PrecompiledScript.java b/src/main/java/org/apache/sling/scripting/resolver/internal/PrecompiledScript.java
index 99e2ba2..400adbd 100644
--- a/src/main/java/org/apache/sling/scripting/resolver/internal/PrecompiledScript.java
+++ b/src/main/java/org/apache/sling/scripting/resolver/internal/PrecompiledScript.java
@@ -26,40 +26,42 @@
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.sling.api.scripting.SlingScriptConstants;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.osgi.framework.Bundle;
 
-public class PrecompiledScript implements ScriptEngineExecutable {
+public class PrecompiledScript extends AbstractBundledRenderUnit {
 
     private static final StringReader EMPTY_READER = new StringReader(StringUtils.EMPTY);
 
     private final ScriptEngine scriptEngine;
     private final Object precompiledScript;
-    private final Bundle bundle;
 
-    PrecompiledScript(Bundle bundle, ScriptEngine scriptEngine, Object precompiledScript) {
+    PrecompiledScript(@NotNull Bundle bundle, @NotNull ScriptEngine scriptEngine, @NotNull Object precompiledScript) {
+        super(bundle);
         this.scriptEngine = scriptEngine;
         this.precompiledScript = precompiledScript;
-        this.bundle = bundle;
     }
 
     @Override
+    @NotNull
     public String getName() {
         return precompiledScript.getClass().getName();
     }
 
     @Override
+    @NotNull
     public ScriptEngine getScriptEngine() {
         return scriptEngine;
     }
 
     @Override
-    public void eval(ScriptContext context) throws ScriptException {
-        context.setAttribute("precompiled.unit", precompiledScript, SlingScriptConstants.SLING_SCOPE);
+    public void eval(@NotNull ScriptContext context) throws ScriptException {
         scriptEngine.eval(EMPTY_READER, context);
     }
 
     @Override
-    public Bundle getBundle() {
-        return bundle;
+    public @NotNull Object getUnit() {
+        return precompiledScript;
     }
 }
diff --git a/src/main/java/org/apache/sling/scripting/resolver/internal/Script.java b/src/main/java/org/apache/sling/scripting/resolver/internal/Script.java
index 0d863e4..7d2a80d 100644
--- a/src/main/java/org/apache/sling/scripting/resolver/internal/Script.java
+++ b/src/main/java/org/apache/sling/scripting/resolver/internal/Script.java
@@ -35,9 +35,8 @@
 import org.apache.sling.scripting.core.ScriptNameAwareReader;
 import org.osgi.framework.Bundle;
 
-class Script implements ScriptEngineExecutable {
+class Script extends AbstractBundledRenderUnit {
 
-    private final Bundle bundle;
     private final URL url;
     private final ScriptEngine scriptEngine;
     private String sourceCode;
@@ -47,7 +46,7 @@
 
 
     Script(Bundle bundle, URL url, ScriptEngine scriptEngine) {
-        this.bundle = bundle;
+        super(bundle);
         this.url = url;
         this.scriptEngine = scriptEngine;
     }
@@ -100,9 +99,4 @@
             throw new ScriptException(e);
         }
     }
-
-    @Override
-    public Bundle getBundle() {
-        return bundle;
-    }
 }
diff --git a/src/main/java/org/apache/sling/scripting/resolver/internal/ScriptContextProvider.java b/src/main/java/org/apache/sling/scripting/resolver/internal/ScriptContextProvider.java
index efd2639..326253b 100644
--- a/src/main/java/org/apache/sling/scripting/resolver/internal/ScriptContextProvider.java
+++ b/src/main/java/org/apache/sling/scripting/resolver/internal/ScriptContextProvider.java
@@ -40,6 +40,7 @@
 import org.apache.sling.scripting.api.BindingsValuesProvidersByContext;
 import org.apache.sling.scripting.api.resource.ScriptingResourceResolverProvider;
 import org.apache.sling.scripting.core.ScriptHelper;
+import org.apache.sling.scripting.resolver.BundledRenderUnit;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Reference;
 import org.slf4j.Logger;
@@ -49,7 +50,7 @@
         service = ScriptContextProvider.class
 )
 public class ScriptContextProvider {
-    
+
     private static final Set<String> PROTECTED_BINDINGS = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
             SlingBindings.REQUEST,
             SlingBindings.RESPONSE,
@@ -59,7 +60,8 @@
             SlingBindings.OUT,
             SlingBindings.LOG,
             SlingBindings.SLING,
-            ScriptEngine.FILENAME
+            ScriptEngine.FILENAME,
+            BundledRenderUnit.VARIABLE
     )));
 
     @Reference
@@ -68,7 +70,7 @@
     @Reference
     private ScriptingResourceResolverProvider scriptingResourceResolverProvider;
 
-    ScriptContext prepareScriptContext(SlingHttpServletRequest request, SlingHttpServletResponse response, ScriptEngineExecutable executable)
+    ScriptContext prepareScriptContext(SlingHttpServletRequest request, SlingHttpServletResponse response, Executable executable)
             throws IOException {
         // prepare the SlingBindings
         Bindings bindings = new SimpleBindings();
@@ -81,6 +83,7 @@
         Logger scriptLogger = LoggerFactory.getLogger(executable.getName());
         bindings.put(SlingBindings.LOG, scriptLogger);
         bindings.put(SlingBindings.SLING, new ScriptHelper(executable.getBundle().getBundleContext(), null, request, response));
+        bindings.put(BundledRenderUnit.VARIABLE, executable);
         bindings.put(ScriptEngine.FILENAME, executable.getName());
         bindings.put(ScriptEngine.FILENAME.replaceAll("\\.", "_"), executable.getName());
 
@@ -99,7 +102,6 @@
         scriptContext.setWriter(response.getWriter());
         scriptContext.setErrorWriter(new LogWriter(scriptLogger));
         scriptContext.setReader(request.getReader());
-        scriptContext.setAttribute("org.apache.sling.scripting.resolver.provider.bundle", executable.getBundle(), SlingScriptConstants.SLING_SCOPE);
         return scriptContext;
     }
 
diff --git a/src/main/java/org/apache/sling/scripting/resolver/internal/ScriptEngineExecutable.java b/src/main/java/org/apache/sling/scripting/resolver/package-info.java
similarity index 71%
copy from src/main/java/org/apache/sling/scripting/resolver/internal/ScriptEngineExecutable.java
copy to src/main/java/org/apache/sling/scripting/resolver/package-info.java
index a62188d..c45b556 100644
--- a/src/main/java/org/apache/sling/scripting/resolver/internal/ScriptEngineExecutable.java
+++ b/src/main/java/org/apache/sling/scripting/resolver/package-info.java
@@ -16,21 +16,7 @@
  ~ specific language governing permissions and limitations
  ~ under the License.
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-package org.apache.sling.scripting.resolver.internal;
+@Version("0.1.0")
+package org.apache.sling.scripting.resolver;
 
-import javax.script.ScriptContext;
-import javax.script.ScriptEngine;
-import javax.script.ScriptException;
-
-import org.osgi.framework.Bundle;
-
-interface ScriptEngineExecutable {
-
-    String getName();
-
-    ScriptEngine getScriptEngine();
-
-    Bundle getBundle();
-
-    void eval(ScriptContext context) throws ScriptException;
-}
+import org.osgi.annotation.versioning.Version;
diff --git a/src/test/java/org/apache/sling/junit/teleporter/customizers/ITCustomizer.java b/src/test/java/org/apache/sling/junit/teleporter/customizers/ITCustomizer.java
deleted file mode 100644
index e14e36f..0000000
--- a/src/test/java/org/apache/sling/junit/teleporter/customizers/ITCustomizer.java
+++ /dev/null
@@ -1,35 +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.junit.teleporter.customizers;
-
-import org.apache.sling.junit.rules.TeleporterRule;
-import org.apache.sling.testing.teleporter.client.ClientSideTeleporter;
-
-public class ITCustomizer implements TeleporterRule.Customizer {
-
-    public static final String BASE_URL_PROP = "launchpad.http.server.url";
-
-    @Override
-    public void customize(TeleporterRule t, String options) {
-        final ClientSideTeleporter cst = (ClientSideTeleporter)t;
-        cst.setBaseUrl(System.getProperty(BASE_URL_PROP, BASE_URL_PROP + "_IS_NOT_SET"));
-        cst.setServerCredentials("admin", "admin");
-        cst.includeDependencyPrefix("org.apache.sling.scripting.resolver.internal");
-        cst.includeDependencyPrefix("org.apache.sling.testing");
-        cst.setTestReadyTimeoutSeconds(20);
-    }
-}
diff --git a/src/test/java/org/apache/sling/scripting/resolver/internal/AbstractEndpointIT.java b/src/test/java/org/apache/sling/scripting/resolver/internal/AbstractEndpointIT.java
deleted file mode 100644
index aad08f4..0000000
--- a/src/test/java/org/apache/sling/scripting/resolver/internal/AbstractEndpointIT.java
+++ /dev/null
@@ -1,148 +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.resolver.internal;
-
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.nio.charset.StandardCharsets;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.apache.http.HttpResponse;
-import org.apache.http.NameValuePair;
-import org.apache.http.client.config.RequestConfig;
-import org.apache.http.client.methods.HttpDelete;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.methods.HttpHead;
-import org.apache.http.client.methods.HttpOptions;
-import org.apache.http.client.methods.HttpPatch;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.client.methods.HttpPut;
-import org.apache.http.client.methods.HttpRequestBase;
-import org.apache.http.client.methods.HttpTrace;
-import org.apache.http.client.methods.HttpUriRequest;
-import org.apache.http.client.utils.URIBuilder;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClientBuilder;
-import org.apache.sling.junit.teleporter.customizers.ITCustomizer;
-import org.apache.sling.testing.junit.rules.SlingInstanceRule;
-import org.jsoup.Jsoup;
-import org.jsoup.nodes.Document;
-import org.junit.AfterClass;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.ClassRule;
-
-
-public abstract class AbstractEndpointIT {
-
-    protected int contentFindTimeout = 20000;
-    protected int contentFindRetryDelay = 1000;
-    private static CloseableHttpClient httpClient;
-
-    @ClassRule
-    public static final SlingInstanceRule SLING_INSTANCE_RULE = new SlingInstanceRule();
-
-    private Map<String, Document> documentMap = new ConcurrentHashMap<>();
-
-    @BeforeClass
-    public static void setUp() {
-        httpClient = HttpClientBuilder.create().build();
-    }
-
-    @AfterClass
-    public static void tearDown() throws IOException {
-        httpClient.close();
-    }
-
-    /**
-     * Retrieves a jsoup Document from the passed {@code url}. The URL can contain selectors and extensions, but it has to identify a Sling
-     * content {@link org.apache.sling.api.resource.Resource}.
-     *
-     * @param url the URL from which to retrieve the {@link Document}
-     * @return the Document
-     * @throws Exception if the resource was not found before the timeout elapsed
-     */
-    protected Document getDocument(String url) throws Exception {
-        return getDocument(url, HttpGet.METHOD_NAME);
-    }
-
-    protected Document getDocument(String url, String httpMethod, NameValuePair... parameters) throws Exception {
-        URIBuilder uriBuilder = new URIBuilder(url);
-        uriBuilder.setParameters(parameters);
-        URI uri = uriBuilder.build();
-        Document document = documentMap.get(httpMethod + ":" + uri.toString());
-        if (document == null) {
-            HttpResponse response = getResponse(httpMethod, url, 200);
-            document = Jsoup.parse(response.getEntity().getContent(), StandardCharsets.UTF_8.name(),
-                    System.getProperty(ITCustomizer.BASE_URL_PROP, ITCustomizer.BASE_URL_PROP +
-                            "_IS_NOT_SET"));
-            documentMap.put(httpMethod + ":" + uri, document);
-        }
-        return document;
-    }
-
-    protected HttpResponse getResponse(String method, String url, int statusCode, NameValuePair... parameters) throws Exception {
-        String resourcePath = url.substring(0, url.indexOf('.'));
-        SLING_INSTANCE_RULE.getAdminClient().waitExists(resourcePath, contentFindTimeout, contentFindRetryDelay);
-        HttpUriRequest request = prepareRequest(method, url, parameters);
-        HttpResponse response = httpClient.execute(request);
-        Assert.assertNotNull(response);
-        Assert.assertEquals("URL " + url + " did not return a " + statusCode + " status code.", statusCode,
-                response.getStatusLine().getStatusCode
-                        ());
-        return response;
-    }
-
-    protected HttpUriRequest prepareRequest(String method, String url, NameValuePair... parameters) throws URISyntaxException {
-        HttpRequestBase request = null;
-        URIBuilder uriBuilder =
-                new URIBuilder(System.getProperty(ITCustomizer.BASE_URL_PROP, ITCustomizer.BASE_URL_PROP + "_IS_NOT_SET") + url);
-        uriBuilder.setParameters(parameters);
-        switch (method) {
-            case HttpGet.METHOD_NAME:
-                request = new HttpGet(uriBuilder.build());
-                break;
-            case HttpHead.METHOD_NAME:
-                request = new HttpHead(uriBuilder.build());
-                break;
-            case HttpOptions.METHOD_NAME:
-                request = new HttpOptions(uriBuilder.build());
-                break;
-            case HttpPost.METHOD_NAME:
-                request = new HttpPost(uriBuilder.build());
-                break;
-            case HttpPut.METHOD_NAME:
-                request = new HttpPut(uriBuilder.build());
-                break;
-            case HttpPatch.METHOD_NAME:
-                request = new HttpPatch(uriBuilder.build());
-                break;
-            case HttpTrace.METHOD_NAME:
-                request = new HttpTrace(uriBuilder.build());
-                break;
-            case HttpDelete.METHOD_NAME:
-                request = new HttpDelete(uriBuilder.build());
-                break;
-        }
-        return request;
-    }
-
-}
diff --git a/src/test/java/org/apache/sling/scripting/resolver/internal/BundledScriptTrackerIT.java b/src/test/java/org/apache/sling/scripting/resolver/internal/BundledScriptTrackerIT.java
deleted file mode 100644
index 0ca3578..0000000
--- a/src/test/java/org/apache/sling/scripting/resolver/internal/BundledScriptTrackerIT.java
+++ /dev/null
@@ -1,64 +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.resolver.internal;
-
-import javax.servlet.Servlet;
-
-import org.apache.sling.junit.rules.TeleporterRule;
-import org.apache.sling.testing.clients.util.poller.Polling;
-import org.junit.Rule;
-import org.junit.Test;
-
-public class BundledScriptTrackerIT {
-
-    @Rule
-    public TeleporterRule teleporter = TeleporterRule.forClass(getClass(), "IT");
-
-    @Test
-    public void testSlingServletForResourceTypeProvided() throws Exception {
-        waitForService(Servlet.class, String.format("(%s=%s)", "sling.servlet.resourceTypes", "org.apache.sling.scripting" +
-                ".examplebundle.hello/1.0.0"), 20000, 1000);
-        waitForService(Servlet.class, String.format("(%s=%s)", "sling.servlet.resourceTypes", "org.apache.sling.scripting" +
-                ".examplebundle.hello/2.0.0"), 20000, 1000);
-        waitForService(Servlet.class, String.format("(%s=%s)", "sling.servlet.resourceTypes", "org.apache.sling.scripting" +
-                ".examplebundle.hello"), 20000, 1000);
-        waitForService(Servlet.class, String.format("(%s=%s)", "sling.servlet.resourceTypes", "org.apache.sling.scripting" +
-                ".examplebundle.hi/1.0.0"), 20000, 1000);
-        waitForService(Servlet.class, String.format("(%s=%s)", "sling.servlet.resourceTypes", "org.apache.sling.scripting" +
-                ".examplebundle.hi"), 20000, 1000);
-        waitForService(Servlet.class, String.format("(%s=%s)", "sling.servlet.resourceTypes", "org.apache.sling.scripting" +
-                ".examplebundle.scriptmatching/1.0.0"), 20000, 1000);
-        waitForService(Servlet.class, String.format("(%s=%s)", "sling.servlet.resourceTypes", "org.apache.sling.scripting" +
-                ".examplebundle.scriptmatching"), 20000, 1000);
-    }
-
-    private void waitForService(Class serviceClass, String filter, long waitTime, long retryAfter)
-            throws Exception {
-        Polling p = new Polling() {
-            @Override
-            public Boolean call() {
-                return teleporter.getService(serviceClass, filter) != null;
-            }
-
-            @Override
-            protected String message() {
-                return "Cannot obtain a reference to service " + serviceClass.getName() + " with filter " + filter + " after %1$d ms";
-            }
-        };
-        p.poll(waitTime, retryAfter);
-    }
-}
diff --git a/src/test/java/org/apache/sling/scripting/resolver/internal/EndpointIT.java b/src/test/java/org/apache/sling/scripting/resolver/internal/EndpointIT.java
deleted file mode 100644
index f4f93d0..0000000
--- a/src/test/java/org/apache/sling/scripting/resolver/internal/EndpointIT.java
+++ /dev/null
@@ -1,90 +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.resolver.internal;
-
-import org.jsoup.nodes.Document;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class EndpointIT extends AbstractEndpointIT {
-
-    @Test
-    public void testHelloEndpoint() throws Exception {
-        Document document = getDocument("/content/srr/examples/hello.html");
-        Assert.assertEquals("We're testing some serious scripting here in Version 2", document.select("h2").html());
-        Assert.assertTrue(document.body().html().contains("World2"));
-        Assert.assertTrue(document.body().html().contains("Hello2"));
-    }
-
-    @Test
-    public void testPrecompiledHelloEndpoint() throws Exception {
-        Document document = getDocument("/content/srr/examples/precompiled-hello.html");
-        Assert.assertEquals("We're testing some serious scripting here in Version 2", document.select("h2").html());
-        Assert.assertTrue(document.body().html().contains("World2"));
-        Assert.assertTrue(document.body().html().contains("Hello2"));
-    }
-
-    @Test
-    public void testHelloEndpointV1() throws Exception {
-        Document document = getDocument("content/srr/examples/hello-v1.html");
-        Assert.assertEquals("We're testing some serious scripting here", document.select("h2").html());
-        Assert.assertTrue(document.body().html().contains("World"));
-        Assert.assertTrue(document.body().html().contains("Hello"));
-    }
-
-    @Test
-    public void testPrecompiledHelloEndpointV1() throws Exception {
-        Document document = getDocument("content/srr/examples/precompiled-hello-v1.html");
-        Assert.assertEquals("We're testing some serious scripting here", document.select("h2").html());
-        Assert.assertTrue(document.body().html().contains("World"));
-        Assert.assertTrue(document.body().html().contains("Hello"));
-    }
-
-    @Test
-    public void testHelloEndpointV2() throws Exception {
-        Document document = getDocument("content/srr/examples/hello-v2.html");
-        Assert.assertEquals("We're testing some serious scripting here in Version 2", document.select("h2").html());
-        Assert.assertTrue(document.body().html().contains("World2"));
-        Assert.assertTrue(document.body().html().contains("Hello2"));
-    }
-
-    @Test
-    public void testPrecompiledHelloEndpointV2() throws Exception {
-        Document document = getDocument("content/srr/examples/precompiled-hello-v2.html");
-        Assert.assertEquals("We're testing some serious scripting here in Version 2", document.select("h2").html());
-        Assert.assertTrue(document.body().html().contains("World2"));
-        Assert.assertTrue(document.body().html().contains("Hello2"));
-    }
-
-    @Test
-    public void testHiEndpoint() throws Exception {
-        Document document = getDocument("content/srr/examples/hi.html");
-        Assert.assertEquals("We're testing some serious scripting here", document.select("h2").html());
-        Assert.assertTrue(document.body().html().contains("World"));
-        Assert.assertTrue(document.body().html().contains("Hallo"));
-        Assert.assertFalse(document.body().html().contains("Hello"));
-    }
-
-    @Test
-    public void testHiEndpointV1() throws Exception {
-        Document document = getDocument("content/srr/examples/hi-v1.html");
-        Assert.assertEquals("We're testing some serious scripting here", document.select("h2").html());
-        Assert.assertTrue(document.body().html().contains("World"));
-        Assert.assertTrue(document.body().html().contains("Hallo"));
-        Assert.assertFalse(document.body().html().contains("Hello"));
-    }
-}
diff --git a/src/test/java/org/apache/sling/scripting/resolver/internal/ScriptMatchIT.java b/src/test/java/org/apache/sling/scripting/resolver/internal/ScriptMatchIT.java
deleted file mode 100644
index 3b7e569..0000000
--- a/src/test/java/org/apache/sling/scripting/resolver/internal/ScriptMatchIT.java
+++ /dev/null
@@ -1,155 +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.resolver.internal;
-
-import java.net.URI;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.http.Header;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.methods.HttpDelete;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.methods.HttpHead;
-import org.apache.http.client.methods.HttpOptions;
-import org.apache.http.client.methods.HttpPatch;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.client.methods.HttpPut;
-import org.apache.http.client.methods.HttpTrace;
-import org.jsoup.nodes.Document;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-public class ScriptMatchIT extends AbstractEndpointIT {
-
-    @Test
-    public void testGETMethodMatching() throws Exception {
-        testHttpMethodScriptMatching("/content/srr/examples/script-matching.html", HttpGet.METHOD_NAME);
-    }
-
-    @Test
-    public void testGETMethodSelectorMatching() throws Exception {
-        testHttpMethodScriptMatching("/content/srr/examples/script-matching.selector-1.html", HttpGet.METHOD_NAME);
-    }
-
-    @Test
-    public void testHEADMethodMatching() throws Exception {
-        HttpResponse response = getResponse(HttpHead.METHOD_NAME, "/content/srr/examples/script-matching.html", 200);
-        Header[] header = response.getHeaders("X-Script-Name");
-        assertEquals("Expected to find one X-Script-Name header.", 1, header.length);
-        assertEquals("/javax.script/org.apache.sling.scripting.examplebundle.scriptmatching/1.0.0/HEAD.html", header[0].getValue());
-    }
-
-    @Test
-    public void testHEADMethodSelectorMatching() throws Exception {
-        HttpResponse response = getResponse(HttpHead.METHOD_NAME, "/content/srr/examples/script-matching.selector-1.html", 200);
-        Header[] header = response.getHeaders("X-Script-Name");
-        assertEquals("Expected to find one X-Script-Name header.", 1, header.length);
-        assertEquals("/javax.script/org.apache.sling.scripting.examplebundle.scriptmatching/1.0.0/HEAD.selector-1.html",
-                header[0].getValue());
-    }
-
-    @Test
-    public void testOPTIONSMethodMatching() throws Exception {
-        testHttpMethodScriptMatching("/content/srr/examples/script-matching.html", HttpOptions.METHOD_NAME);
-    }
-
-    @Test
-    public void testOPTIONSMethodSelectorMatching() throws Exception {
-        testHttpMethodScriptMatching("/content/srr/examples/script-matching.selector-1.html", HttpOptions.METHOD_NAME);
-    }
-
-    @Test
-    public void testPOSTMethodMatching() throws Exception {
-        testHttpMethodScriptMatching("/content/srr/examples/script-matching.html", HttpPost.METHOD_NAME);
-    }
-
-    @Test
-    public void testPOSTMethodSelectorMatching() throws Exception {
-        testHttpMethodScriptMatching("/content/srr/examples/script-matching.selector-1.html", HttpPost.METHOD_NAME);
-    }
-
-    @Test
-    public void testPATCHMethodMatching() throws Exception {
-        testHttpMethodScriptMatching("/content/srr/examples/script-matching.html", HttpPatch.METHOD_NAME);
-    }
-
-    @Test
-    public void testPATCHMethodSelectorMatching() throws Exception {
-        testHttpMethodScriptMatching("/content/srr/examples/script-matching.selector-1.html", HttpPatch.METHOD_NAME);
-    }
-
-    @Test
-    public void testPUTMethodMatching() throws Exception {
-        testHttpMethodScriptMatching("/content/srr/examples/script-matching.html", HttpPut.METHOD_NAME);
-    }
-
-    @Test
-    public void testPUTMethodSelectorMatching() throws Exception {
-        testHttpMethodScriptMatching("/content/srr/examples/script-matching.selector-1.html", HttpPut.METHOD_NAME);
-    }
-
-    @Test
-    public void testDELETEMethodMatching() throws Exception {
-        testHttpMethodScriptMatching("/content/srr/examples/script-matching.html", HttpDelete.METHOD_NAME);
-    }
-
-    @Test
-    public void testDELETEMethodSelectorMatching() throws Exception {
-        testHttpMethodScriptMatching("/content/srr/examples/script-matching.selector-1.html", HttpDelete.METHOD_NAME);
-    }
-
-    @Test
-    public void testTRACEMethodMatching() throws Exception {
-        testHttpMethodScriptMatching("/content/srr/examples/script-matching.html", HttpTrace.METHOD_NAME);
-    }
-
-    @Test
-    public void testTRACEMethodSelectorMatching() throws Exception {
-        testHttpMethodScriptMatching("/content/srr/examples/script-matching.selector-1.html", HttpTrace.METHOD_NAME);
-    }
-
-    @Test
-    public void testSelectorMatching() throws Exception {
-        Document document = getDocument("/content/srr/examples/script-matching.selector-2.html");
-        assertTrue(document.select("div").html().contains("/javax.script/org.apache.sling.scripting.examplebundle" +
-                ".scriptmatching/1.0.0/selector-2.html"));
-    }
-
-    private void testHttpMethodScriptMatching(String url, String httpMethod) throws Exception {
-        Document document = getDocument(url, httpMethod);
-        String path = url.substring(url.lastIndexOf('/'));
-        String[] parts = path.split("\\.");
-        String selectorString = null;
-        String extension = null;
-        if (parts.length == 3) {
-            selectorString = parts[1];
-            extension = parts[2];
-        } else if (parts.length == 2) {
-            extension = parts[1];
-        } else {
-            throw new IllegalArgumentException("The following URL doesn't seem to be correctly handled: " + url);
-        }
-        String expectedScriptName = "/javax.script/org.apache.sling.scripting.examplebundle.scriptmatching/1.0.0/" + httpMethod +
-                (StringUtils.isNotEmpty(selectorString) ? "." + selectorString : "") + "." + extension;
-        assertTrue(document.select("div").html().contains(expectedScriptName));
-    }
-
-}