FELIX-5109 : Wrong path matching for http whiteboard service

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1715214 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PathResolverFactory.java b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PathResolverFactory.java
index 16b67c8..9891292 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PathResolverFactory.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PathResolverFactory.java
@@ -22,6 +22,7 @@
 import javax.annotation.Nonnull;
 
 import org.apache.felix.http.base.internal.handler.ServletHandler;
+import org.apache.felix.http.base.internal.service.HttpServiceFactory;
 
 /**
  * The path resolver factory creates a path resolver for a pattern.
@@ -55,7 +56,11 @@
         {
             return new PathMatcher(handler, pattern);
         }
-        return new ExactAndPathMatcher(handler, pattern);
+        else if ( handler != null && handler.getContextServiceId() == HttpServiceFactory.HTTP_SERVICE_CONTEXT_SERVICE_ID )
+        {
+            return new ExactAndPathMatcher(handler, pattern);
+        }
+        return new ExactMatcher(handler, pattern);
     }
 
     public static @Nonnull PathResolver createRegexMatcher(@Nonnull final String regex)
@@ -184,7 +189,7 @@
 
         public ExactAndPathMatcher(final ServletHandler handler, final String pattern)
         {
-            super(handler, pattern, 4);
+            super(handler, pattern, 5);
             this.path = pattern;
             this.prefix = pattern.concat("/");
         }
@@ -221,18 +226,63 @@
         }
     }
 
+    public static final class ExactMatcher extends AbstractMatcher
+    {
+        private final String path;
+
+        public ExactMatcher(final ServletHandler handler, final String pattern)
+        {
+            super(handler, pattern, 5);
+            this.path = pattern;
+        }
+
+        @Override
+        public PathResolution resolve(final String uri) {
+            if ( uri.equals(this.path) )
+            {
+                final PathResolution pr = new PathResolution();
+                pr.servletPath = uri;
+                pr.pathInfo = null;
+                pr.requestURI = uri;
+                pr.handler = this.getServletHandler();
+
+                return pr;
+            }
+            return null;
+        }
+
+        @Override
+        public int getOrdering()
+        {
+            return this.path.length();
+        }
+    }
+
     public static final class PathMatcher extends AbstractMatcher
     {
         private final String prefix;
 
+        private final String path;
+
         public PathMatcher(final ServletHandler handler, final String pattern)
         {
             super(handler, pattern, 4);
             this.prefix = pattern.substring(0, pattern.length() - 1);
+            this.path = pattern.substring(0, pattern.length() - 2);
         }
 
         @Override
         public PathResolution resolve(final String uri) {
+            if ( uri.equals(this.path) )
+            {
+                final PathResolution pr = new PathResolution();
+                pr.servletPath = this.path;
+                pr.pathInfo = null;
+                pr.requestURI = uri;
+                pr.handler = this.getServletHandler();
+
+                return pr;
+            }
             if ( uri.startsWith(this.prefix) )
             {
                 final PathResolution pr = new PathResolution();
diff --git a/http/base/src/test/java/org/apache/felix/http/base/internal/registry/PathResolverFactoryTest.java b/http/base/src/test/java/org/apache/felix/http/base/internal/registry/PathResolverFactoryTest.java
index d110440..46dbe23 100644
--- a/http/base/src/test/java/org/apache/felix/http/base/internal/registry/PathResolverFactoryTest.java
+++ b/http/base/src/test/java/org/apache/felix/http/base/internal/registry/PathResolverFactoryTest.java
@@ -62,4 +62,17 @@
         assertResult(pr, "/foo/bar", "/foo/bar", null);
         assertResult(pr, "/foo", "/foo", null);
     }
+
+    @Test public void testPathMatcher()
+    {
+        final PathResolver pr = PathResolverFactory.createPatternMatcher(null, "/*");
+        assertNotNull(pr);
+
+        assertResult(pr, "/foo", "", "/foo");
+        assertResult(pr, "/foo/bar", "", "/foo/bar");
+
+        assertResult(pr, "/", "", "/");
+
+        assertResult(pr, "", "", null);
+    }
 }
diff --git a/http/base/src/test/java/org/apache/felix/http/base/internal/registry/ServletRegistryTest.java b/http/base/src/test/java/org/apache/felix/http/base/internal/registry/ServletRegistryTest.java
index a158c7a..3791fe3 100644
--- a/http/base/src/test/java/org/apache/felix/http/base/internal/registry/ServletRegistryTest.java
+++ b/http/base/src/test/java/org/apache/felix/http/base/internal/registry/ServletRegistryTest.java
@@ -26,6 +26,10 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
 import javax.servlet.Servlet;
 import javax.servlet.ServletConfig;
 import javax.servlet.ServletException;
@@ -171,6 +175,20 @@
         assertEmpty(dto, holder);
     }
 
+    @Test public void testMatcherOrdering()  throws InvalidSyntaxException
+    {
+        final ServletHandler h1 = createServletHandler(1L, 0, "/foo");
+        final ServletHandler h2 = createServletHandler(2L, 0, "/foo/*");
+
+        final List<PathResolver> resolvers = new ArrayList<PathResolver>();
+        resolvers.add(PathResolverFactory.createPatternMatcher(h1, "/foo"));
+        resolvers.add(PathResolverFactory.createPatternMatcher(h2, "/foo/*"));
+
+        Collections.sort(resolvers);
+        assertEquals("/foo", resolvers.get(0).getPattern());
+        assertEquals("/foo/*", resolvers.get(1).getPattern());
+    }
+
     @Test public void testServletOrdering() throws InvalidSyntaxException
     {
         final ServletHandler h1 = createServletHandler(1L, 0, "/foo");
@@ -195,16 +213,16 @@
         assertNull(pr);
 
         pr = reg.resolve("/foo/bar");
-        assertEquals("/foo/*", pr.patterns[0]);
-        assertEquals(h2, pr.handler);
+        assertEquals("/foo", pr.patterns[0]);
+        assertEquals(h1, pr.handler);
 
         pr = reg.resolve("/foo/rsrc");
         assertEquals("/foo/rsrc", pr.patterns[0]);
         assertEquals(h3, pr.handler);
 
         pr = reg.resolve("/foo/rsrc/some");
-        assertEquals("/foo/rsrc/*", pr.patterns[0]);
-        assertEquals(h4, pr.handler);
+        assertEquals("/foo/rsrc", pr.patterns[0]);
+        assertEquals(h3, pr.handler);
 
         pr = reg.resolve("/other");
         assertEquals("/other", pr.patterns[0]);
diff --git a/http/itest/src/test/java/org/apache/felix/http/itest/ServletPatternTest.java b/http/itest/src/test/java/org/apache/felix/http/itest/ServletPatternTest.java
index a91df7d..e8cfb30 100644
--- a/http/itest/src/test/java/org/apache/felix/http/itest/ServletPatternTest.java
+++ b/http/itest/src/test/java/org/apache/felix/http/itest/ServletPatternTest.java
@@ -257,4 +257,18 @@
         assertTrue(initLatch.await(5, TimeUnit.SECONDS));
         assertContent("servlet2", createURL("/a/b/test/servlet"));
     }
+
+    @Test
+    public void pathMatchingTest() throws Exception
+    {
+        setupLatches(1);
+
+        setupContext("contextA", "/a");
+
+        setupServlet("servlet1", new String[]{ "/servlet/*" }, 1, "contextA");
+
+        assertTrue(initLatch.await(5, TimeUnit.SECONDS));
+        assertContent("servlet1", createURL("/a/servlet/foo"));
+        assertContent("servlet1", createURL("/a/servlet"));
+    }
 }