SLING-9306 - Provide a path capability for scripts which are not part of a resource type
* switched to using the ServletResolverConstants for generating the capabilities'
attributes
* capabilities providing only a path instead of a resource type will generate
a path-registered servlet
diff --git a/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java b/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java
index 42f15e7..a9adcd5 100644
--- a/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java
+++ b/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java
@@ -44,7 +44,7 @@
Executable getScript(Set<TypeProvider> providers) {
for (TypeProvider provider : providers) {
- ResourceTypeCapability capability = provider.getResourceTypeCapability();
+ ServletCapability capability = provider.getServletCapability();
for (String match : buildScriptMatches(capability.getResourceTypes(),
capability.getSelectors().toArray(new String[0]), capability.getMethod(), capability.getExtension())) {
String scriptExtension = capability.getScriptExtension();
@@ -61,10 +61,7 @@
return null;
}
- @Nullable
- private Executable getExecutable(@NotNull Bundle bundle, boolean precompiled, @NotNull String match,
- @NotNull String scriptEngineName, @NotNull String scriptExtension) {
- String path = match + DOT + scriptExtension;
+ Executable getScript(@NotNull Bundle bundle, boolean precompiled, @NotNull String path, @NotNull String scriptEngineName) {
if (precompiled) {
String className = JavaEscapeHelper.makeJavaPackage(path);
try {
@@ -74,7 +71,7 @@
// do nothing here
}
} else {
- URL bundledScriptURL = bundle.getEntry(NS_JAVAX_SCRIPT_CAPABILITY + (match.startsWith("/") ? "" : SLASH) + path);
+ URL bundledScriptURL = bundle.getEntry(NS_JAVAX_SCRIPT_CAPABILITY + (path.startsWith("/") ? "" : SLASH) + path);
if (bundledScriptURL != null) {
return new Script(bundle, path, bundledScriptURL, scriptEngineName);
}
@@ -82,6 +79,13 @@
return null;
}
+ @Nullable
+ private Executable getExecutable(@NotNull Bundle bundle, boolean precompiled, @NotNull String match,
+ @NotNull String scriptEngineName, @NotNull String scriptExtension) {
+ String path = match + DOT + scriptExtension;
+ return getScript(bundle, precompiled, path, scriptEngineName);
+ }
+
private List<String> buildScriptMatches(Set<ResourceType> resourceTypes, String[] selectors, String method, String extension) {
List<String> matches = new ArrayList<>();
for (ResourceType resourceType : resourceTypes) {
diff --git a/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptServlet.java b/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptServlet.java
index e053a58..e9e7b8e 100644
--- a/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptServlet.java
+++ b/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptServlet.java
@@ -67,7 +67,7 @@
}
RequestWrapper requestWrapper = new RequestWrapper(request,
- wiredTypeProviders.stream().map(typeProvider -> typeProvider.getResourceTypeCapability().getResourceTypes()
+ wiredTypeProviders.stream().map(typeProvider -> typeProvider.getServletCapability().getResourceTypes()
).flatMap(Collection::stream).collect(Collectors.toSet()));
ScriptContextProvider.ExecutableContext executableContext = scriptContextProvider
.prepareScriptContext(requestWrapper, response, executable);
diff --git a/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptTracker.java b/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptTracker.java
index 9006823..0cab4c6 100644
--- a/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptTracker.java
+++ b/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptTracker.java
@@ -30,7 +30,6 @@
import java.util.Map;
import java.util.Optional;
import java.util.Set;
-import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -82,10 +81,8 @@
public class BundledScriptTracker implements BundleTrackerCustomizer<List<ServiceRegistration<Servlet>>> {
static final String NS_SLING_SCRIPTING_EXTENDER = "sling.scripting";
- static final String NS_SLING_RESOURCE_TYPE = "sling.resourceType";
+ static final String NS_SLING_SERVLET = "sling.servlet";
private static final Logger LOGGER = LoggerFactory.getLogger(BundledScriptTracker.class);
- static final String AT_SLING_SELECTORS = "sling.resourceType.selectors";
- static final String AT_SLING_EXTENSIONS = "sling.resourceType.extensions";
private static final String REGISTERING_BUNDLE = "org.apache.sling.scripting.bundle.tracker.internal.BundledScriptTracker.registering_bundle";
static final String AT_VERSION = "version";
static final String AT_SCRIPT_ENGINE = "scriptEngine";
@@ -120,51 +117,61 @@
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_RESOURCE_TYPE);
- List<BundleCapability> capabilities = bundleWiring.getCapabilities(NS_SLING_RESOURCE_TYPE);
+ LOGGER.debug("Inspecting bundle {} for {} capability.", bundle.getSymbolicName(), NS_SLING_SERVLET);
+ List<BundleCapability> capabilities = bundleWiring.getCapabilities(NS_SLING_SERVLET);
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());
- ResourceTypeCapability resourceTypeCapability = ResourceTypeCapability.fromBundleCapability(cap);
- String[] resourceTypesRegistrationValue = new String[resourceTypeCapability.getResourceTypes().size()];
- int rtIndex = 0;
- for (ResourceType resourceType : resourceTypeCapability.getResourceTypes()) {
- resourceTypesRegistrationValue[rtIndex++] = resourceType.toString();
- }
- properties.put(ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES, resourceTypesRegistrationValue);
-
- String extension = resourceTypeCapability.getExtension();
- if (StringUtils.isEmpty(extension)) {
- extension = "html";
- }
- properties.put(ServletResolverConstants.SLING_SERVLET_EXTENSIONS, extension);
-
- if (!resourceTypeCapability.getSelectors().isEmpty()) {
- properties.put(ServletResolverConstants.SLING_SERVLET_SELECTORS, resourceTypeCapability.getSelectors().toArray());
- }
-
- if (StringUtils.isNotEmpty(resourceTypeCapability.getMethod())) {
- properties.put(ServletResolverConstants.SLING_SERVLET_METHODS, resourceTypeCapability.getMethod());
- }
-
- List<ServiceRegistration<Servlet>> regs = new ArrayList<>();
+ ServletCapability servletCapability = ServletCapability.fromBundleCapability(cap);
+ Executable executable = null;
+ TypeProvider baseTypeProvider = new TypeProvider(servletCapability, bundle);
LinkedHashSet<TypeProvider> wiredProviders = new LinkedHashSet<>();
- wiredProviders.add(new TypeProvider(resourceTypeCapability, bundle));
- String extendedResourceTypeString = resourceTypeCapability.getExtendedResourceType();
- if (StringUtils.isNotEmpty(extendedResourceTypeString)) {
- collectProvidersChain(wiredProviders, bundleWiring, extendedResourceTypeString);
- wiredProviders.stream().filter(typeProvider -> typeProvider.getResourceTypeCapability().getResourceTypes().stream().anyMatch(resourceType -> resourceType.getType().equals(extendedResourceTypeString))).findFirst().ifPresent(typeProvider -> {
- for (ResourceType type : typeProvider.getResourceTypeCapability().getResourceTypes()) {
- if (type.getType().equals(extendedResourceTypeString)) {
- properties.put(ServletResolverConstants.SLING_SERVLET_RESOURCE_SUPER_TYPE, type.toString());
- }
- }
- });
+ wiredProviders.add(baseTypeProvider);
+ if (!servletCapability.getResourceTypes().isEmpty()) {
+ String[] resourceTypesRegistrationValue = new String[servletCapability.getResourceTypes().size()];
+ int rtIndex = 0;
+ for (ResourceType resourceType : servletCapability.getResourceTypes()) {
+ resourceTypesRegistrationValue[rtIndex++] = resourceType.toString();
+ }
+ properties.put(ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES, resourceTypesRegistrationValue);
+
+ String extension = servletCapability.getExtension();
+ if (StringUtils.isEmpty(extension)) {
+ extension = "html";
+ }
+ properties.put(ServletResolverConstants.SLING_SERVLET_EXTENSIONS, extension);
+
+ if (!servletCapability.getSelectors().isEmpty()) {
+ properties.put(ServletResolverConstants.SLING_SERVLET_SELECTORS, servletCapability.getSelectors().toArray());
+ }
+
+ if (StringUtils.isNotEmpty(servletCapability.getMethod())) {
+ properties.put(ServletResolverConstants.SLING_SERVLET_METHODS, servletCapability.getMethod());
+ }
+
+ String extendedResourceTypeString = servletCapability.getExtendedResourceType();
+ if (StringUtils.isNotEmpty(extendedResourceTypeString)) {
+ collectProvidersChain(wiredProviders, bundleWiring, extendedResourceTypeString);
+ wiredProviders.stream().filter(typeProvider -> typeProvider.getServletCapability().getResourceTypes().stream()
+ .anyMatch(resourceType -> resourceType.getType().equals(extendedResourceTypeString))).findFirst()
+ .ifPresent(typeProvider -> {
+ for (ResourceType type : typeProvider.getServletCapability().getResourceTypes()) {
+ if (type.getType().equals(extendedResourceTypeString)) {
+ properties.put(ServletResolverConstants.SLING_SERVLET_RESOURCE_SUPER_TYPE, type.toString());
+ }
+ }
+ });
+ }
+ executable = bundledScriptFinder.getScript(wiredProviders);
+ } else if (StringUtils.isNotEmpty(servletCapability.getPath()) && StringUtils.isNotEmpty(servletCapability.getScriptEngineName())) {
+ executable = bundledScriptFinder.getScript(baseTypeProvider.getBundle(), baseTypeProvider.isPrecompiled(),
+ servletCapability.getPath(), servletCapability.getScriptEngineName());
}
- Executable executable = bundledScriptFinder.getScript(wiredProviders);
+ List<ServiceRegistration<Servlet>> regs = new ArrayList<>();
+
if (executable != null) {
properties.put(ServletResolverConstants.SLING_SERVLET_PATHS, executable.getPath());
regs.add(
@@ -351,9 +358,12 @@
private static String getResourceTypeVersion(ServiceReference<?> ref) {
String[] values = PropertiesUtil.toStringArray(ref.getProperty(ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES));
- String resourceTypeValue = values[0];
- ResourceType resourceType = ResourceType.parseResourceType(resourceTypeValue);
- return resourceType.getVersion();
+ 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) {
@@ -367,26 +377,26 @@
private void collectProvidersChain(@NotNull Set<TypeProvider> providers, @NotNull BundleWiring wiring,
@NotNull String extendedResourceType) {
- for (BundleWire wire : wiring.getRequiredWires(NS_SLING_RESOURCE_TYPE)) {
- ResourceTypeCapability wiredCapability = ResourceTypeCapability.fromBundleCapability(wire.getCapability());
+ for (BundleWire wire : wiring.getRequiredWires(NS_SLING_SERVLET)) {
+ ServletCapability wiredCapability = ServletCapability.fromBundleCapability(wire.getCapability());
if (wiredCapability.getSelectors().isEmpty()) {
for (ResourceType resourceType : wiredCapability.getResourceTypes()) {
if (extendedResourceType.equals(resourceType.getType())) {
Bundle providingBundle = wire.getProvider().getBundle();
providers.add(new TypeProvider(wiredCapability, providingBundle));
- for (BundleWire providedWire : wire.getProvider().getWiring().getRequiredWires(NS_SLING_RESOURCE_TYPE)) {
- ResourceTypeCapability resourceTypeCapability =
- ResourceTypeCapability.fromBundleCapability(providedWire.getCapability());
- String capabilityExtends = resourceTypeCapability.getExtendedResourceType();
- if (resourceTypeCapability.getSelectors().isEmpty() && StringUtils.isNotEmpty(capabilityExtends)) {
- for (ResourceType providedResourceType : resourceTypeCapability.getResourceTypes()) {
+ for (BundleWire providedWire : wire.getProvider().getWiring().getRequiredWires(NS_SLING_SERVLET)) {
+ ServletCapability servletCapability =
+ ServletCapability.fromBundleCapability(providedWire.getCapability());
+ String capabilityExtends = servletCapability.getExtendedResourceType();
+ if (servletCapability.getSelectors().isEmpty() && StringUtils.isNotEmpty(capabilityExtends)) {
+ for (ResourceType providedResourceType : servletCapability.getResourceTypes()) {
if (providedResourceType.getType().equals(extendedResourceType)) {
collectProvidersChain(providers, providedWire.getProvider()
.getBundle().adapt(BundleWiring.class), capabilityExtends);
}
}
} else {
- providers.add(new TypeProvider(resourceTypeCapability, providedWire.getProvider().getBundle()));
+ providers.add(new TypeProvider(servletCapability, providedWire.getProvider().getBundle()));
}
}
}
diff --git a/main/java/org/apache/sling/scripting/bundle/tracker/internal/ResourceTypeCapability.java b/main/java/org/apache/sling/scripting/bundle/tracker/internal/ServletCapability.java
similarity index 76%
rename from main/java/org/apache/sling/scripting/bundle/tracker/internal/ResourceTypeCapability.java
rename to main/java/org/apache/sling/scripting/bundle/tracker/internal/ServletCapability.java
index 756750c..f782fe4 100644
--- a/main/java/org/apache/sling/scripting/bundle/tracker/internal/ResourceTypeCapability.java
+++ b/main/java/org/apache/sling/scripting/bundle/tracker/internal/ServletCapability.java
@@ -34,9 +34,10 @@
import org.osgi.framework.Version;
import org.osgi.framework.wiring.BundleCapability;
-class ResourceTypeCapability {
+class ServletCapability {
private final Set<ResourceType> resourceTypes;
+ private final String path;
private final List<String> selectors;
private final String extension;
private final String method;
@@ -44,11 +45,12 @@
private final String scriptEngineName;
private final String scriptExtension;
- private ResourceTypeCapability(@NotNull Set<ResourceType> resourceTypes, @NotNull List<String> selectors,
- @Nullable String extension, @Nullable String method,
- @Nullable String extendedResourceType, @Nullable String scriptEngineName,
- @Nullable String scriptExtension) {
+ private ServletCapability(@NotNull Set<ResourceType> resourceTypes, @Nullable String path, @NotNull List<String> selectors,
+ @Nullable String extension, @Nullable String method,
+ @Nullable String extendedResourceType, @Nullable String scriptEngineName,
+ @Nullable String scriptExtension) {
this.resourceTypes = resourceTypes;
+ this.path = path;
this.selectors = selectors;
this.extension = extension;
this.method = method;
@@ -62,6 +64,11 @@
return Collections.unmodifiableSet(resourceTypes);
}
+ @Nullable
+ public String getPath() {
+ return path;
+ }
+
@NotNull
List<String> getSelectors() {
return Collections.unmodifiableList(selectors);
@@ -94,7 +101,7 @@
@Override
public int hashCode() {
- return Objects.hash(resourceTypes, selectors, extension, method, extendedResourceType, scriptEngineName, scriptExtension);
+ return Objects.hash(resourceTypes, path, selectors, extension, method, extendedResourceType, scriptEngineName, scriptExtension);
}
@Override
@@ -102,9 +109,10 @@
if (this == obj) {
return true;
}
- if (obj instanceof ResourceTypeCapability) {
- ResourceTypeCapability other = (ResourceTypeCapability) obj;
- return Objects.equals(resourceTypes, other.resourceTypes) && Objects.equals(selectors, other.selectors) &&
+ if (obj instanceof ServletCapability) {
+ ServletCapability other = (ServletCapability) obj;
+ return Objects.equals(resourceTypes, other.resourceTypes) && Objects.equals(path, other.path) &&
+ Objects.equals(selectors, other.selectors) &&
Objects.equals(extension, other.extension) && Objects.equals(method, other.method) &&
Objects.equals(extendedResourceType, other.extendedResourceType) &&
Objects.equals(scriptEngineName, other.scriptEngineName) && Objects.equals(scriptExtension, other.scriptExtension);
@@ -112,10 +120,10 @@
return false;
}
- static ResourceTypeCapability fromBundleCapability(@NotNull BundleCapability capability) {
+ static ServletCapability fromBundleCapability(@NotNull BundleCapability capability) {
Map<String, Object> attributes = capability.getAttributes();
Set<ResourceType> resourceTypes = new HashSet<>();
- String[] capabilityResourceTypes = PropertiesUtil.toStringArray(attributes.get(BundledScriptTracker.NS_SLING_RESOURCE_TYPE),
+ 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) {
@@ -125,10 +133,11 @@
resourceTypes.add(ResourceType.parseResourceType(rt + "/" + version.toString()));
}
}
- return new ResourceTypeCapability(
+ return new ServletCapability(
resourceTypes,
- Arrays.asList(PropertiesUtil.toStringArray(attributes.get(BundledScriptTracker.AT_SLING_SELECTORS), new String[0])),
- (String) attributes.get(BundledScriptTracker.AT_SLING_EXTENSIONS),
+ (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),
diff --git a/main/java/org/apache/sling/scripting/bundle/tracker/internal/TypeProvider.java b/main/java/org/apache/sling/scripting/bundle/tracker/internal/TypeProvider.java
index daa4bdf..ee6c643 100644
--- a/main/java/org/apache/sling/scripting/bundle/tracker/internal/TypeProvider.java
+++ b/main/java/org/apache/sling/scripting/bundle/tracker/internal/TypeProvider.java
@@ -27,18 +27,18 @@
*/
public class TypeProvider {
- private final ResourceTypeCapability resourceTypeCapability;
+ private final ServletCapability servletCapability;
private final Bundle bundle;
private final boolean precompiled;
/**
* Builds a {@code TypeProvider}.
*
- * @param resourceTypeCapability the resource type capability
+ * @param servletCapability the resource type capability
* @param bundle the bundle that provides the resource type
*/
- TypeProvider(ResourceTypeCapability resourceTypeCapability, Bundle bundle) {
- this.resourceTypeCapability = resourceTypeCapability;
+ TypeProvider(ServletCapability servletCapability, Bundle bundle) {
+ this.servletCapability = servletCapability;
this.bundle = bundle;
precompiled = Boolean.parseBoolean(bundle.getHeaders().get("Sling-ResourceType-Precompiled"));
}
@@ -48,8 +48,8 @@
*
* @return the resource type capabilities
*/
- ResourceTypeCapability getResourceTypeCapability() {
- return resourceTypeCapability;
+ ServletCapability getServletCapability() {
+ return servletCapability;
}
/**
@@ -72,7 +72,7 @@
@Override
public int hashCode() {
- return Objects.hash(bundle, resourceTypeCapability, precompiled);
+ return Objects.hash(bundle, servletCapability, precompiled);
}
@Override
@@ -82,7 +82,7 @@
}
if (obj instanceof TypeProvider) {
TypeProvider other = (TypeProvider) obj;
- return Objects.equals(bundle, other.bundle) && Objects.equals(resourceTypeCapability, other.resourceTypeCapability) &&
+ return Objects.equals(bundle, other.bundle) && Objects.equals(servletCapability, other.servletCapability) &&
Objects.equals(precompiled, other.precompiled);
}
return false;
@@ -90,7 +90,7 @@
@Override
public String toString() {
- return String.format("TypeProvider{ resourceTypeCapability=%s; bundle=%s; precompiled=%s }", resourceTypeCapability,
+ return String.format("TypeProvider{ resourceTypeCapability=%s; bundle=%s; precompiled=%s }", servletCapability,
bundle.getSymbolicName(), precompiled);
}
}