You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ra...@apache.org on 2020/03/06 17:29:02 UTC
[sling-org-apache-sling-scripting-bundle-tracker] branch master
updated: SLING-9181 - The Scripting Bundle Tracker should be extended to
allow more flexibility for resource type definitions
This is an automated email from the ASF dual-hosted git repository.
radu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-bundle-tracker.git
The following commit(s) were added to refs/heads/master by this push:
new ee23513 SLING-9181 - The Scripting Bundle Tracker should be extended to allow more flexibility for resource type definitions
ee23513 is described below
commit ee235138cafd6d775387ada813d964f9eb9f18c0
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Fri Mar 6 18:27:04 2020 +0100
SLING-9181 - The Scripting Bundle Tracker should be extended to allow more flexibility for resource type definitions
* added a unified way to parse resource type strings
---
.../tracker/internal/BundledScriptFinder.java | 25 ++--
.../tracker/internal/BundledScriptTracker.java | 18 +--
.../tracker/internal/ResourceTypeParser.java | 134 +++++++++++++++++++++
.../tracker/internal/ResourceTypeParserTest.java | 87 +++++++++++++
4 files changed, 239 insertions(+), 25 deletions(-)
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java
index f967a4a..0bc350d 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java
@@ -81,22 +81,20 @@ public class BundledScriptFinder {
private List<String> buildScriptMatches(SlingHttpServletRequest request, String providerType) {
List<String> matches = new ArrayList<>();
- String resourceType = providerType;
- String version = null;
String method = request.getMethod();
boolean defaultMethod = DEFAULT_METHODS.contains(method);
- if (resourceType.contains(SLASH) && StringUtils.countMatches(resourceType, SLASH) == 1) {
- version = resourceType.substring(resourceType.indexOf(SLASH) + 1);
- resourceType = resourceType.substring(0, resourceType.length() - version.length() - 1);
- }
+ ResourceTypeParser.ResourceType resourceType = ResourceTypeParser.parseResourceType(providerType);
String extension = request.getRequestPathInfo().getExtension();
String[] selectors = request.getRequestPathInfo().getSelectors();
if (selectors.length > 0) {
for (int i = selectors.length - 1; i >= 0; i--) {
- String scriptForMethod = resourceType + (StringUtils.isNotEmpty(version) ? SLASH + version + SLASH : SLASH) +
+ String scriptForMethod = resourceType.getType() +
+ (StringUtils.isNotEmpty(resourceType.getVersion()) ? SLASH + resourceType.getVersion() + SLASH : SLASH) +
method + DOT + String.join(SLASH, Arrays.copyOf(selectors, i + 1));
- String scriptNoMethod = resourceType + (StringUtils.isNotEmpty(version) ? SLASH + version + SLASH : SLASH) + String.join
- (SLASH, Arrays.copyOf(selectors, i + 1));
+ String scriptNoMethod = resourceType.getType() +
+ (StringUtils.isNotEmpty(resourceType.getVersion()) ? SLASH + resourceType.getVersion() + SLASH : SLASH) +
+ String.join
+ (SLASH, Arrays.copyOf(selectors, i + 1));
if (StringUtils.isNotEmpty(extension)) {
if (defaultMethod) {
matches.add(scriptNoMethod + DOT + extension);
@@ -109,15 +107,16 @@ public class BundledScriptFinder {
matches.add(scriptForMethod);
}
}
- String scriptForMethod = resourceType + (StringUtils.isNotEmpty(version) ? SLASH + version + SLASH : SLASH) + method;
- String scriptNoMethod = resourceType + (StringUtils.isNotEmpty(version) ? SLASH + version + SLASH : SLASH) + resourceType
- .substring(resourceType.lastIndexOf(DOT) + 1);
+ String scriptForMethod = resourceType.getType() +
+ (StringUtils.isNotEmpty(resourceType.getVersion()) ? SLASH + resourceType.getVersion() + SLASH : SLASH) + method;
+ String scriptNoMethod = resourceType.getType() +
+ (StringUtils.isNotEmpty(resourceType.getVersion()) ? SLASH + resourceType.getVersion() + SLASH : SLASH) +
+ resourceType.getResourceLabel();
if (StringUtils.isNotEmpty(extension)) {
if (defaultMethod) {
matches.add(scriptNoMethod + DOT + extension);
}
matches.add(scriptForMethod + DOT + extension);
-
}
if (defaultMethod) {
matches.add(scriptNoMethod);
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptTracker.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptTracker.java
index ef16eb4..b4841e5 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptTracker.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptTracker.java
@@ -288,22 +288,16 @@ public class BundledScriptTracker implements BundleTrackerCustomizer<List<Servic
private String getResourceType(Hashtable<String, Object> props) {
String[] values = PropertiesUtil.toStringArray(props.get(ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES));
- int idx = values[0].indexOf("/");
- if (idx != -1) {
- return values[0].substring(0, idx);
- } else {
- return values[0];
- }
+ String resourceTypeValue = values[0];
+ ResourceTypeParser.ResourceType resourceType = ResourceTypeParser.parseResourceType(resourceTypeValue);
+ return resourceType.getType();
}
private String getResourceTypeVersion(ServiceReference<?> ref) {
String[] values = PropertiesUtil.toStringArray(ref.getProperty(ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES));
- int idx = values[0].indexOf("/");
- if (idx != -1) {
- return values[0].substring(idx + 1);
- } else {
- return null;
- }
+ String resourceTypeValue = values[0];
+ ResourceTypeParser.ResourceType resourceType = ResourceTypeParser.parseResourceType(resourceTypeValue);
+ return resourceType.getVersion();
}
private void set(String key, ServiceReference<?> ref, Hashtable<String, Object> props) {
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/ResourceTypeParser.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/ResourceTypeParser.java
new file mode 100644
index 0000000..122a85c
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/ResourceTypeParser.java
@@ -0,0 +1,134 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+package org.apache.sling.scripting.bundle.tracker.internal;
+
+import org.apache.commons.lang3.StringUtils;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.osgi.framework.Version;
+
+/**
+ * The {@code ResourceTypeParser} provides methods for parsing resource type strings.
+ *
+ * <p>The following patterns are supported:</p>
+ * <ol>
+ * <li><tt>a/b/c</tt> - path-based</li>
+ * <li><tt>a/b/c/1.0.0</tt> - path-based, versioned</li>
+ * <li><tt>a.b.c</tt> - Java package name</li>
+ * <li><tt>a.b.c/1.0.0</tt> - Java package name, versioned</li>
+ * <li><tt>a</tt> - flat (sub-set of path-based)</li>
+ * </ol>
+ */
+final class ResourceTypeParser {
+
+ private ResourceTypeParser() {
+ }
+
+ /**
+ * The {@code ResourceType} class encapsulates the details about a resource type.
+ */
+ static class ResourceType {
+ private final String type;
+ private final String version;
+ private final String resourceLabel;
+
+ private ResourceType(@NotNull String type, @Nullable String version) {
+ this.type = type;
+ this.version = version;
+ if (type.lastIndexOf('/') != -1) {
+ resourceLabel = type.substring(type.lastIndexOf('/') + 1);
+ } else if (type.lastIndexOf('.') != -1) {
+ resourceLabel = type.substring(type.lastIndexOf('.') + 1);
+ } else {
+ resourceLabel = type;
+ }
+ }
+
+ /**
+ * Returns a resource type's label. The label is important for script selection, since it will provide the name of the main script
+ * for this resource type. For more details check the Apache Sling
+ * <a href="https://sling.apache.org/documentation/the-sling-engine/url-to-script-resolution.html#scripts-for-get-requests">URL to
+ * Script Resolution</a> page
+ *
+ * @return the resource type label
+ */
+ @NotNull
+ public String getResourceLabel() {
+ return resourceLabel;
+ }
+
+ /**
+ * Returns the resource type string, without any version information.
+ *
+ * @return the resource type string
+ */
+ @NotNull
+ String getType() {
+ return type;
+ }
+
+ /**
+ * Returns the version, if available.
+ *
+ * @return the version, if available; {@code null} otherwise
+ */
+ @Nullable
+ String getVersion() {
+ return version;
+ }
+ }
+
+ /**
+ * Given a {@code resourceTypeString}, this method will extract a {@link ResourceType} object.
+ * <p>The accepted patterns are:</p>
+ * <ol>
+ * <li><tt>a/b/c</tt> - path-based</li>
+ * <li><tt>a/b/c/1.0.0</tt> - path-based, versioned</li>
+ * <li><tt>a.b.c</tt> - Java package name</li>
+ * <li><tt>a.b.c/1.0.0</tt> - Java package name, versioned</li>
+ * <li><tt>a</tt> - flat (sub-set of path-based)</li>
+ * </ol>
+ *
+ * @param resourceTypeString the resource type string to parse
+ * @return a {@link ResourceType} object
+ * @throws IllegalArgumentException if the {@code resourceTypeString} cannot be parsed
+ */
+ @NotNull
+ static ResourceType parseResourceType(@NotNull String resourceTypeString) {
+ String type = StringUtils.EMPTY;
+ String version = null;
+ if (StringUtils.isNotEmpty(resourceTypeString)) {
+ int lastSlash = resourceTypeString.lastIndexOf('/');
+ if (lastSlash != -1 && !resourceTypeString.endsWith("/")) {
+ try {
+ version = Version.parseVersion(resourceTypeString.substring(lastSlash + 1)).toString();
+ type = resourceTypeString.substring(0, lastSlash);
+ } catch (IllegalArgumentException e) {
+ type = resourceTypeString;
+ }
+ } else {
+ type = resourceTypeString;
+ }
+ }
+ if (StringUtils.isEmpty(type)) {
+ throw new IllegalArgumentException(String.format("Cannot extract a type for the resourceTypeString %s.", resourceTypeString));
+ }
+ return new ResourceType(type, version);
+ }
+}
diff --git a/src/test/java/org/apache/sling/scripting/bundle/tracker/internal/ResourceTypeParserTest.java b/src/test/java/org/apache/sling/scripting/bundle/tracker/internal/ResourceTypeParserTest.java
new file mode 100644
index 0000000..47f92ef
--- /dev/null
+++ b/src/test/java/org/apache/sling/scripting/bundle/tracker/internal/ResourceTypeParserTest.java
@@ -0,0 +1,87 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+package org.apache.sling.scripting.bundle.tracker.internal;
+
+import org.apache.commons.lang3.StringUtils;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+public class ResourceTypeParserTest {
+
+ @Test
+ public void testSlashNoVersion() {
+ ResourceTypeParser.ResourceType t1 = ResourceTypeParser.parseResourceType("a/b/c");
+ assertEquals("a/b/c", t1.getType());
+ assertEquals("c", t1.getResourceLabel());
+ assertNull(t1.getVersion());
+ }
+
+ @Test
+ public void testSlashVersion() {
+ ResourceTypeParser.ResourceType t1 = ResourceTypeParser.parseResourceType("a/b/c/1.0.0");
+ assertEquals("a/b/c", t1.getType());
+ assertEquals("c", t1.getResourceLabel());
+ assertEquals("1.0.0", t1.getVersion());
+ }
+
+ @Test
+ public void testOneSegmentNoVersion() {
+ ResourceTypeParser.ResourceType t1 = ResourceTypeParser.parseResourceType("a");
+ assertEquals("a", t1.getType());
+ assertEquals("a", t1.getResourceLabel());
+ assertNull(t1.getVersion());
+ }
+
+ @Test
+ public void testOneSegmentVersion() {
+ ResourceTypeParser.ResourceType t1 = ResourceTypeParser.parseResourceType("a/1.2.3");
+ assertEquals("a", t1.getType());
+ assertEquals("a", t1.getResourceLabel());
+ assertEquals("1.2.3", t1.getVersion());
+ }
+
+ @Test
+ public void testDotNoVersion() {
+ ResourceTypeParser.ResourceType t1 = ResourceTypeParser.parseResourceType("a.b.c");
+ assertEquals("a.b.c", t1.getType());
+ assertEquals("c", t1.getResourceLabel());
+ assertNull(t1.getVersion());
+ }
+
+ @Test
+ public void testDotVersion() {
+ ResourceTypeParser.ResourceType t1 = ResourceTypeParser.parseResourceType("a.b.c/42.0.0");
+ assertEquals("a.b.c", t1.getType());
+ assertEquals("c", t1.getResourceLabel());
+ assertEquals("42.0.0", t1.getVersion());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testEmptyString() {
+ ResourceTypeParser.ResourceType t1 = ResourceTypeParser.parseResourceType(StringUtils.EMPTY);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testNull() {
+ ResourceTypeParser.ResourceType t1 = ResourceTypeParser.parseResourceType(null);
+ }
+
+}