FELIX-1999 Handle ServletRequest.getPathInfo() possibly being null. For both filters and servlets, we assume the path info is "/" in case the actual path info is reported as null from the servlet container.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@901600 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java
index 7dc3f01..fe3ca0e 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java
@@ -41,7 +41,7 @@
     {
         return this.filter;
     }
-    
+
     public void init()
         throws ServletException
     {
@@ -57,6 +57,11 @@
 
     public boolean matches(String uri)
     {
+        // assume root if uri is null
+        if (uri == null) {
+            uri = "/";
+        }
+
         return uri.matches(this.pattern);
     }
 
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java
index e2e14a8..5b46cf0 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java
@@ -62,7 +62,9 @@
 
     public boolean matches(String uri)
     {
-        if (this.alias.equals("/")) {
+        if (uri == null) {
+            return this.alias.equals("/");
+        } else if (this.alias.equals("/")) {
             return uri.startsWith(this.alias);
         } else {
             return uri.equals(this.alias) || uri.startsWith(this.alias + "/");
@@ -95,5 +97,5 @@
     public int compareTo(ServletHandler other)
     {
         return other.alias.length() - this.alias.length();
-    }    
+    }
 }
diff --git a/http/base/src/test/java/org/apache/felix/http/base/internal/handler/FilterHandlerTest.java b/http/base/src/test/java/org/apache/felix/http/base/internal/handler/FilterHandlerTest.java
index dcce161..67db1ce 100644
--- a/http/base/src/test/java/org/apache/felix/http/base/internal/handler/FilterHandlerTest.java
+++ b/http/base/src/test/java/org/apache/felix/http/base/internal/handler/FilterHandlerTest.java
@@ -20,10 +20,6 @@
 import org.junit.Before;
 import org.junit.Assert;
 import org.mockito.Mockito;
-import org.mockito.MockSettings;
-import org.mockito.stubbing.Answer;
-import org.hamcrest.Matcher;
-
 import javax.servlet.Filter;
 import javax.servlet.FilterConfig;
 import javax.servlet.FilterChain;
@@ -67,11 +63,23 @@
     {
         FilterHandler h1 = createHandler("/a/b", 0);
         FilterHandler h2 = createHandler("/a/b/.+", 0);
+        FilterHandler h3 = createHandler("/", 0);
+        FilterHandler h4 = createHandler("/.*", 0);
 
+        Assert.assertFalse(h1.matches(null));
+        Assert.assertFalse(h1.matches("/a"));
         Assert.assertTrue(h1.matches("/a/b"));
         Assert.assertFalse(h1.matches("/a/b/c"));
+        Assert.assertFalse(h2.matches(null));
+        Assert.assertFalse(h1.matches("/a"));
         Assert.assertTrue(h2.matches("/a/b/c"));
         Assert.assertFalse(h2.matches("/a/b/"));
+        Assert.assertTrue(h3.matches(null));
+        Assert.assertTrue(h3.matches("/"));
+        Assert.assertFalse(h3.matches("/a/b/"));
+        Assert.assertTrue(h4.matches(null));
+        Assert.assertTrue(h4.matches("/"));
+        Assert.assertTrue(h4.matches("/a/b/"));
     }
 
     @Test
@@ -141,4 +149,37 @@
         Mockito.verify(chain, Mockito.never()).doFilter(req, res);
         Mockito.verify(res).sendError(HttpServletResponse.SC_FORBIDDEN);
     }
+
+    @Test
+    public void testHandleNotFoundContextRoot()
+        throws Exception
+    {
+        FilterHandler h1 = createHandler("/a", 0);
+        HttpServletRequest req = Mockito.mock(HttpServletRequest.class);
+        HttpServletResponse res = Mockito.mock(HttpServletResponse.class);
+        FilterChain chain = Mockito.mock(FilterChain.class);
+
+        Mockito.when(req.getPathInfo()).thenReturn(null);
+        h1.handle(req, res, chain);
+
+        Mockito.verify(this.filter, Mockito.never()).doFilter(req, res, chain);
+        Mockito.verify(chain).doFilter(req, res);
+    }
+
+    @Test
+    public void testHandleFoundContextRoot()
+        throws Exception
+    {
+        FilterHandler h1 = createHandler("/", 0);
+        HttpServletRequest req = Mockito.mock(HttpServletRequest.class);
+        HttpServletResponse res = Mockito.mock(HttpServletResponse.class);
+        FilterChain chain = Mockito.mock(FilterChain.class);
+        Mockito.when(this.context.handleSecurity(req, res)).thenReturn(true);
+
+        Mockito.when(req.getPathInfo()).thenReturn(null);
+        h1.handle(req, res, chain);
+
+        Mockito.verify(this.filter).doFilter(req, res, chain);
+        Mockito.verify(chain, Mockito.never()).doFilter(req, res);
+    }
 }
diff --git a/http/base/src/test/java/org/apache/felix/http/base/internal/handler/ServletHandlerTest.java b/http/base/src/test/java/org/apache/felix/http/base/internal/handler/ServletHandlerTest.java
index d0a44a4..eb7124d 100644
--- a/http/base/src/test/java/org/apache/felix/http/base/internal/handler/ServletHandlerTest.java
+++ b/http/base/src/test/java/org/apache/felix/http/base/internal/handler/ServletHandlerTest.java
@@ -41,12 +41,12 @@
     {
         return createHandler("/dummy");
     }
-    
+
     private ServletHandler createHandler(String alias)
     {
         return new ServletHandler(this.context, this.servlet, alias);
     }
-    
+
     @Test
     public void testCompare()
     {
@@ -62,6 +62,8 @@
     {
         ServletHandler h1 = createHandler("/a/b");
 
+        Assert.assertFalse(h1.matches(null));
+        Assert.assertFalse(h1.matches("/"));
         Assert.assertFalse(h1.matches("/a/"));
         Assert.assertTrue(h1.matches("/a/b"));
         Assert.assertTrue(h1.matches("/a/b/"));
@@ -102,7 +104,7 @@
 
     @Test
     public void testHandleFound()
-        throws Exception
+    throws Exception
     {
         ServletHandler h1 = createHandler("/a");
         HttpServletRequest req = Mockito.mock(HttpServletRequest.class);
@@ -114,7 +116,7 @@
 
         Assert.assertTrue(result);
         Mockito.verify(this.servlet).service(Mockito.any(HttpServletRequest.class),
-                Mockito.any(HttpServletResponse.class));
+            Mockito.any(HttpServletResponse.class));
     }
 
     @Test
@@ -133,4 +135,37 @@
         Mockito.verify(this.servlet, Mockito.never()).service(req, res);
         Mockito.verify(res).sendError(HttpServletResponse.SC_FORBIDDEN);
     }
+
+    @Test
+    public void testHandleNotFoundContextRoot()
+        throws Exception
+    {
+        ServletHandler h1 = createHandler("/a");
+        HttpServletRequest req = Mockito.mock(HttpServletRequest.class);
+        HttpServletResponse res = Mockito.mock(HttpServletResponse.class);
+        Mockito.when(this.context.handleSecurity(req, res)).thenReturn(true);
+
+        Mockito.when(req.getPathInfo()).thenReturn(null);
+        boolean result = h1.handle(req, res);
+
+        Assert.assertFalse(result);
+        Mockito.verify(this.servlet, Mockito.never()).service(req, res);
+    }
+
+    @Test
+    public void testHandleFoundContextRoot()
+        throws Exception
+    {
+        ServletHandler h1 = createHandler("/");
+        HttpServletRequest req = Mockito.mock(HttpServletRequest.class);
+        HttpServletResponse res = Mockito.mock(HttpServletResponse.class);
+        Mockito.when(this.context.handleSecurity(req, res)).thenReturn(true);
+
+        Mockito.when(req.getPathInfo()).thenReturn(null);
+        boolean result = h1.handle(req, res);
+
+        Assert.assertTrue(result);
+        Mockito.verify(this.servlet).service(Mockito.any(HttpServletRequest.class),
+                Mockito.any(HttpServletResponse.class));
+    }
 }