FELIX-4060 : Implement HTTP Service Update (RFC-189) - clean up tracker implementations

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1670912 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/AbstractReferenceTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/AbstractReferenceTracker.java
deleted file mode 100644
index 8519bad..0000000
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/AbstractReferenceTracker.java
+++ /dev/null
@@ -1,79 +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.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
-import org.apache.felix.http.base.internal.whiteboard.ServletContextHelperManager;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Filter;
-import org.osgi.framework.ServiceReference;
-import org.osgi.util.tracker.ServiceTracker;
-
-/**
- * Service tracker that does not get/unget the service objects itself, but
- * just forwards the service reference.
- */
-public abstract class AbstractReferenceTracker<T> extends ServiceTracker<T, ServiceReference<T>>
-{
-    private final ServletContextHelperManager contextManager;
-
-    public AbstractReferenceTracker(final ServletContextHelperManager contextManager,
-            final BundleContext context, final Filter filter)
-    {
-        super(context, filter, null);
-        this.contextManager = contextManager;
-    }
-
-    @Override
-    public final ServiceReference<T> addingService(final ServiceReference<T> ref)
-    {
-        this.added(ref);
-        return ref;
-    }
-
-    @Override
-    public final void modifiedService(final ServiceReference<T> ref, final ServiceReference<T> service)
-    {
-        this.modified(ref);
-    }
-
-    @Override
-    public final void removedService(final ServiceReference<T> ref, final ServiceReference<T> service)
-    {
-        this.removed(ref);
-    }
-
-    protected void modified(final ServiceReference<T> ref)
-    {
-        removed(ref);
-        added(ref);
-    }
-
-    protected void added(final ServiceReference<T> ref)
-    {
-        final WhiteboardServiceInfo<T> info = this.getServiceInfo(ref);
-        this.contextManager.addWhiteboardService(info);
-    }
-
-    protected void removed(final ServiceReference<T> ref)
-    {
-        final WhiteboardServiceInfo<T> info = this.getServiceInfo(ref);
-        this.contextManager.removeWhiteboardService(info);
-    }
-
-    protected abstract WhiteboardServiceInfo<T> getServiceInfo(final ServiceReference<T> ref);
-}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/FilterTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/FilterTracker.java
index 83201bf..5f594bb 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/FilterTracker.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/FilterTracker.java
@@ -22,33 +22,18 @@
 import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
 import org.apache.felix.http.base.internal.whiteboard.ServletContextHelperManager;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
 
-public final class FilterTracker extends AbstractReferenceTracker<Filter>
+public final class FilterTracker extends WhiteboardServiceTracker<Filter>
 {
-
-    private static org.osgi.framework.Filter createFilter(final BundleContext btx)
-    {
-        try
-        {
-            return btx.createFilter(String.format("(&(objectClass=%s)(|(%s=*)(%s=*)(%s=*)))",
-                    Filter.class.getName(),
-                    HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN,
-                    HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_REGEX,
-                    HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_SERVLET));
-        }
-        catch ( final InvalidSyntaxException ise)
-        {
-            // we can safely ignore it as the above filter is a constant
-        }
-        return null; // we never get here - and if we get an NPE which is fine
-    }
-
     public FilterTracker(final BundleContext context, final ServletContextHelperManager manager)
     {
-        super(manager, context, createFilter(context));
+        super(manager, context, String.format("(&(objectClass=%s)(|(%s=*)(%s=*)(%s=*)))",
+                Filter.class.getName(),
+                HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN,
+                HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_REGEX,
+                HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_SERVLET));
     }
 
     @Override
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/HttpSessionAttributeListenerTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/HttpSessionAttributeListenerTracker.java
index d6b4691..0971399 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/HttpSessionAttributeListenerTracker.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/HttpSessionAttributeListenerTracker.java
@@ -22,32 +22,13 @@
 import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
 import org.apache.felix.http.base.internal.whiteboard.ServletContextHelperManager;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
-import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
 
-public final class HttpSessionAttributeListenerTracker extends AbstractReferenceTracker<HttpSessionAttributeListener>
+public final class HttpSessionAttributeListenerTracker extends WhiteboardServiceTracker<HttpSessionAttributeListener>
 {
-
-    private static org.osgi.framework.Filter createFilter(final BundleContext btx)
-    {
-        try
-        {
-            return btx.createFilter(String.format("(&(objectClass=%s)(%s=*)(!(%s~=false)))",
-                    HttpSessionAttributeListener.class.getName(),
-                    HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER,
-                    HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER));
-        }
-        catch ( final InvalidSyntaxException ise)
-        {
-            // we can safely ignore it as the above filter is a constant
-        }
-        return null; // we never get here - and if we get an NPE which is fine
-    }
-
     public HttpSessionAttributeListenerTracker(final BundleContext context, final ServletContextHelperManager manager)
     {
-        super(manager, context, createFilter(context));
+        super(manager, context, createListenerFilterExpression(HttpSessionAttributeListener.class));
     }
 
     @Override
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/HttpSessionIdListenerTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/HttpSessionIdListenerTracker.java
index 5ed3170..894e2a8 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/HttpSessionIdListenerTracker.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/HttpSessionIdListenerTracker.java
@@ -22,32 +22,13 @@
 import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
 import org.apache.felix.http.base.internal.whiteboard.ServletContextHelperManager;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
-import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
 
-public final class HttpSessionIdListenerTracker extends AbstractReferenceTracker<HttpSessionIdListener>
+public final class HttpSessionIdListenerTracker extends WhiteboardServiceTracker<HttpSessionIdListener>
 {
-
-    private static org.osgi.framework.Filter createFilter(final BundleContext btx)
-    {
-        try
-        {
-            return btx.createFilter(String.format("(&(objectClass=%s)(%s=*)(!(%s~=false)))",
-                    HttpSessionIdListener.class.getName(),
-                    HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER,
-                    HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER));
-        }
-        catch ( final InvalidSyntaxException ise)
-        {
-            // we can safely ignore it as the above filter is a constant
-        }
-        return null; // we never get here - and if we get an NPE which is fine
-    }
-
     public HttpSessionIdListenerTracker(final BundleContext context, final ServletContextHelperManager manager)
     {
-        super(manager, context, createFilter(context));
+        super(manager, context, createListenerFilterExpression(HttpSessionIdListener.class));
     }
 
     @Override
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/HttpSessionListenerTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/HttpSessionListenerTracker.java
index 1bb09d2..bf70059 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/HttpSessionListenerTracker.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/HttpSessionListenerTracker.java
@@ -22,32 +22,13 @@
 import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
 import org.apache.felix.http.base.internal.whiteboard.ServletContextHelperManager;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
-import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
 
-public final class HttpSessionListenerTracker extends AbstractReferenceTracker<HttpSessionListener>
+public final class HttpSessionListenerTracker extends WhiteboardServiceTracker<HttpSessionListener>
 {
-
-    private static org.osgi.framework.Filter createFilter(final BundleContext btx)
-    {
-        try
-        {
-            return btx.createFilter(String.format("(&(objectClass=%s)(%s=*)(!(%s~=false)))",
-                    HttpSessionListener.class.getName(),
-                    HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER,
-                    HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER));
-        }
-        catch ( final InvalidSyntaxException ise)
-        {
-            // we can safely ignore it as the above filter is a constant
-        }
-        return null; // we never get here - and if we get an NPE which is fine
-    }
-
     public HttpSessionListenerTracker(final BundleContext context, final ServletContextHelperManager manager)
     {
-        super(manager, context, createFilter(context));
+        super(manager, context, createListenerFilterExpression(HttpSessionListener.class));
     }
 
     @Override
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 1e9c590..4c22004 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
@@ -20,32 +20,16 @@
 import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
 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 AbstractReferenceTracker<Object>
+public final class ResourceTracker extends WhiteboardServiceTracker<Object>
 {
-
-    private static Filter createFilter(final BundleContext btx)
-    {
-        try
-        {
-            return btx.createFilter(String.format("(&(%s=*)(%s=*))",
-                    HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PATTERN,
-                    HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PREFIX));
-        }
-        catch ( final InvalidSyntaxException ise)
-        {
-            // we can safely ignore it as the above filter is a constant
-        }
-        return null; // we never get here - and if we get an NPE which is fine
-    }
-
     public ResourceTracker(final BundleContext context, final ServletContextHelperManager manager)
     {
-        super(manager, context, createFilter(context));
+        super(manager, context, String.format("(&(%s=*)(%s=*))",
+                HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PATTERN,
+                HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PREFIX));
     }
 
     @Override
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextAttributeListenerTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextAttributeListenerTracker.java
index 2ed295d..a64e6d2 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextAttributeListenerTracker.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextAttributeListenerTracker.java
@@ -22,32 +22,13 @@
 import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
 import org.apache.felix.http.base.internal.whiteboard.ServletContextHelperManager;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
-import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
 
-public final class ServletContextAttributeListenerTracker extends AbstractReferenceTracker<ServletContextAttributeListener>
+public final class ServletContextAttributeListenerTracker extends WhiteboardServiceTracker<ServletContextAttributeListener>
 {
-
-    private static org.osgi.framework.Filter createFilter(final BundleContext btx)
-    {
-        try
-        {
-            return btx.createFilter(String.format("(&(objectClass=%s)(%s=*)(!(%s~=false)))",
-                    ServletContextAttributeListener.class.getName(),
-                    HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER,
-                    HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER));
-        }
-        catch ( final InvalidSyntaxException ise)
-        {
-            // we can safely ignore it as the above filter is a constant
-        }
-        return null; // we never get here - and if we get an NPE which is fine
-    }
-
     public ServletContextAttributeListenerTracker(final BundleContext context, final ServletContextHelperManager manager)
     {
-        super(manager, context, createFilter(context));
+        super(manager, context, createListenerFilterExpression(ServletContextAttributeListener.class));
     }
 
     @Override
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextListenerTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextListenerTracker.java
index b2af061..618902b 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextListenerTracker.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextListenerTracker.java
@@ -22,32 +22,13 @@
 import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
 import org.apache.felix.http.base.internal.whiteboard.ServletContextHelperManager;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
-import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
 
-public final class ServletContextListenerTracker extends AbstractReferenceTracker<ServletContextListener>
+public final class ServletContextListenerTracker extends WhiteboardServiceTracker<ServletContextListener>
 {
-
-    private static org.osgi.framework.Filter createFilter(final BundleContext btx)
-    {
-        try
-        {
-            return btx.createFilter(String.format("(&(objectClass=%s)(%s=*)(!(%s~=false)))",
-                    ServletContextListener.class.getName(),
-                    HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER,
-                    HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER));
-        }
-        catch ( final InvalidSyntaxException ise)
-        {
-            // we can safely ignore it as the above filter is a constant
-        }
-        return null; // we never get here - and if we get an NPE which is fine
-    }
-
     public ServletContextListenerTracker(final BundleContext context, final ServletContextHelperManager manager)
     {
-        super(manager, context, createFilter(context));
+        super(manager, context, createListenerFilterExpression(ServletContextListener.class));
     }
 
     @Override
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletRequestAttributeListenerTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletRequestAttributeListenerTracker.java
index 9e4bb94..42cb1c3 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletRequestAttributeListenerTracker.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletRequestAttributeListenerTracker.java
@@ -22,32 +22,13 @@
 import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
 import org.apache.felix.http.base.internal.whiteboard.ServletContextHelperManager;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
-import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
 
-public final class ServletRequestAttributeListenerTracker extends AbstractReferenceTracker<ServletRequestAttributeListener>
+public final class ServletRequestAttributeListenerTracker extends WhiteboardServiceTracker<ServletRequestAttributeListener>
 {
-
-    private static org.osgi.framework.Filter createFilter(final BundleContext btx)
-    {
-        try
-        {
-            return btx.createFilter(String.format("(&(objectClass=%s)(%s=*)(!(%s~=false)))",
-                    ServletRequestAttributeListener.class.getName(),
-                    HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER,
-                    HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER));
-        }
-        catch ( final InvalidSyntaxException ise)
-        {
-            // we can safely ignore it as the above filter is a constant
-        }
-        return null; // we never get here - and if we get an NPE which is fine
-    }
-
     public ServletRequestAttributeListenerTracker(final BundleContext context, final ServletContextHelperManager manager)
     {
-        super(manager, context, createFilter(context));
+        super(manager, context, createListenerFilterExpression(ServletRequestAttributeListener.class));
     }
 
     @Override
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletRequestListenerTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletRequestListenerTracker.java
index 41f0f97..40343bc 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletRequestListenerTracker.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletRequestListenerTracker.java
@@ -22,32 +22,13 @@
 import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
 import org.apache.felix.http.base.internal.whiteboard.ServletContextHelperManager;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
-import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
 
-public final class ServletRequestListenerTracker extends AbstractReferenceTracker<ServletRequestListener>
+public final class ServletRequestListenerTracker extends WhiteboardServiceTracker<ServletRequestListener>
 {
-
-    private static org.osgi.framework.Filter createFilter(final BundleContext btx)
-    {
-        try
-        {
-            return btx.createFilter(String.format("(&(objectClass=%s)(%s=*)(!(%s~=false)))",
-                    ServletRequestListener.class.getName(),
-                    HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER,
-                    HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER));
-        }
-        catch ( final InvalidSyntaxException ise)
-        {
-            // we can safely ignore it as the above filter is a constant
-        }
-        return null; // we never get here - and if we get an NPE which is fine
-    }
-
     public ServletRequestListenerTracker(final BundleContext context, final ServletContextHelperManager manager)
     {
-        super(manager, context, createFilter(context));
+        super(manager, context, createListenerFilterExpression(ServletRequestListener.class));
     }
 
     @Override
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletTracker.java
index 0a8f237..4088432 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletTracker.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletTracker.java
@@ -22,32 +22,17 @@
 import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
 import org.apache.felix.http.base.internal.whiteboard.ServletContextHelperManager;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
 
-public final class ServletTracker extends AbstractReferenceTracker<Servlet>
+public final class ServletTracker extends WhiteboardServiceTracker<Servlet>
 {
-
-    private static org.osgi.framework.Filter createFilter(final BundleContext btx)
-    {
-        try
-        {
-            return btx.createFilter(String.format("(&(objectClass=%s)(|(%s=*)(%s=*)))",
-                    Servlet.class.getName(),
-                    HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN,
-                    HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ERROR_PAGE));
-        }
-        catch ( final InvalidSyntaxException ise)
-        {
-            // we can safely ignore it as the above filter is a constant
-        }
-        return null; // we never get here - and if we get an NPE which is fine
-    }
-
     public ServletTracker(final BundleContext context, final ServletContextHelperManager manager)
     {
-        super(manager, context, createFilter(context));
+        super(manager, context, String.format("(&(objectClass=%s)(|(%s=*)(%s=*)))",
+                Servlet.class.getName(),
+                HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN,
+                HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ERROR_PAGE));
     }
 
     @Override
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/WhiteboardServiceTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/WhiteboardServiceTracker.java
new file mode 100644
index 0000000..8a2c515
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/WhiteboardServiceTracker.java
@@ -0,0 +1,118 @@
+/*
+ * 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.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
+import org.apache.felix.http.base.internal.whiteboard.ServletContextHelperManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
+import org.osgi.util.tracker.ServiceTracker;
+
+/**
+ * Service tracker for all whiteboard services except servlet context helper.
+ * This tracker does not get/unget the service objects itself, but just forwards the service reference
+ * by creating an info data object. Each sub class creates a different
+ * data object.
+ */
+public abstract class WhiteboardServiceTracker<T> extends ServiceTracker<T, ServiceReference<T>>
+{
+    /**
+     * Create a filter expression for the specific listener.
+     */
+    public static String createListenerFilterExpression(final Class<?> listenerClass)
+    {
+        return String.format("(&(objectClass=%s)(%s=*)(!(%s~=false)))",
+                listenerClass.getName(),
+                HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER,
+                HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER);
+    }
+
+    private static org.osgi.framework.Filter createFilter(final BundleContext btx, final String expr)
+    {
+        try
+        {
+            return btx.createFilter(expr);
+        }
+        catch ( final InvalidSyntaxException ise)
+        {
+            // we can safely ignore it as the filter is a constant
+        }
+        return null; // we never get here - and if we get an NPE which is fine
+    }
+
+    /** The context manager is called for each added/removed reference. */
+    private final ServletContextHelperManager contextManager;
+
+    /**
+     * Create a new tracker
+     * @param contextManager The context manager
+     * @param bundleContext The bundle context.
+     * @param filterExpr The filter expression for the services to track
+     */
+    public WhiteboardServiceTracker(final ServletContextHelperManager contextManager,
+            final BundleContext bundleContext, final String filterExpr)
+    {
+        super(bundleContext, createFilter(bundleContext, filterExpr), null);
+        this.contextManager = contextManager;
+    }
+
+    @Override
+    public final ServiceReference<T> addingService(final ServiceReference<T> ref)
+    {
+        this.added(ref);
+        return ref;
+    }
+
+    @Override
+    public final void modifiedService(final ServiceReference<T> ref, final ServiceReference<T> service)
+    {
+        this.modified(ref);
+    }
+
+    @Override
+    public final void removedService(final ServiceReference<T> ref, final ServiceReference<T> service)
+    {
+        this.removed(ref);
+    }
+
+    private void modified(final ServiceReference<T> ref)
+    {
+        removed(ref);
+        added(ref);
+    }
+
+    private void added(final ServiceReference<T> ref)
+    {
+        final WhiteboardServiceInfo<T> info = this.getServiceInfo(ref);
+        this.contextManager.addWhiteboardService(info);
+    }
+
+    private void removed(final ServiceReference<T> ref)
+    {
+        final WhiteboardServiceInfo<T> info = this.getServiceInfo(ref);
+        this.contextManager.removeWhiteboardService(info);
+    }
+
+    /**
+     * Implemented by sub classes to create the correct whiteboard service info object.
+     * @param ref The service reference
+     * @return A whiteboard service info
+     */
+    protected abstract WhiteboardServiceInfo<T> getServiceInfo(final ServiceReference<T> ref);
+}