FELIX-4545 : Implement Servlet Context Helper. Integrate resource handling

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1656075 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 e26535c..4662ca9 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
@@ -31,6 +31,7 @@
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.felix.http.base.internal.context.ExtServletContext;
+import org.apache.felix.http.base.internal.runtime.ContextInfo;
 import org.apache.felix.http.base.internal.runtime.FilterInfo;
 import org.apache.felix.http.base.internal.util.PatternUtil;
 
@@ -40,7 +41,9 @@
     private final FilterInfo filterInfo;
     private final Pattern[] patterns;
 
-    public FilterHandler(ExtServletContext context, Filter filter, FilterInfo filterInfo)
+    private final long contextServiceId;
+
+    public FilterHandler(final ContextInfo contextInfo, ExtServletContext context, Filter filter, FilterInfo filterInfo)
     {
         super(context, filterInfo.getInitParams(), filterInfo.getName());
         this.filter = filter;
@@ -53,6 +56,14 @@
         {
             this.patterns[i] = Pattern.compile(patterns[i]);
         }
+        if ( contextInfo != null )
+        {
+            this.contextServiceId = contextInfo.getServiceId();
+        }
+        else
+        {
+            this.contextServiceId = -1;
+        }
     }
 
     @Override
@@ -137,4 +148,9 @@
     public Pattern[] getPatterns() {
         return this.patterns;
     }
+
+    public long getContextServiceId()
+    {
+        return this.contextServiceId;
+    }
 }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerMapping.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerMapping.java
index fabf959..94e025f 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerMapping.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerMapping.java
@@ -35,7 +35,7 @@
  * Represents a Map-like structure that can map path-patterns to servlet/filter handlers, allowing
  * for easy access to those handlers, based on the match rules defined in section 12.1 of Servlet
  * 3.0 specification.
- * 
+ *
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
 public class HandlerMapping<V extends AbstractHandler>
@@ -48,12 +48,13 @@
      * <li>lastly all wildcard extension matches.</li>
      * </ol>
      * <p>
-     * Equal matches will first be sorted on length in descending order (longest patterns first), 
+     * Equal matches will first be sorted on length in descending order (longest patterns first),
      * and in case of equal lengths, they are sorted in natural (ascending) order.
      * </p>
      */
     static class PatternComparator implements Comparator<Pattern>
     {
+        @Override
         public int compare(Pattern p1, Pattern p2)
         {
             String ps1 = p1.pattern();
@@ -135,7 +136,7 @@
 
     /**
      * Creates a new {@link HandlerMapping} instance for the given elements.
-     * 
+     *
      * @param elements the elements to map, cannot be <code>null</code>.
      */
     public HandlerMapping(Collection<V> elements)
@@ -180,7 +181,7 @@
 
     /**
      * Returns all mapped elements.
-     * 
+     *
      * @return a collection of mapped elements, never <code>null</code>.
      */
     public Collection<V> getAllElements()
@@ -190,7 +191,7 @@
 
     /**
      * Returns all matching handlers for the given path.
-     * 
+     *
      * @param path the path that should match, cannot be <code>null</code>.
      * @return a {@link Collection} of all matching handlers, never <code>null</code>.
      */
@@ -208,7 +209,7 @@
      * <li>if the last segment in the URL path contains an extension (e.g. .jsp), the servlet container will try to match a servlet that
      *     handles requests for the extension. An extension is defined as the part of the last segment after the last '.' character.</li>
      * </ul>
-     * 
+     *
      * @param path the path that should match, cannot be <code>null</code>.
      * @return the best matching handler for the given path, or <code>null</code> in case no handler matched.
      */
@@ -243,7 +244,7 @@
 
     /**
      * Provides information on whether there are elements mapped or not.
-     * 
+     *
      * @return <code>true</code> if there is at least one element mapped, <code>false</code> otherwise.
      */
     public boolean hasElements()
@@ -253,10 +254,10 @@
 
     /**
      * Performs the actual matching, yielding a list of either the first or all matching patterns.
-     * 
-     * @param path the path to match, can be <code>null</code> in which case an empty string is 
+     *
+     * @param path the path to match, can be <code>null</code> in which case an empty string is
      *        used;
-     * @param firstOnly <code>true</code> if only the first matching pattern should be returned, 
+     * @param firstOnly <code>true</code> if only the first matching pattern should be returned,
      *        <code>false</code> if all matching patterns should be returned.
      * @return a list with matching elements, never <code>null</code>.
      */
@@ -309,7 +310,7 @@
                 }
             }
         }
-        
+
         // Make sure the results are properly sorted...
         Collections.sort(result);
 
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerRegistry.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerRegistry.java
index a95a7da..60cb8b2 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerRegistry.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerRegistry.java
@@ -122,6 +122,16 @@
             }
         }
 
+        // TODO - we should already check for the context when building up the result set
+        final Iterator<FilterHandler> i = result.iterator();
+        while ( i.hasNext() )
+        {
+            final FilterHandler handler = i.next();
+            if ( handler.getContextServiceId() != servletHandler.getContextServiceId() )
+            {
+                i.remove();
+            }
+        }
         return result.toArray(new FilterHandler[result.size()]);
     }
 
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceImpl.java b/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceImpl.java
index 9b34453..ee416b8 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceImpl.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceImpl.java
@@ -116,7 +116,7 @@
             // TODO create failure DTO if null
         }
 
-        FilterHandler handler = new FilterHandler(httpContext, filter, filterInfo);
+        FilterHandler handler = new FilterHandler(contextInfo, httpContext, filter, filterInfo);
         try {
             this.handlerRegistry.addFilter(handler);
         } catch (ServletException e) {
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/AbstractMapping.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/AbstractMapping.java
deleted file mode 100644
index 52c2c13..0000000
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/AbstractMapping.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.whiteboard;
-
-import java.util.Hashtable;
-
-import org.osgi.framework.Bundle;
-import org.osgi.service.http.HttpContext;
-import org.osgi.service.http.HttpService;
-
-abstract class AbstractMapping
-{
-    private final Bundle bundle;
-    private HttpContext context;
-    private final Hashtable<String, String> initParams;
-    private boolean registered;
-
-    protected AbstractMapping(final Bundle bundle)
-    {
-        this.bundle = bundle;
-        this.context = null;
-        this.initParams = new Hashtable<String, String>();
-        this.registered = false;
-    }
-
-    public Bundle getBundle()
-    {
-        return bundle;
-    }
-
-    public void setContext(HttpContext context)
-    {
-        this.context = context;
-    }
-
-    public final HttpContext getContext()
-    {
-        return this.context;
-    }
-
-    public final Hashtable<String, String> getInitParams()
-    {
-        return this.initParams;
-    }
-
-    boolean isRegistered()
-    {
-        return registered;
-    }
-
-    void setRegistered(boolean registered)
-    {
-        this.registered = registered;
-    }
-
-    public abstract void register(HttpService httpService);
-
-    public abstract void unregister(HttpService httpService);
-
-}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ExtenderManager.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ExtenderManager.java
index b87050e..a23ba03 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ExtenderManager.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ExtenderManager.java
@@ -17,42 +17,30 @@
 package org.apache.felix.http.base.internal.whiteboard;
 
 import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
 
-import org.apache.felix.http.base.internal.logger.SystemLogger;
 import org.apache.felix.http.base.internal.service.HttpServiceImpl;
 import org.apache.felix.http.base.internal.whiteboard.tracker.FilterTracker;
+import org.apache.felix.http.base.internal.whiteboard.tracker.ResourceTracker;
 import org.apache.felix.http.base.internal.whiteboard.tracker.ServletContextHelperTracker;
 import org.apache.felix.http.base.internal.whiteboard.tracker.ServletTracker;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.http.HttpService;
-import org.osgi.service.http.runtime.dto.ResourceDTO;
-import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
 import org.osgi.util.tracker.ServiceTracker;
 
+/**
+ * TODO - move code to ServletContextHelperManager
+ */
 public final class ExtenderManager
 {
-    static final String TYPE_RESOURCE = "r";
-
-    private final Map<String, AbstractMapping> mapping;
-
     private final ServletContextHelperManager contextManager;
 
-    private final HttpService httpService;
-
     private final ArrayList<ServiceTracker<?, ?>> trackers = new ArrayList<ServiceTracker<?, ?>>();
 
     public ExtenderManager(final HttpServiceImpl httpService, final BundleContext bundleContext)
     {
-        this.mapping = new HashMap<String, AbstractMapping>();
         this.contextManager = new ServletContextHelperManager(bundleContext, httpService);
-        this.httpService = httpService;
         addTracker(new FilterTracker(bundleContext, contextManager));
         addTracker(new ServletTracker(bundleContext, this.contextManager));
+        addTracker(new ResourceTracker(bundleContext, this.contextManager));
         addTracker(new ServletContextHelperTracker(bundleContext, this.contextManager));
     }
 
@@ -63,7 +51,6 @@
             t.close();
         }
         this.trackers.clear();
-        this.unregisterAll();
         this.contextManager.close();
     }
 
@@ -72,139 +59,4 @@
         this.trackers.add(tracker);
         tracker.open();
     }
-
-    static boolean isEmpty(final String value)
-    {
-        return value == null || value.length() == 0;
-    }
-
-    static boolean isEmpty(final String[] value)
-    {
-        return value == null || value.length == 0;
-    }
-
-    private String getStringProperty(ServiceReference ref, String key)
-    {
-        Object value = ref.getProperty(key);
-        return (value instanceof String) ? (String) value : null;
-    }
-
-    private String[] getStringArrayProperty(ServiceReference ref, String key)
-    {
-        Object value = ref.getProperty(key);
-
-        if (value instanceof String)
-        {
-            return new String[] { (String) value };
-        }
-        else if (value instanceof String[])
-        {
-            return (String[]) value;
-        }
-        else if (value instanceof Collection<?>)
-        {
-            Collection<?> collectionValues = (Collection<?>) value;
-            String[] values = new String[collectionValues.size()];
-
-            int i = 0;
-            for (Object current : collectionValues)
-            {
-                values[i++] = current != null ? String.valueOf(current) : null;
-            }
-
-            return values;
-        }
-
-        return null;
-    }
-
-    public void addResource(final ServiceReference ref)
-    {
-        final String[] pattern = getStringArrayProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PATTERN);
-        final String prefix = getStringProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PREFIX);
-
-        if (!isEmpty(pattern))
-        {
-            if ( !isEmpty(prefix))
-            {
-                for(final String p : pattern)
-                {
-                    // TODO : check if p is empty - and then log?
-                    final ResourceDTO resourceDTO = new ResourceDTO();
-                    resourceDTO.patterns = new String[] {p};
-                    resourceDTO.prefix = prefix;
-                    final ResourceMapping mapping = new ResourceMapping(ref.getBundle(), resourceDTO);
-                    this.addMapping(TYPE_RESOURCE, ref, mapping);
-                }
-            }
-            else
-            {
-                SystemLogger.debug("Ignoring Resource Service " + ref + ", " + HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PREFIX + " is missing or empty");
-            }
-        }
-        else
-        {
-            SystemLogger.debug("Ignoring Resource Service " + ref + ", " + HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PATTERN + " is missing or empty");
-        }
-    }
-
-    public void removeResource(final ServiceReference ref)
-    {
-        this.removeMapping(TYPE_RESOURCE, ref);
-    }
-
-    private synchronized void unregisterAll()
-    {
-        AbstractMapping[] mappings = null;
-        HttpService service;
-        synchronized (this)
-        {
-            service = this.httpService;
-            if (service != null)
-            {
-                Collection<AbstractMapping> values = this.mapping.values();
-                mappings = values.toArray(new AbstractMapping[values.size()]);
-            }
-        }
-        if (mappings != null)
-        {
-            for (AbstractMapping mapping : mappings)
-            {
-                mapping.unregister(service);
-            }
-        }
-    }
-
-    private synchronized void addMapping(final String servType, ServiceReference ref, AbstractMapping mapping)
-    {
-        this.mapping.put(ref.getProperty(Constants.SERVICE_ID).toString().concat(servType), mapping);
-        this.registerMapping(mapping);
-    }
-
-    private synchronized void removeMapping(final String servType, ServiceReference ref)
-    {
-        AbstractMapping mapping = this.mapping.remove(ref.getProperty(Constants.SERVICE_ID).toString().concat(servType));
-        if (mapping != null)
-        {
-            unregisterMapping(mapping);
-        }
-    }
-
-    private void registerMapping(AbstractMapping mapping)
-    {
-        HttpService httpService = this.httpService;
-        if (httpService != null)
-        {
-            mapping.register(httpService);
-        }
-    }
-
-    private void unregisterMapping(AbstractMapping mapping)
-    {
-        HttpService httpService = this.httpService;
-        if (httpService != null)
-        {
-            mapping.unregister(httpService);
-        }
-    }
  }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ResourceMapping.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ResourceMapping.java
deleted file mode 100644
index 72e371e..0000000
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ResourceMapping.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.whiteboard;
-
-import org.osgi.framework.Bundle;
-import org.osgi.service.http.HttpService;
-import org.osgi.service.http.NamespaceException;
-import org.osgi.service.http.runtime.dto.ResourceDTO;
-
-public final class ResourceMapping extends AbstractMapping
-{
-    private final ResourceDTO dto;
-
-    public ResourceMapping(final Bundle bundle, final ResourceDTO resourceDTO)
-    {
-        super(bundle);
-        this.dto = resourceDTO;
-    }
-
-    @Override
-    public void register(final HttpService httpService)
-    {
-        if (!isRegistered() && getContext() != null)
-        {
-            try {
-                httpService.registerResources(this.dto.patterns[0], this.dto.prefix, this.getContext());
-                this.setRegistered(true);
-            }
-            catch (final NamespaceException e)
-            {
-                // TODO Handle exception
-                e.printStackTrace();
-            }
-        }
-    }
-
-    @Override
-    public void unregister(final HttpService httpService)
-    {
-        if (isRegistered())
-        {
-            httpService.unregister(this.dto.patterns[0]);
-        }
-    }
-}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ServletContextHelperManager.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ServletContextHelperManager.java
index 28edf08..25aa62c 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ServletContextHelperManager.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ServletContextHelperManager.java
@@ -28,12 +28,14 @@
 import org.apache.felix.http.base.internal.runtime.AbstractInfo;
 import org.apache.felix.http.base.internal.runtime.ContextInfo;
 import org.apache.felix.http.base.internal.runtime.FilterInfo;
+import org.apache.felix.http.base.internal.runtime.ResourceInfo;
 import org.apache.felix.http.base.internal.runtime.ServletInfo;
 import org.apache.felix.http.base.internal.service.HttpServiceImpl;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceFactory;
 import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.http.NamespaceException;
 import org.osgi.service.http.context.ServletContextHelper;
 import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
 
@@ -105,6 +107,10 @@
                 {
                     this.registerFilter((FilterInfo)entry.getKey(), holder);
                 }
+                else if ( entry.getKey() instanceof ResourceInfo )
+                {
+                    this.registerResource((ResourceInfo)entry.getKey(), holder);
+                }
             }
         }
     }
@@ -125,6 +131,10 @@
                 {
                     this.unregisterFilter((FilterInfo)entry.getKey(), holder);
                 }
+                else if ( entry.getKey() instanceof ResourceInfo )
+                {
+                    this.unregisterResource((ResourceInfo)entry.getKey(), holder);
+                }
                 if ( entry.getValue().isEmpty() ) {
                     i.remove();
                 }
@@ -237,6 +247,29 @@
         this.httpService.unregisterFilter(holder.getInfo(), filterInfo);
     }
 
+    private void registerResource(final ResourceInfo resourceInfo, final ContextHolder holder)
+    {
+        final ServletContextHelper helper = holder.getContext(resourceInfo.getServiceReference().getBundle());
+        // TODO - use servlet context helper and move registration to http service
+        for(final String alias : resourceInfo.getPatterns())
+        {
+            try {
+                this.httpService.registerResources(alias, resourceInfo.getPrefix(), null);
+            } catch (NamespaceException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            }
+        }
+    }
+
+    private void unregisterResource(final ResourceInfo resourceInfo, final ContextHolder holder)
+    {
+        for(final String alias : resourceInfo.getPatterns())
+        {
+            this.httpService.unregister(alias);
+        }
+    }
+
     /**
      * Add a new servlet.
      * @param servletInfo The servlet info
@@ -328,4 +361,30 @@
             }
         }
     }
+
+    public void addResource(final ResourceInfo info) {
+        synchronized ( this.contextMap )
+        {
+            final List<ContextHolder> holderList = this.getMatchingContexts(info);
+            this.servicesMap.put(info, holderList);
+            for(final ContextHolder h : holderList)
+            {
+                this.registerResource(info, h);
+            }
+        }
+    }
+
+    public void removeResource(final ResourceInfo info) {
+        synchronized ( this.contextMap )
+        {
+            final List<ContextHolder> holderList = this.servicesMap.remove(info);
+            if ( holderList != null )
+            {
+                for(final ContextHolder h : holderList)
+                {
+                    this.unregisterResource(info, h);
+                }
+            }
+        }
+    }
 }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/AbstractTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/AbstractTracker.java
deleted file mode 100644
index c1707e6..0000000
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/AbstractTracker.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.whiteboard.tracker;
-
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Filter;
-import org.osgi.framework.ServiceReference;
-import org.osgi.util.tracker.ServiceTracker;
-
-public abstract class AbstractTracker<T> extends ServiceTracker
-{
-    public AbstractTracker(final BundleContext context, final Filter filter)
-    {
-        super(context, filter, null);
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public final Object addingService(final ServiceReference ref)
-    {
-        T service = (T) super.addingService(ref);
-        added(service, ref);
-        return service;
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public final void modifiedService(final ServiceReference ref, final Object service)
-    {
-        modified( (T)service, ref);
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public final void removedService(final ServiceReference ref, final Object service)
-    {
-        super.removedService(ref, service);
-        removed((T) service, ref);
-    }
-
-    protected abstract void modified(T service, ServiceReference ref);
-
-    protected abstract void added(T service, ServiceReference ref);
-
-    protected abstract void removed(T service, ServiceReference ref);
-}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ResourceTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ResourceTracker.java
index fdf6bb3..f1fc9b7 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ResourceTracker.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ResourceTracker.java
@@ -16,16 +16,18 @@
  */
 package org.apache.felix.http.base.internal.whiteboard.tracker;
 
-import org.apache.felix.http.base.internal.whiteboard.ExtenderManager;
+import org.apache.felix.http.base.internal.logger.SystemLogger;
+import org.apache.felix.http.base.internal.runtime.ResourceInfo;
+import org.apache.felix.http.base.internal.whiteboard.ServletContextHelperManager;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Filter;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
 
-public final class ResourceTracker extends AbstractTracker<Object>
+public final class ResourceTracker extends AbstractReferenceTracker<Object>
 {
-    private final ExtenderManager manager;
+    private final ServletContextHelperManager contextManager;
 
     private static Filter createFilter(final BundleContext btx)
     {
@@ -42,28 +44,34 @@
         return null; // we never get here - and if we get an NPE which is fine
     }
 
-    public ResourceTracker(final BundleContext context, final ExtenderManager manager)
+    public ResourceTracker(final BundleContext context, final ServletContextHelperManager manager)
     {
         super(context, createFilter(context));
-        this.manager = manager;
+        this.contextManager = manager;
     }
 
     @Override
-    protected void added(final Object service, final ServiceReference ref)
+    protected void added(final ServiceReference<Object> ref)
     {
-        this.manager.addResource(ref);
+        final ResourceInfo info = new ResourceInfo(ref);
+
+        if ( info.isValid() )
+        {
+            this.contextManager.addResource(info);
+        }
+        else
+        {
+            SystemLogger.debug("Ignoring Resource service " + ref);
+        }
     }
 
     @Override
-    protected void modified(final Object service, final ServiceReference ref)
+    protected void removed(final ServiceReference<Object> ref)
     {
-        removed(service, ref);
-        added(service, ref);
-    }
+        final ResourceInfo info = new ResourceInfo(ref);
 
-    @Override
-    protected void removed(final Object service, final ServiceReference ref)
-    {
-        this.manager.removeResource(ref);
-    }
-}
+        if ( info.isValid() )
+        {
+            this.contextManager.removeResource(info);
+        }
+    }}
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 445a5c0..93e9306 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
@@ -243,7 +243,7 @@
     private FilterHandler createHandler(String pattern, int ranking, final Map<String, String> initParams)
     {
         final FilterInfo info = new FilterInfo(null, pattern, ranking, initParams, this.filter, null);
-        return new FilterHandler(this.context, this.filter, info);
+        return new FilterHandler(null, this.context, this.filter, info);
     }
 
     private HttpServletRequest createServletRequest()