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

[sling-org-apache-sling-servlets-resolver] branch master updated: SLING-9222 - Support requiring empty extensions or selectors in paths.strict mode

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

bdelacretaz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-servlets-resolver.git


The following commit(s) were added to refs/heads/master by this push:
     new bf4040d  SLING-9222 - Support requiring empty extensions or selectors in paths.strict mode
bf4040d is described below

commit bf4040d04f7eb69f4929c4d3ee75eb422b3592bd
Author: Bertrand Delacretaz <bd...@apache.org>
AuthorDate: Thu Mar 19 15:04:18 2020 +0100

    SLING-9222 - Support requiring empty extensions or selectors in paths.strict mode
---
 .../internal/PathBasedServletAcceptor.java         | 42 +++++++++++----
 .../internal/PathBasedServletAcceptorTest.java     | 60 +++++++++++++++++++++-
 2 files changed, 91 insertions(+), 11 deletions(-)

diff --git a/src/main/java/org/apache/sling/servlets/resolver/internal/PathBasedServletAcceptor.java b/src/main/java/org/apache/sling/servlets/resolver/internal/PathBasedServletAcceptor.java
index 1fea703..5da3f6e 100644
--- a/src/main/java/org/apache/sling/servlets/resolver/internal/PathBasedServletAcceptor.java
+++ b/src/main/java/org/apache/sling/servlets/resolver/internal/PathBasedServletAcceptor.java
@@ -23,6 +23,7 @@ import java.util.Arrays;
 import javax.servlet.Servlet;
 import javax.servlet.ServletConfig;
 
+import org.apache.commons.lang3.ArrayUtils;
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.servlets.ServletResolverConstants;
 import org.apache.sling.engine.RequestUtil;
@@ -41,6 +42,16 @@ class PathBasedServletAcceptor {
     // TODO should be in ServletResolverConstants
     private static final String STRICT_PATHS_SERVICE_PROPERTY = "sling.servlet.paths.strict";
 
+    // Used to indicate "accept only an empty set of selectors or extensions - should not be
+    // a valid selector or extension to avoid collisions
+    private static final String EMPTY_VALUE = ".EMPTY.";
+
+    static class InvalidPropertyException extends RuntimeException {
+        InvalidPropertyException(String reason) {
+            super(reason);
+        }
+    }
+
     boolean accept(SlingHttpServletRequest request, Servlet servlet) {
         // Get OSGi service properties from the SlingServletConfig
         final ServletConfig rawCfg = servlet.getServletConfig();
@@ -56,9 +67,9 @@ class PathBasedServletAcceptor {
         final Object strictPaths = config.getServiceProperty(STRICT_PATHS_SERVICE_PROPERTY);
         if(strictPaths != null && Boolean.valueOf(strictPaths.toString())) {
             accepted = 
-                accept(servletName, config, ServletResolverConstants.SLING_SERVLET_EXTENSIONS, request.getRequestPathInfo().getExtension())
-                && accept(servletName, config, ServletResolverConstants.SLING_SERVLET_SELECTORS, request.getRequestPathInfo().getSelectors())
-                && accept(servletName, config, ServletResolverConstants.SLING_SERVLET_METHODS, request.getMethod());
+                accept(servletName, config, ServletResolverConstants.SLING_SERVLET_EXTENSIONS, true, request.getRequestPathInfo().getExtension())
+                && accept(servletName, config, ServletResolverConstants.SLING_SERVLET_SELECTORS, true, request.getRequestPathInfo().getSelectors())
+                && accept(servletName, config, ServletResolverConstants.SLING_SERVLET_METHODS, false, request.getMethod());
         }
 
         LOGGER.debug("accepted={} for {}", accepted, servletName);
@@ -66,23 +77,34 @@ class PathBasedServletAcceptor {
         return accepted;
     }
 
-    private boolean accept(String servletName, SlingServletConfig config, String servicePropertyKey, String ... requestValues) {
+    private boolean accept(String servletName, SlingServletConfig config, String servicePropertyKey, boolean emptyValueApplies, String ... requestValues) {
         final String [] propValues = toStringArray(config.getServiceProperty(servicePropertyKey));
         if(propValues == null) {
             LOGGER.debug("Property {} is null or empty, not checking that value for {}", servicePropertyKey, servletName);
             return true;
         }
 
-        // requestValues must match at least one value in propValue
         boolean accepted = false;
-        for(String rValue : requestValues) {
-            for(String pValue : propValues) {
-                if(rValue != null && rValue.equals(pValue)) {
-                    accepted = true;
-                    break;
+        if(propValues.length == 1 && EMPTY_VALUE.equals(propValues[0])) {
+            // If supported for this service property, request value must be empty
+            if(!emptyValueApplies) {
+                throw new InvalidPropertyException("Special value " + EMPTY_VALUE
+                + "  is not valid for the " + servicePropertyKey + " service property");
+            } else {
+                accepted = requestValues.length == 0 || (requestValues.length == 1 && requestValues[0] == null);
+            }
+        } else {
+            // requestValues must match at least one value in propValue
+            for(String rValue : requestValues) {
+                for(String pValue : propValues) {
+                    if(rValue != null && rValue.equals(pValue)) {
+                        accepted = true;
+                        break;
+                    }
                 }
             }
         }
+
         LOGGER.debug("accepted={} for property {} and servlet {}", accepted, servicePropertyKey, servletName);
         return accepted;
     }
diff --git a/src/test/java/org/apache/sling/servlets/resolver/internal/PathBasedServletAcceptorTest.java b/src/test/java/org/apache/sling/servlets/resolver/internal/PathBasedServletAcceptorTest.java
index 5fd43aa..0e4bd23 100644
--- a/src/test/java/org/apache/sling/servlets/resolver/internal/PathBasedServletAcceptorTest.java
+++ b/src/test/java/org/apache/sling/servlets/resolver/internal/PathBasedServletAcceptorTest.java
@@ -45,6 +45,8 @@ public class PathBasedServletAcceptorTest {
 
     public static final String [] STRING_ARRAY = new String[0];
 
+    public static final String V_EMPTY = ".EMPTY.";
+
     private final PathBasedServletAcceptor acceptor = new PathBasedServletAcceptor();
 
     private class TestCase {
@@ -248,10 +250,66 @@ public class PathBasedServletAcceptorTest {
     }
 
     @Test
+    public void testEmptyExtensionAndSelectorWithEmpty() {
+        new TestCase()
+        .withServiceProperty(ServletResolverTestSupport.P_STRICT_PATHS, true)
+        .withServiceProperty(ServletResolverTestSupport.P_EXTENSIONS, V_EMPTY)
+        .withServiceProperty(ServletResolverTestSupport.P_SELECTORS, V_EMPTY)
+        .assertAccept(true);
+    }
+
+    @Test
+    public void testEmptyExtensionAndSelectorWithSelector() {
+        new TestCase()
+        .withServiceProperty(ServletResolverTestSupport.P_STRICT_PATHS, true)
+        .withServiceProperty(ServletResolverTestSupport.P_EXTENSIONS, V_EMPTY)
+        .withServiceProperty(ServletResolverTestSupport.P_SELECTORS, V_EMPTY)
+        .withSelector("someSel")
+        .assertAccept(false);
+    }
+
+    @Test
+    public void testEmptyExtensionAndSelectorWithExtension() {
+        new TestCase()
+        .withServiceProperty(ServletResolverTestSupport.P_STRICT_PATHS, true)
+        .withServiceProperty(ServletResolverTestSupport.P_EXTENSIONS, V_EMPTY)
+        .withServiceProperty(ServletResolverTestSupport.P_SELECTORS, V_EMPTY)
+        .withExtension("someExt")
+        .assertAccept(false);
+    }
+
+    @Test
+    public void testEmptyExtensionSpecificSelector() {
+        new TestCase()
+        .withServiceProperty(ServletResolverTestSupport.P_STRICT_PATHS, true)
+        .withServiceProperty(ServletResolverTestSupport.P_EXTENSIONS, V_EMPTY)
+        .withServiceProperty(ServletResolverTestSupport.P_SELECTORS, "someSel")
+        .withSelector("someSel")
+        .assertAccept(true);
+    }
+
+    @Test
+    public void testEmptySelectorSpecificExtension() {
+        new TestCase()
+        .withServiceProperty(ServletResolverTestSupport.P_STRICT_PATHS, true)
+        .withServiceProperty(ServletResolverTestSupport.P_EXTENSIONS, "someExt")
+        .withServiceProperty(ServletResolverTestSupport.P_SELECTORS, V_EMPTY)
+        .withExtension("someExt")
+        .assertAccept(true);
+    }
+
+    @Test(expected = PathBasedServletAcceptor.InvalidPropertyException.class)
+    public void testEmptyMethodException() {
+        new TestCase()
+        .withServiceProperty(ServletResolverTestSupport.P_STRICT_PATHS, true)
+        .withServiceProperty(ServletResolverTestSupport.P_METHODS, V_EMPTY)
+        .assertAccept(true);
+    }
+
+    @Test
     public void testNoSlingServletConfig() {
         final Servlet s = mock(Servlet.class);
         when(s.getServletConfig()).thenReturn(mock(ServletConfig.class));
         assertTrue(acceptor.accept(null, s));
     }
-
 }