SLING-8170 - Allow Sling servlets to declare a resource super type

* the servlet resolver bundle should not provide Resources adaptable
to Servlets for the resources used to mark the sling:resourceSuperType
inheritance
diff --git a/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletResource.java b/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletResource.java
index 41375a5..3f3f7c0 100644
--- a/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletResource.java
+++ b/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletResource.java
@@ -88,14 +88,16 @@
 
     private String getServletName() {
         String servletName = null;
-        if (servlet.getServletConfig() != null) {
-            servletName = servlet.getServletConfig().getServletName();
-        }
-        if (servletName == null) {
-            servletName = servlet.getServletInfo();
-        }
-        if (servletName == null) {
-            servletName = servlet.getClass().getName();
+        if (servlet != null) {
+            if (servlet.getServletConfig() != null) {
+                servletName = servlet.getServletConfig().getServletName();
+            }
+            if (servletName == null) {
+                servletName = servlet.getServletInfo();
+            }
+            if (servletName == null) {
+                servletName = servlet.getClass().getName();
+            }
         }
         return servletName;
     }
@@ -103,14 +105,16 @@
     @Override
     @SuppressWarnings("unchecked")
     public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
-        if (type == Servlet.class) {
+        if (type == Servlet.class && servlet != null) {
             return (AdapterType) servlet; // unchecked cast
         } else if ( type == ValueMap.class ) {
             final Map<String, Object> props = new HashMap<>();
             props.put("sling:resourceType", this.getResourceType());
             props.put("sling:resourceSuperType", this.getResourceSuperType());
-            props.put("servletName", this.getServletName());
-            props.put("servletClass", this.servlet.getClass().getName());
+            if (servlet != null) {
+                props.put("servletName", this.getServletName());
+                props.put("servletClass", this.servlet.getClass().getName());
+            }
 
             return (AdapterType) new ValueMapDecorator(props); // unchecked cast
         }
diff --git a/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletResourceProvider.java b/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletResourceProvider.java
index fd284ce..0e90a55 100644
--- a/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletResourceProvider.java
+++ b/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletResourceProvider.java
@@ -34,11 +34,14 @@
 
     private final Set<String> resourcePaths;
     private final String resourceSuperType;
+    private final Set<String> resourceSuperTypeMarkers;
 
-    ServletResourceProvider(final Servlet servlet, final Set<String> resourcePaths, final String resourceSuperType) {
+    ServletResourceProvider(final Servlet servlet, final Set<String> resourcePaths,
+                            final Set<String> resourceSuperTypeMarkers, final String resourceSuperType) {
         this.servlet = servlet;
         this.resourcePaths = resourcePaths;
         this.resourceSuperType = resourceSuperType;
+        this.resourceSuperTypeMarkers = resourceSuperTypeMarkers;
     }
 
     @SuppressWarnings("unchecked")
@@ -49,6 +52,9 @@
             final Resource parent) {
         // only return a resource if the servlet has been assigned
         if (resourcePaths.contains(path)) {
+            if (resourceSuperTypeMarkers.contains(path)) {
+                return new ServletResource(ctx.getResourceResolver(), null, path, resourceSuperType);
+            }
             return new ServletResource(ctx.getResourceResolver(), servlet, path, resourceSuperType);
         }
 
diff --git a/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletResourceProviderFactory.java b/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletResourceProviderFactory.java
index 8b0e44c..2c43174 100644
--- a/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletResourceProviderFactory.java
+++ b/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletResourceProviderFactory.java
@@ -27,6 +27,7 @@
 import org.apache.commons.lang3.StringUtils;
 import org.apache.sling.api.resource.ResourceUtil;
 import org.apache.sling.api.servlets.HttpConstants;
+import org.apache.sling.api.servlets.ServletResolverConstants;
 import org.apache.sling.commons.osgi.PropertiesUtil;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.Constants;
@@ -146,16 +147,18 @@
             log.debug("create({}): Registering servlet for paths {}",
                     getServiceReferenceInfo(ref), pathSet);
         }
-        String resourceSuperType = PropertiesUtil.toString(ref.getProperty(SLING_SERVLET_RESOURCE_SUPER_TYPE), "");
+        String resourceSuperType = PropertiesUtil.toString(ref.getProperty(SLING_SERVLET_RESOURCE_SUPER_TYPE), null);
+        Set<String> resourceSuperTypeMarkers = new HashSet<>();
         if (StringUtils.isNotEmpty(resourceSuperType)) {
             for (String rt : PropertiesUtil.toStringArray(ref.getProperty(SLING_SERVLET_RESOURCE_TYPES))) {
                 if (!rt.startsWith("/")) {
                     rt = getPrefix(ref).concat(ResourceUtil.resourceTypeToPath(rt));
                 }
+                resourceSuperTypeMarkers.add(rt);
                 pathSet.add(rt);
             }
         }
-        return new ServletResourceProvider(servlet, pathSet, resourceSuperType);
+        return new ServletResourceProvider(servlet, pathSet, resourceSuperTypeMarkers, resourceSuperType);
     }
 
     /**
diff --git a/src/test/java/org/apache/sling/servlets/resolver/internal/resource/ServletResourceProviderCreateTest.java b/src/test/java/org/apache/sling/servlets/resolver/internal/resource/ServletResourceProviderCreateTest.java
index 9f09fbc..a4881de 100644
--- a/src/test/java/org/apache/sling/servlets/resolver/internal/resource/ServletResourceProviderCreateTest.java
+++ b/src/test/java/org/apache/sling/servlets/resolver/internal/resource/ServletResourceProviderCreateTest.java
@@ -20,6 +20,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 import java.util.Collections;
@@ -198,11 +199,17 @@
         assertEquals(2, paths.size());
         assertTrue(paths.contains(ROOT + RES_TYPE_PATH));
         assertTrue(paths.contains(ROOT + RES_TYPE_PATH + "/html" + ServletResourceProviderFactory.SERVLET_PATH_EXTENSION));
-        Resource servletResource = srp.getResource(Mockito.mock(ResolveContext.class), "/apps/sling/sample",
+        Resource superTypeMarkingResource = srp.getResource(Mockito.mock(ResolveContext.class), "/apps/sling/sample",
+                Mockito.mock(ResourceContext.class), Mockito.mock(Resource.class));
+        assertNotNull(superTypeMarkingResource);
+        assertEquals("this/is/a/test", superTypeMarkingResource.getResourceSuperType());
+        assertNull(superTypeMarkingResource.adaptTo(Servlet.class));
+
+        Resource servletResource = srp.getResource(Mockito.mock(ResolveContext.class), "/apps/sling/sample/html.servlet",
                 Mockito.mock(ResourceContext.class), Mockito.mock(Resource.class));
         assertNotNull(servletResource);
         assertEquals("this/is/a/test", servletResource.getResourceSuperType());
-
+        assertEquals(TEST_SERVLET, servletResource.adaptTo(Servlet.class));
     }
 
 }