Add default dispatcher for resource types without versions and fix dependency lookup with versions
diff --git a/pom.xml b/pom.xml
index 25ee3d5..dc8ff4c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -270,7 +270,7 @@
                         <configuration>
                             <usePomDependencies>true</usePomDependencies>
                             <attachArtifact>false</attachArtifact>
-                             <shouldBlockUntilKeyIsPressed>true</shouldBlockUntilKeyIsPressed>
+                             <!-- <shouldBlockUntilKeyIsPressed>true</shouldBlockUntilKeyIsPressed> -->
                             <servers>
                                 <server>
                                     <id>singleinstance</id>
diff --git a/src/main/java/org/apache/sling/scripting/resolver/internal/BundledScriptServlet.java b/src/main/java/org/apache/sling/scripting/resolver/internal/BundledScriptServlet.java
index 0bd91a6..0c1f0ca 100644
--- a/src/main/java/org/apache/sling/scripting/resolver/internal/BundledScriptServlet.java
+++ b/src/main/java/org/apache/sling/scripting/resolver/internal/BundledScriptServlet.java
@@ -52,20 +52,22 @@
     private final BundledScriptFinder m_bundledScriptFinder;
     private final ScriptContextProvider m_scriptContextProvider;
     private final String m_delegatedResourceType;
+    private final Set<String> m_wiredResourceTypes;
 
     private Map<String, Script> scriptsMap = new HashMap<>();
     private ReadWriteLock lock = new ReentrantReadWriteLock();
 
-    BundledScriptServlet(BundledScriptFinder bundledScriptFinder, Bundle bundle, ScriptContextProvider scriptContextProvider) {
-        this(bundledScriptFinder, bundle, scriptContextProvider, null);
+    BundledScriptServlet(BundledScriptFinder bundledScriptFinder, Bundle bundle, ScriptContextProvider scriptContextProvider, Set<String> wiredResourceTypes) {
+        this(bundledScriptFinder, bundle, scriptContextProvider, null, wiredResourceTypes );
     }
 
     BundledScriptServlet(BundledScriptFinder bundledScriptFinder, Bundle bundle, ScriptContextProvider scriptContextProvider, String
-            overridingResourceType) {
+            overridingResourceType, Set<String> wiredResourceTypes) {
         m_bundle = bundle;
         m_bundledScriptFinder = bundledScriptFinder;
         m_scriptContextProvider = scriptContextProvider;
         m_delegatedResourceType = overridingResourceType;
+        m_wiredResourceTypes = wiredResourceTypes;
     }
 
     @Override
@@ -112,7 +114,7 @@
                 lock.readLock().unlock();
             }
             if (script != null) {
-                RequestWrapper requestWrapper = new RequestWrapper(request, getWiredResourceTypes());
+                RequestWrapper requestWrapper = new RequestWrapper(request, m_wiredResourceTypes);
                 ScriptContext scriptContext = m_scriptContextProvider.prepareScriptContext(requestWrapper, response, script);
                 try {
                     script.eval(scriptContext);
@@ -135,28 +137,4 @@
         return request.getResource().getResourceType() + (StringUtils.isNotEmpty(selectorString) ? ":" + selectorString : "") +
                 (StringUtils.isNotEmpty(requestExtension) ? ":" + requestExtension : "");
     }
-
-    private Set<String> getWiredResourceTypes() {
-        Set<String> wiredResourceTypes = new HashSet<>();
-        BundleWiring bundleWiring = m_bundle.adapt(BundleWiring.class);
-        bundleWiring.getProvidedWires(BundledScriptTracker.NS_SLING_RESOURCE_TYPE).forEach(
-                bundleWire -> {
-                    String resourceType = (String) bundleWire.getCapability().getAttributes().get(BundledScriptTracker
-                            .NS_SLING_RESOURCE_TYPE);
-                    Version version = (Version) bundleWire.getCapability().getAttributes().get(BundledScriptTracker
-                            .AT_VERSION);
-                    wiredResourceTypes.add(resourceType + (version == null ? "" : "/" + version.toString()));
-                }
-        );
-        bundleWiring.getRequiredWires(BundledScriptTracker.NS_SLING_RESOURCE_TYPE).forEach(
-                bundleWire -> {
-                    String resourceType = (String) bundleWire.getCapability().getAttributes().get(BundledScriptTracker
-                            .NS_SLING_RESOURCE_TYPE);
-                    Version version = (Version) bundleWire.getCapability().getAttributes().get(BundledScriptTracker
-                            .AT_VERSION);
-                    wiredResourceTypes.add(resourceType + (version == null ? "" : "/" + version.toString()));
-                }
-        );
-        return wiredResourceTypes;
-    }
 }
diff --git a/src/main/java/org/apache/sling/scripting/resolver/internal/BundledScriptTracker.java b/src/main/java/org/apache/sling/scripting/resolver/internal/BundledScriptTracker.java
index 406a225..e70ca8a 100644
--- a/src/main/java/org/apache/sling/scripting/resolver/internal/BundledScriptTracker.java
+++ b/src/main/java/org/apache/sling/scripting/resolver/internal/BundledScriptTracker.java
@@ -18,24 +18,44 @@
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 package org.apache.sling.scripting.resolver.internal;
 
+import java.io.IOException;
+import java.lang.reflect.Array;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
 import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.List;
 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;
 
+import javax.servlet.GenericServlet;
+import javax.servlet.RequestDispatcher;
 import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
 
 import org.apache.commons.lang3.StringUtils;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.request.RequestDispatcherOptions;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.api.resource.ResourceWrapper;
+import org.apache.sling.api.resource.SyntheticResource;
 import org.apache.sling.api.servlets.ServletResolverConstants;
 import org.apache.sling.commons.osgi.PropertiesUtil;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleEvent;
+import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.framework.Version;
 import org.osgi.framework.wiring.BundleCapability;
@@ -103,8 +123,6 @@
                 {
                     Hashtable<String, Object> properties = new Hashtable<>();
 
-                    List<ServiceRegistration<Servlet>> result = new ArrayList<>();
-
                     Map<String, Object> attributes = cap.getAttributes();
                     String resourceType = (String) attributes.get(NS_SLING_RESOURCE_TYPE);
 
@@ -145,26 +163,39 @@
                         ).findFirst();
                     }
 
+                    List<ServiceRegistration<Servlet>> regs = new ArrayList<>();
+
                     if (optionalWire.isPresent()) {
                         BundleWire extendsWire = optionalWire.get();
                         Map<String, Object> wireCapabilityAttributes = extendsWire.getCapability().getAttributes();
                         String wireResourceType = (String) wireCapabilityAttributes.get(NS_SLING_RESOURCE_TYPE);
                         Version wireResourceTypeVersion = (Version) wireCapabilityAttributes.get(AT_VERSION);
-                        result.add(bundle.getBundleContext().registerService(
+                        regs.add(bundle.getBundleContext().registerService(
                             Servlet.class,
                             new BundledScriptServlet(bundledScriptFinder, optionalWire.get().getProvider().getBundle(),
-                                scriptContextProvider, wireResourceType + (StringUtils.isNotEmpty(wireResourceType) ? "/" +
-                                wireResourceTypeVersion.toString() : "")),
+                                scriptContextProvider, wireResourceType + (wireResourceTypeVersion != null ? "/" +
+                                wireResourceTypeVersion.toString() : ""), getWiredResourceTypes(
+                                    new HashSet<>(Arrays.asList((String) attributes.get(NS_SLING_RESOURCE_TYPE), wireResourceType)),
+                                    new HashSet<>(Arrays.asList(resourceType, wireResourceType + (wireResourceTypeVersion != null ? "/" +
+                                        wireResourceTypeVersion.toString() : ""))),
+                                    bundle,optionalWire.get().getProvider().getBundle())),
                             properties
                         ));
                     }
                     else
                     {
-                        result.add(bundle.getBundleContext()
-                            .registerService(Servlet.class, new BundledScriptServlet(bundledScriptFinder, bundle, scriptContextProvider),
+                        regs.add(bundle.getBundleContext()
+                            .registerService(Servlet.class, new BundledScriptServlet(bundledScriptFinder, bundle, scriptContextProvider,
+                                    getWiredResourceTypes(new HashSet<>(Arrays.asList((String) attributes.get(NS_SLING_RESOURCE_TYPE))),
+                                        new HashSet<>(Arrays.asList(resourceType)),bundle)),
                                 properties));
                     }
-                    return result.stream();
+                    if (version != null)
+                    {
+                        properties.put(ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES, attributes.get(NS_SLING_RESOURCE_TYPE));
+                        regs.add(m_context.registerService(Servlet.class, new DispatcherServlet((String) attributes.get(NS_SLING_RESOURCE_TYPE)), properties));
+                    }
+                    return regs.stream();
                 }).collect(Collectors.toList());
             } else {
                 return null;
@@ -174,6 +205,94 @@
         }
     }
 
+
+
+    private Set<String> getWiredResourceTypes(Set<String> rts, Set<String> initial, Bundle... bundles) {
+        Set<String> wiredResourceTypes = new HashSet<>();
+        wiredResourceTypes.addAll(initial);
+        for (Bundle bundle : bundles)
+        {
+            BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);
+            bundleWiring.getCapabilities(BundledScriptTracker.NS_SLING_RESOURCE_TYPE).forEach(
+                cap ->
+                {
+                    String resourceType = (String) cap.getAttributes().get(BundledScriptTracker
+                        .NS_SLING_RESOURCE_TYPE);
+                    Version version = (Version) cap.getAttributes().get(BundledScriptTracker
+                        .AT_VERSION);
+                    if (!rts.contains(resourceType))
+                    {
+                        wiredResourceTypes.add(resourceType + (version == null ? "" : "/" + version.toString()));
+                    }
+                }
+            );
+            bundleWiring.getRequiredWires(BundledScriptTracker.NS_SLING_RESOURCE_TYPE).forEach(
+                bundleWire ->
+                {
+                    String resourceType = (String) bundleWire.getCapability().getAttributes().get(BundledScriptTracker
+                        .NS_SLING_RESOURCE_TYPE);
+                    Version version = (Version) bundleWire.getCapability().getAttributes().get(BundledScriptTracker
+                        .AT_VERSION);
+                    if (!rts.contains(resourceType))
+                    {
+                        wiredResourceTypes.add(resourceType + (version == null ? "" : "/" + version.toString()));
+                    }
+                }
+            );
+        }
+        return wiredResourceTypes;
+    }
+
+    private Hashtable<String, Object> toProperties(ServiceRegistration<?> reg)
+    {
+        Hashtable<String, Object> result = new Hashtable<>();
+        ServiceReference<?> ref = reg.getReference();
+
+        set(ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES, ref, result);
+        set(ServletResolverConstants.SLING_SERVLET_EXTENSIONS, ref, result);
+        set(ServletResolverConstants.SLING_SERVLET_SELECTORS, ref, result);
+        set(ServletResolverConstants.SLING_SERVLET_METHODS, ref, result);
+
+        return result;
+    }
+
+    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];
+        }
+    }
+
+    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;
+        }
+    }
+
+    private void set(String key, ServiceReference<?> ref, Hashtable<String, Object> props)
+    {
+        Object value = ref.getProperty(key);
+        if (value != null)
+        {
+            props.put(key, value);
+        }
+    }
+
     @Override
     public void modifiedBundle(Bundle bundle, BundleEvent event, List<ServiceRegistration<Servlet>> regs) {
         LOGGER.warn(String.format("Unexpected modified event: %s for bundle %s", event.toString(), bundle.toString()));
@@ -185,4 +304,69 @@
         regs.forEach(ServiceRegistration::unregister);
     }
 
+    private class DispatcherServlet extends GenericServlet
+    {
+        private final String m_rt;
+
+        DispatcherServlet(String rt)
+        {
+            m_rt = rt;
+        }
+
+        @Override
+        public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
+        {
+            SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) req;
+
+            Optional<ServiceRegistration<Servlet>> target = m_tracker.getTracked().values().stream().flatMap(List::stream)
+                .filter(
+                    ((Predicate<ServiceRegistration<Servlet>>) reg -> reg.getReference().getBundle().equals(m_context.getBundle())).negate()
+                )
+                .filter(reg -> getResourceTypeVersion(reg.getReference()) != null)
+                .filter(reg ->
+                {
+                    Hashtable<String, Object> props = toProperties(reg);
+                    if (getResourceType(props).equals(m_rt))
+                    {
+                        if (Arrays.asList(PropertiesUtil.toStringArray(props.get(ServletResolverConstants.SLING_SERVLET_SELECTORS), new String[0]))
+                            .containsAll(Arrays.asList(slingRequest.getRequestPathInfo().getSelectors()))
+                            &&
+                            Arrays.asList(PropertiesUtil.toStringArray(props.get(ServletResolverConstants.SLING_SERVLET_METHODS), new String[]{"GET", "HEAD"}))
+                                .contains(slingRequest.getMethod())
+                            &&
+                            Arrays.asList(PropertiesUtil.toStringArray(props.get(ServletResolverConstants.SLING_SERVLET_EXTENSIONS), new String[]{"html"}))
+                                .contains(slingRequest.getRequestPathInfo().getExtension() == null ? "html" : slingRequest.getRequestPathInfo().getExtension() ))
+                        {
+                            return true;
+                        }
+                    }
+                    return false;
+                })
+                .sorted(Comparator.comparing(reg -> new Version(getResourceTypeVersion(reg.getReference())), Comparator.reverseOrder()))
+                .findFirst();
+
+            if (target.isPresent())
+            {
+                String rt = (String) target.get().getReference().getProperty(ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES);
+                RequestDispatcherOptions options = new RequestDispatcherOptions();
+                options.setForceResourceType(rt);
+
+                System.out.println("found: " + rt);
+                RequestDispatcher dispatcher = slingRequest.getRequestDispatcher(slingRequest.getResource(), options);
+                if (dispatcher != null)
+                {
+                    dispatcher.forward(req, res);
+                }
+                else
+                {
+                    ((SlingHttpServletResponse) res).sendError(HttpServletResponse.SC_NOT_FOUND);
+                }
+            }
+            else
+            {
+                System.out.println("Not found");
+                ((SlingHttpServletResponse) res).sendError(HttpServletResponse.SC_NOT_FOUND);
+            }
+        }
+    }
 }
diff --git a/src/main/java/org/apache/sling/scripting/resolver/internal/RequestWrapper.java b/src/main/java/org/apache/sling/scripting/resolver/internal/RequestWrapper.java
index f1ad7c0..536f3bb 100644
--- a/src/main/java/org/apache/sling/scripting/resolver/internal/RequestWrapper.java
+++ b/src/main/java/org/apache/sling/scripting/resolver/internal/RequestWrapper.java
@@ -42,6 +42,17 @@
         if (resource == null) {
             return null;
         }
+        if (StringUtils.isEmpty(options.getForceResourceType()))
+        {
+            if (!StringUtils.isEmpty(resource.getResourceType()))
+            {
+                options.setForceResourceType(resource.getResourceType());
+            }
+            else if (!StringUtils.isEmpty(resource.getResourceSuperType()))
+            {
+                options.setForceResourceType(resource.getResourceSuperType());
+            }
+        }
         RequestDispatcherOptions processedOptions = processOptions(options);
         return super.getRequestDispatcher(resource, processedOptions);
     }