SLING-9999 Remove cyclic dependency between scripting and servlets features

add Bundle API from bundle tracker
diff --git a/pom.xml b/pom.xml
index 50d2de3..3b5df37 100644
--- a/pom.xml
+++ b/pom.xml
@@ -41,19 +41,36 @@
     </scm>
 
     <dependencies>
+        <!-- javax -->
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
         <!-- OSGi -->
         <dependency>
             <groupId>org.osgi</groupId>
             <artifactId>org.osgi.annotation.versioning</artifactId>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.core</artifactId>
+            <scope>provided</scope>
+        </dependency>
         <!-- Apache Sling -->
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.api</artifactId>
-            <version>2.16.0</version>
+            <version>2.23.1-SNAPSHOT</version>
             <scope>provided</scope>
         </dependency>
+        <!-- nullability -->
+        <dependency>
+            <groupId>org.jetbrains</groupId>
+            <artifactId>annotations</artifactId>
+            <scope>compile</scope>
+        </dependency>
     </dependencies>
 
 </project>
diff --git a/src/main/java/org/apache/sling/scripting/api/bundle/BundledRenderUnit.java b/src/main/java/org/apache/sling/scripting/api/bundle/BundledRenderUnit.java
new file mode 100644
index 0000000..e039c7b
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/api/bundle/BundledRenderUnit.java
@@ -0,0 +1,145 @@
+/*
+ * 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.api.bundle;
+
+import java.io.InputStream;
+import java.util.Set;
+
+import javax.script.ScriptException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.osgi.annotation.versioning.ConsumerType;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+/**
+ * <p>
+ * A {@code BundledRenderUnit} represents a pre-packaged script or precompiled script (Java class) that will be executed in order to
+ * render a {@link org.apache.sling.api.SlingHttpServletRequest}.
+ * </p>
+ * <p>
+ * The {@code BundledRenderUnit} provider module is responsible for defining how a unit is executed. However, when executing the unit in the
+ * context of a {@link javax.script.ScriptEngine}, the provider module should add the current executing unit into the {@link
+ * javax.script.ScriptEngine}'s {@link javax.script.ScriptContext} using the {@link #VARIABLE} key.
+ * </p>
+ */
+@ConsumerType
+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 the {@link Bundle} the publishing bundle of this unit (not to be confused with the provider module, which is the module that
+     * instantiates a {@link BundledRenderUnit}). 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();
+
+    /**
+     * Returns the {@link BundleContext} to use for this unit. This method can be useful for getting an instance of the publishing bundle's
+     * context, when needed to load dependencies at run-time.
+     *
+     * @return the bundle context of the bundle publishing this unit
+     */
+    @NotNull BundleContext getBundleContext();
+
+    /**
+     * Returns the {@code Set} of {@link TypeProvider}s which are related to this unit.
+     *
+     * @return the set of providers; if the unit doesn't have any inheritance chains, then the set will contain only one {@link
+     * TypeProvider}
+     */
+    @NotNull Set<TypeProvider> getTypeProviders();
+
+    /**
+     * Retrieves an OSGi runtime dependency of the wrapped script identified by the passed {@code className} parameter.
+     *
+     * @param className the fully qualified class name
+     * @param <T>       the expected service type
+     * @return an instance of the {@link T} or {@code null}
+     */
+    @Nullable <T> T 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 <T>       the expected service type
+     * @return an instance of the {@link T} or {@code null}
+     */
+    @Nullable <T> T[] getServices(@NotNull String className, @Nullable String filter);
+
+    /**
+     * Returns the path of this executable in the resource type hierarchy. The path can be relative to the search paths or absolute.
+     *
+     * @return the path of this executable in the resource type hierarchy
+     */
+    @NotNull
+    String getPath();
+
+    /**
+     * This method will execute / evaluate the wrapped script or precompiled script with the given request.
+     *
+     * @throws ScriptException if the execution leads to an error
+     */
+    void eval(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response) throws ScriptException;
+
+    /**
+     * This method will return an input stream if {@code this} unit is backed by a script that can be interpreted.
+     *
+     * @return an {@link InputStream} providing the source code of the backing script; if {@code this} unit is backed by a precompiled
+     * script (essentially a Java class), then this method will return {@code null}
+     */
+    @Nullable
+    default InputStream getInputStream() {
+        return null;
+    }
+}
diff --git a/src/main/java/org/apache/sling/scripting/api/bundle/BundledRenderUnitCapability.java b/src/main/java/org/apache/sling/scripting/api/bundle/BundledRenderUnitCapability.java
new file mode 100644
index 0000000..8704bf0
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/api/bundle/BundledRenderUnitCapability.java
@@ -0,0 +1,92 @@
+/*
+ * 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.api.bundle;
+
+import java.util.List;
+import java.util.Set;
+
+import org.apache.sling.api.resource.type.ResourceType;
+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/api/bundle/BundledRenderUnitFinder.java b/src/main/java/org/apache/sling/scripting/api/bundle/BundledRenderUnitFinder.java
new file mode 100644
index 0000000..bc4c863
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/api/bundle/BundledRenderUnitFinder.java
@@ -0,0 +1,62 @@
+/*
+ * 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.api.bundle;
+
+import java.util.Set;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.osgi.annotation.versioning.ConsumerType;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The {@code BundledScriptFinder} finds the {@link BundledRenderUnit} corresponding to a certain chain of {@link TypeProvider}s or
+ * corresponding to a certain path-based {@link BundledRenderUnitCapability}.
+ */
+@ConsumerType
+public interface BundledRenderUnitFinder {
+
+    /**
+     * Retrieves the best matching {@link BundledRenderUnit} for the provided {@code inheritanceChain}, by scanning all {@link TypeProvider}
+     * bundles for the class or script capable of providing a rendering for resource type chain.
+     *
+     * @param context             the bundle context to use.
+     * @param inheritanceChain    the resource type chain; the set is ordered from the most specific resource type to the most generic one
+     * @param allRelatedProviders this is a super set, containing both the {@code inheritanceChain} but also all the required providers; a
+     *                            required provider is a provider that's needed by a {@link ResourceType} in order to delegate rendering to
+     *                            it, but it's not extended by the same {@link ResourceType}
+     * @return a {@link BundledRenderUnit} if one was found, {@code null} otherwise
+     */
+    @Nullable
+    BundledRenderUnit findUnit(@NotNull BundleContext context, @NotNull Set<TypeProvider> inheritanceChain, @NotNull Set<TypeProvider> allRelatedProviders);
+
+    /**
+     * Retrieves a path-based {@link BundledRenderUnit} from the passed {@code provider}.
+     *
+     * @param context             the bundle context to use.
+     * @param provider            the provider from which to retrieve the unit
+     * @param allRelatedProviders this is a super set, containing both the providers connected through an inheritance relationship but also
+     *                            all the required providers; a required provider is a provider that's needed by a {@link ResourceType} in
+     *                            order to delegate rendering to it, but it's not extended by the same {@link ResourceType}
+     * @return a {@link BundledRenderUnit} if one was found, {@code null} otherwise
+     * @see BundledRenderUnitCapability#getPath()
+     */
+    @Nullable
+    BundledRenderUnit findUnit(@NotNull BundleContext context, @NotNull TypeProvider provider, @NotNull Set<TypeProvider> allRelatedProviders);
+}
diff --git a/src/main/java/org/apache/sling/scripting/api/bundle/TypeProvider.java b/src/main/java/org/apache/sling/scripting/api/bundle/TypeProvider.java
new file mode 100644
index 0000000..3027252
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/api/bundle/TypeProvider.java
@@ -0,0 +1,45 @@
+/*
+ * 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.api.bundle;
+
+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/api/bundle/package-info.java b/src/main/java/org/apache/sling/scripting/api/bundle/package-info.java
new file mode 100644
index 0000000..7e63653
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/api/bundle/package-info.java
@@ -0,0 +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.
+ */
+@Version("0.2.0")
+package org.apache.sling.scripting.api.bundle;
+
+import org.osgi.annotation.versioning.Version;