You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cz...@apache.org on 2015/05/21 09:40:56 UTC

svn commit: r1680752 - in /felix/trunk/http/base/src: main/java/org/apache/felix/http/base/internal/registry/ main/java/org/apache/felix/http/base/internal/runtime/dto/ test/java/org/apache/felix/http/base/internal/registry/

Author: cziegeler
Date: Thu May 21 07:40:55 2015
New Revision: 1680752

URL: http://svn.apache.org/r1680752
Log:
FELIX-4893 : Replace filter registry with path resolvers

Added:
    felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/registry/FilterRegistryTest.java   (with props)
    felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/registry/PathResolverFactoryTest.java   (with props)
Removed:
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/FilterHandlerMapping.java
Modified:
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/FilterRegistry.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/HandlerRegistry.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PathResolverFactory.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ServletRegistry.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/RequestInfoDTOBuilder.java

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/FilterRegistry.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/FilterRegistry.java?rev=1680752&r1=1680751&r2=1680752&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/FilterRegistry.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/FilterRegistry.java Thu May 21 07:40:55 2015
@@ -17,12 +17,13 @@
 package org.apache.felix.http.base.internal.registry;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
-import java.util.Iterator;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.TreeMap;
+import java.util.TreeSet;
 import java.util.concurrent.ConcurrentHashMap;
 
 import javax.annotation.CheckForNull;
@@ -39,30 +40,49 @@ import org.osgi.service.http.runtime.dto
 
 /**
  * The filter registry keeps track of all filter mappings for a single servlet context.
+ *
+ * TODO - we should sort the statusMapping by result and ranking, keeping the active filters first,
+ *        highest ranking first. This would allow to stop iterating and avoid sorting the result.
  */
 public final class FilterRegistry
 {
-    private volatile FilterHandlerMapping filterMapping = new FilterHandlerMapping();
-
+    /** Map of all filter registrations. */
     private final Map<FilterInfo, FilterRegistrationStatus> statusMapping = new ConcurrentHashMap<FilterInfo, FilterRegistrationStatus>();
 
     private static final class FilterRegistrationStatus
     {
         public int result;
         public FilterHandler handler;
+        public PathResolver[] resolvers;
     }
 
     public synchronized void addFilter(@Nonnull final FilterHandler handler)
     {
         final int result = handler.init();
-        if ( result == -1 )
-        {
-            this.filterMapping = this.filterMapping.add(handler);
-        }
         final FilterRegistrationStatus status = new FilterRegistrationStatus();
         status.result = result;
         status.handler = handler;
 
+        if ( result == -1 )
+        {
+            final List<PathResolver> resolvers = new ArrayList<PathResolver>();
+            if ( handler.getFilterInfo().getPatterns() != null )
+            {
+                for(final String pattern : handler.getFilterInfo().getPatterns() ) {
+                    resolvers.add(PathResolverFactory.createPatternMatcher(null, pattern));
+                }
+            }
+            if ( handler.getFilterInfo().getRegexs() != null )
+            {
+                for(final String regex : handler.getFilterInfo().getRegexs() ) {
+                    resolvers.add(PathResolverFactory.createRegexMatcher(regex));
+                }
+            }
+            Collections.sort(resolvers);
+
+            status.resolvers = resolvers.toArray(new PathResolver[resolvers.size()]);
+        }
+
         statusMapping.put(handler.getFilterInfo(), status);
     }
 
@@ -73,7 +93,6 @@ public final class FilterRegistry
         {
             if ( status.result == -1 )
             {
-                this.filterMapping = this.filterMapping.remove(status.handler);
                 if (destroy)
                 {
                     status.handler.dispose();
@@ -82,56 +101,69 @@ public final class FilterRegistry
         }
     }
 
-    public FilterHandler[] getFilterHandlers(@CheckForNull final ServletHandler handler,
-            @CheckForNull DispatcherType dispatcherType,
-            @Nonnull String requestURI)
+    /**
+     * Get all filters handling the request.
+     * Filters are applied to the url and/or the servlet
+     * @param handler Optional servlet handler
+     * @param dispatcherType The dispatcher type
+     * @param requestURI The request uri
+     * @return The array of filter handlers, might be empty.
+     */
+    public @Nonnull FilterHandler[] getFilterHandlers(@CheckForNull final ServletHandler handler,
+            @Nonnull final DispatcherType dispatcherType,
+            @Nonnull final String requestURI)
     {
-        // See Servlet 3.0 specification, section 6.2.4...
-        final List<FilterHandler> result = new ArrayList<FilterHandler>();
-        result.addAll(this.filterMapping.getAllMatches(requestURI));
-
-        // TODO this is not the most efficient/fastest way of doing this...
-        Iterator<FilterHandler> iter = result.iterator();
-        while (iter.hasNext())
-        {
-            if (!referencesDispatcherType(iter.next(), dispatcherType))
-            {
-                iter.remove();
-            }
-        }
+        final Set<FilterHandler> result = new TreeSet<FilterHandler>();
 
-        final String servletName = (handler != null) ? handler.getName() : null;
-        // TODO this is not the most efficient/fastest way of doing this...
-        for (FilterHandler filterHandler : this.filterMapping.values())
+        for(final FilterRegistrationStatus status : this.statusMapping.values())
         {
-            if (referencesServletByName(filterHandler, servletName))
+            if (referencesDispatcherType(status.handler, dispatcherType) )
             {
-                result.add(filterHandler);
+                boolean added = false;
+                for(final PathResolver resolver : status.resolvers)
+                {
+                    if ( resolver.resolve(requestURI) != null )
+                    {
+                        result.add(status.handler);
+                        added = true;
+                        break;
+                    }
+                }
+                // check for servlet name
+                final String servletName = (handler != null) ? handler.getName() : null;
+                if ( !added && servletName != null && status.handler.getFilterInfo().getServletNames() != null )
+                {
+                    for(final String name : status.handler.getFilterInfo().getServletNames())
+                    {
+                        if ( servletName.equals(name) )
+                        {
+                            result.add(status.handler);
+                            added = true;
+                            break;
+                        }
+                    }
+                }
+
             }
         }
 
         return result.toArray(new FilterHandler[result.size()]);
     }
 
-    private boolean referencesDispatcherType(FilterHandler handler, DispatcherType dispatcherType)
-    {
-        if (dispatcherType == null)
-        {
-            return true;
-        }
-        return Arrays.asList(handler.getFilterInfo().getDispatcher()).contains(dispatcherType);
-    }
-
-    private boolean referencesServletByName(FilterHandler handler, String servletName)
+    /**
+     * Check if the filter is registered for the required dispatcher type
+     * @param handler The filter handler
+     * @param dispatcherType The requested dispatcher type
+     * @return {@code true} if the filter can be applied.
+     */
+    private boolean referencesDispatcherType(final FilterHandler handler, final DispatcherType dispatcherType)
     {
-        if (servletName == null)
+        for(final DispatcherType dt : handler.getFilterInfo().getDispatcher())
         {
-            return false;
-        }
-        String[] names = handler.getFilterInfo().getServletNames();
-        if (names != null && names.length > 0)
-        {
-            return Arrays.asList(names).contains(servletName);
+            if ( dt == dispatcherType )
+            {
+                return true;
+            }
         }
         return false;
     }

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/HandlerRegistry.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/HandlerRegistry.java?rev=1680752&r1=1680751&r2=1680752&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/HandlerRegistry.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/HandlerRegistry.java Thu May 21 07:40:55 2015
@@ -198,7 +198,7 @@ public final class HandlerRegistry
     }
 
     public FilterHandler[] getFilters(@Nonnull final ServletResolution pr,
-            final DispatcherType dispatcherType,
+            @Nonnull final DispatcherType dispatcherType,
             @Nonnull String requestURI)
     {
         if ( pr != null && pr.handlerRegistry != null )

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PathResolverFactory.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PathResolverFactory.java?rev=1680752&r1=1680751&r2=1680752&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PathResolverFactory.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PathResolverFactory.java Thu May 21 07:40:55 2015
@@ -16,6 +16,11 @@
  */
 package org.apache.felix.http.base.internal.registry;
 
+import java.util.regex.Pattern;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+
 import org.apache.felix.http.base.internal.handler.ServletHandler;
 
 /**
@@ -32,7 +37,7 @@ import org.apache.felix.http.base.intern
  */
 public abstract class PathResolverFactory {
 
-    public static PathResolver create(final ServletHandler handler, final String pattern)
+    public static @Nonnull PathResolver createPatternMatcher(@CheckForNull final ServletHandler handler, @Nonnull final String pattern)
     {
         if ( pattern.length() == 0 )
         {
@@ -53,6 +58,11 @@ public abstract class PathResolverFactor
         return new ExactAndPathMatcher(handler, pattern);
     }
 
+    public static @Nonnull PathResolver createRegexMatcher(@Nonnull final String regex)
+    {
+        return new RegexMatcher(regex);
+    }
+
     public static abstract class AbstractMatcher implements PathResolver
     {
         private final int ranking;
@@ -100,12 +110,12 @@ public abstract class PathResolverFactor
 
         @Override
         public PathResolution resolve(final String uri) {
-            if ( uri.length() == 0 )
+            if ( uri.length() == 0 || uri.equals("/") )
             {
                 final PathResolution pr = new PathResolution();
                 pr.pathInfo = "/";
                 pr.servletPath = "";
-                pr.requestURI = "";
+                pr.requestURI = uri;
                 pr.handler = this.getServletHandler();
 
                 return pr;
@@ -241,4 +251,35 @@ public abstract class PathResolverFactor
             return this.extension.length();
         }
     }
+
+    public static final class RegexMatcher extends AbstractMatcher
+    {
+        private final Pattern pattern;
+
+        public RegexMatcher(final String regex)
+        {
+            super(null, 0);
+            this.pattern = Pattern.compile(regex);
+        }
+
+        @Override
+        public @CheckForNull PathResolution resolve(@Nonnull final String uri) {
+            if ( pattern.matcher(uri).matches() )
+            {
+                final PathResolution pr = new PathResolution();
+                pr.pathInfo = null;
+                pr.servletPath = uri;
+                pr.requestURI = uri;
+
+                return pr;
+            }
+            return null;
+        }
+
+        @Override
+        public int getOrdering()
+        {
+            return this.pattern.toString().length();
+        }
+    }
 }

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java?rev=1680752&r1=1680751&r2=1680752&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java Thu May 21 07:40:55 2015
@@ -16,6 +16,7 @@
  */
 package org.apache.felix.http.base.internal.registry;
 
+import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 import javax.servlet.DispatcherType;
 
@@ -167,8 +168,9 @@ public final class PerContextHandlerRegi
         this.filterRegistry.removeFilter(info, destroy);
     }
 
-    public FilterHandler[] getFilterHandlers(final ServletHandler servletHandler,
-            DispatcherType dispatcherType, String requestURI)
+    public FilterHandler[] getFilterHandlers(@CheckForNull final ServletHandler servletHandler,
+            @Nonnull final DispatcherType dispatcherType,
+            @Nonnull final String requestURI)
     {
         return this.filterRegistry.getFilterHandlers(servletHandler, dispatcherType, requestURI);
     }

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ServletRegistry.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ServletRegistry.java?rev=1680752&r1=1680751&r2=1680752&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ServletRegistry.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ServletRegistry.java Thu May 21 07:40:55 2015
@@ -147,45 +147,51 @@ public final class ServletRegistry
 
     private void addToNameMapping(final ServletHandler handler)
     {
-        final String servletName = handler.getName();
-        List<ServletHandler> list = this.servletsByName.get(servletName);
-        if ( list == null )
+        if ( !handler.getServletInfo().isResource() )
         {
-            list = new ArrayList<ServletHandler>();
-            list.add(handler);
-        }
-        else
-        {
-            list = new ArrayList<ServletHandler>(list);
-            list.add(handler);
-            Collections.sort(list);
+            final String servletName = handler.getName();
+            List<ServletHandler> list = this.servletsByName.get(servletName);
+            if ( list == null )
+            {
+                list = new ArrayList<ServletHandler>();
+                list.add(handler);
+            }
+            else
+            {
+                list = new ArrayList<ServletHandler>(list);
+                list.add(handler);
+                Collections.sort(list);
+            }
+            this.servletsByName.put(servletName, list);
         }
-        this.servletsByName.put(servletName, list);
     }
 
     private synchronized void removeFromNameMapping(final String servletName, final ServletHandler handler)
     {
-        List<ServletHandler> list = this.servletsByName.get(servletName);
-        if ( list != null )
+        if ( !handler.getServletInfo().isResource() )
         {
-            final List<ServletHandler> newList = new ArrayList<ServletHandler>(list);
-            final Iterator<ServletHandler> i = newList.iterator();
-            while ( i.hasNext() )
+            List<ServletHandler> list = this.servletsByName.get(servletName);
+            if ( list != null )
             {
-                final ServletHandler s = i.next();
-                if ( s == handler )
+                final List<ServletHandler> newList = new ArrayList<ServletHandler>(list);
+                final Iterator<ServletHandler> i = newList.iterator();
+                while ( i.hasNext() )
                 {
-                    i.remove();
-                    break;
+                    final ServletHandler s = i.next();
+                    if ( s == handler )
+                    {
+                        i.remove();
+                        break;
+                    }
+                }
+                if ( newList.isEmpty() )
+                {
+                    this.servletsByName.remove(servletName);
+                }
+                else
+                {
+                    this.servletsByName.put(servletName, newList);
                 }
-            }
-            if ( newList.isEmpty() )
-            {
-                this.servletsByName.remove(servletName);
-            }
-            else
-            {
-                this.servletsByName.put(servletName, newList);
             }
         }
     }
@@ -290,7 +296,7 @@ public final class ServletRegistry
         final int result = handler.init();
         if ( result == -1 )
         {
-            final PathResolver reg = PathResolverFactory.create(handler, pattern);
+            final PathResolver reg = PathResolverFactory.createPatternMatcher(handler, pattern);
             this.activeServletMappings.put(pattern, reg);
 
             // add ok

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/RequestInfoDTOBuilder.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/RequestInfoDTOBuilder.java?rev=1680752&r1=1680751&r2=1680752&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/RequestInfoDTOBuilder.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/RequestInfoDTOBuilder.java Thu May 21 07:40:55 2015
@@ -16,6 +16,8 @@
  */
 package org.apache.felix.http.base.internal.runtime.dto;
 
+import javax.servlet.DispatcherType;
+
 import org.apache.felix.http.base.internal.handler.FilterHandler;
 import org.apache.felix.http.base.internal.registry.HandlerRegistry;
 import org.apache.felix.http.base.internal.registry.PathResolution;
@@ -59,7 +61,7 @@ public final class RequestInfoDTOBuilder
             requestInfoDTO.servletDTO.patterns = pr.patterns;
         }
 
-        final FilterHandler[] filterHandlers = registry.getFilters(pr, null, path);
+        final FilterHandler[] filterHandlers = registry.getFilters(pr, DispatcherType.REQUEST, path);
         requestInfoDTO.filterDTOs = FilterDTOBuilder.build(filterHandlers);
 
         return requestInfoDTO;

Added: felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/registry/FilterRegistryTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/registry/FilterRegistryTest.java?rev=1680752&view=auto
==============================================================================
--- felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/registry/FilterRegistryTest.java (added)
+++ felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/registry/FilterRegistryTest.java Thu May 21 07:40:55 2015
@@ -0,0 +1,152 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.registry;
+
+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 static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import javax.servlet.DispatcherType;
+import javax.servlet.Filter;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+
+import org.apache.felix.http.base.internal.context.ExtServletContext;
+import org.apache.felix.http.base.internal.handler.FilterHandler;
+import org.apache.felix.http.base.internal.handler.HttpServiceFilterHandler;
+import org.apache.felix.http.base.internal.runtime.FilterInfo;
+import org.apache.felix.http.base.internal.runtime.dto.FailedDTOHolder;
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.runtime.dto.ServletContextDTO;
+import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
+
+public class FilterRegistryTest {
+
+    private final FilterRegistry reg = new FilterRegistry();
+
+    private void assertEmpty(final ServletContextDTO dto, final FailedDTOHolder holder)
+    {
+        assertNull(dto.filterDTOs);
+        assertTrue(holder.failedFilterDTOs.isEmpty());
+    }
+
+    private void clear(final ServletContextDTO dto, final FailedDTOHolder holder)
+    {
+        dto.filterDTOs = null;
+        holder.failedFilterDTOs.clear();
+    }
+
+    @Test public void testSingleFilter() throws InvalidSyntaxException, ServletException
+    {
+        final FailedDTOHolder holder = new FailedDTOHolder();
+        final ServletContextDTO dto = new ServletContextDTO();
+
+        // check DTO
+        reg.getRuntimeInfo(dto, holder.failedFilterDTOs);
+        assertEmpty(dto, holder);
+
+        // register filter
+        final FilterHandler h1 = createFilterHandler(1L, 0, "/foo");
+        reg.addFilter(h1);
+
+        verify(h1.getFilter()).init(Matchers.any(FilterConfig.class));
+
+        // one entry in DTO
+        clear(dto, holder);
+        reg.getRuntimeInfo(dto, holder.failedFilterDTOs);
+        assertTrue(holder.failedFilterDTOs.isEmpty());
+        assertNotNull(dto.filterDTOs);
+        assertEquals(1, dto.filterDTOs.length);
+        assertEquals(1, dto.filterDTOs[0].patterns.length);
+        assertEquals("/foo", dto.filterDTOs[0].patterns[0]);
+
+        // remove filter
+        final Filter f = h1.getFilter();
+        reg.removeFilter(h1.getFilterInfo(), true);
+        verify(f).destroy();
+
+        // empty again
+        clear(dto, holder);
+        reg.getRuntimeInfo(dto, holder.failedFilterDTOs);
+        assertEmpty(dto, holder);
+    }
+
+    @Test public void testFilterOrdering() throws InvalidSyntaxException
+    {
+        final FilterHandler h1 = createFilterHandler(1L, 20, "/foo");
+        reg.addFilter(h1);
+        final FilterHandler h2 = createFilterHandler(2L, 10, "/foo");
+        reg.addFilter(h2);
+        final FilterHandler h3 = createFilterHandler(3L, 30, "/foo");
+        reg.addFilter(h3);
+        final FilterHandler h4 = createFilterHandler(4L, 0, "/other");
+        reg.addFilter(h4);
+        final FilterHandler h5 = createFilterHandler(5L, 90, "/foo");
+        reg.addFilter(h5);
+
+        final FilterHandler[] handlers = reg.getFilterHandlers(null, DispatcherType.REQUEST, "/foo");
+        assertEquals(4, handlers.length);
+        assertEquals(h5.getFilterInfo(), handlers[0].getFilterInfo());
+        assertEquals(h3.getFilterInfo(), handlers[1].getFilterInfo());
+        assertEquals(h1.getFilterInfo(), handlers[2].getFilterInfo());
+        assertEquals(h2.getFilterInfo(), handlers[3].getFilterInfo());
+
+        // cleanup
+        reg.removeFilter(h1.getFilterInfo(), true);
+        reg.removeFilter(h2.getFilterInfo(), true);
+        reg.removeFilter(h3.getFilterInfo(), true);
+        reg.removeFilter(h4.getFilterInfo(), true);
+        reg.removeFilter(h5.getFilterInfo(), true);
+    }
+
+    private static FilterInfo createFilterInfo(final long id, final int ranking, final String... paths) throws InvalidSyntaxException
+    {
+        final BundleContext bCtx = mock(BundleContext.class);
+        when(bCtx.createFilter(Matchers.anyString())).thenReturn(null);
+        final Bundle bundle = mock(Bundle.class);
+        when(bundle.getBundleContext()).thenReturn(bCtx);
+
+        final ServiceReference<Filter> ref = mock(ServiceReference.class);
+        when(ref.getBundle()).thenReturn(bundle);
+        when(ref.getProperty(Constants.SERVICE_ID)).thenReturn(id);
+        when(ref.getProperty(Constants.SERVICE_RANKING)).thenReturn(ranking);
+        when(ref.getProperty(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN)).thenReturn(paths);
+        when(ref.getPropertyKeys()).thenReturn(new String[0]);
+        final FilterInfo si = new FilterInfo(ref);
+
+        return si;
+    }
+
+    private static FilterHandler createFilterHandler(final long id, final int ranking, final String... paths) throws InvalidSyntaxException
+    {
+        final FilterInfo si = createFilterInfo(id, ranking, paths);
+        final ExtServletContext ctx = mock(ExtServletContext.class);
+        final Filter filter = mock(Filter.class);
+
+        return new HttpServiceFilterHandler(7, ctx, si, filter);
+    }
+}

Propchange: felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/registry/FilterRegistryTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/registry/FilterRegistryTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/registry/FilterRegistryTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/registry/PathResolverFactoryTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/registry/PathResolverFactoryTest.java?rev=1680752&view=auto
==============================================================================
--- felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/registry/PathResolverFactoryTest.java (added)
+++ felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/registry/PathResolverFactoryTest.java Thu May 21 07:40:55 2015
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.registry;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+
+public class PathResolverFactoryTest {
+
+    private void assertResult(final PathResolver resolver,
+            final String path,
+            final String expectedServletPath,
+            final String expectedPathInfo)
+    {
+        final PathResolution pr = resolver.resolve(path);
+        assertNotNull(pr);
+        assertEquals(path, pr.requestURI);
+        assertEquals(expectedServletPath, pr.servletPath);
+        if ( expectedPathInfo == null )
+        {
+            assertNull(pr.pathInfo);
+        }
+        else
+        {
+            assertEquals(expectedPathInfo, pr.pathInfo);
+        }
+    }
+
+    @Test public void testRootMatching()
+    {
+        final PathResolver pr = PathResolverFactory.createPatternMatcher(null, "");
+        assertNotNull(pr);
+
+        assertResult(pr, "/", "", "/");
+        assertResult(pr, "", "", "/");
+
+        assertNull(pr.resolve("/foo"));
+    }
+
+    @Test public void testDefaultMatcher()
+    {
+        final PathResolver pr = PathResolverFactory.createPatternMatcher(null, "/");
+        assertNotNull(pr);
+
+        assertResult(pr, "/foo/bar", "/foo/bar", null);
+        assertResult(pr, "/foo", "/foo", null);
+    }
+}

Propchange: felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/registry/PathResolverFactoryTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/registry/PathResolverFactoryTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/registry/PathResolverFactoryTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain