FELIX-4860 : Revisit HandlerRegistry implementation. Unify all listener trackers and info objects into a single object. Cleanup registry handling

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1681572 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ListenerHandler.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ListenerHandler.java
index a93a84b..415ff63 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ListenerHandler.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ListenerHandler.java
@@ -16,6 +16,8 @@
  */
 package org.apache.felix.http.base.internal.handler;
 
+import java.util.EventListener;
+
 import org.apache.felix.http.base.internal.context.ExtServletContext;
 import org.apache.felix.http.base.internal.runtime.ListenerInfo;
 import org.osgi.service.http.runtime.dto.DTOConstants;
@@ -24,21 +26,21 @@
  * The listener handler handles the initialization and destruction of listener
  * objects.
  */
-public abstract class ListenerHandler<T> implements Comparable<ListenerHandler<T>>
+public abstract class ListenerHandler implements Comparable<ListenerHandler>
 {
     private final long contextServiceId;
 
-    private final ListenerInfo<T> listenerInfo;
+    private final ListenerInfo listenerInfo;
 
     private final ExtServletContext context;
 
-    private T listener;
+    private EventListener listener;
 
     protected volatile int useCount;
 
     public ListenerHandler(final long contextServiceId,
             final ExtServletContext context,
-            final ListenerInfo<T> listenerInfo)
+            final ListenerInfo listenerInfo)
     {
         this.contextServiceId = contextServiceId;
         this.context = context;
@@ -46,7 +48,7 @@
     }
 
     @Override
-    public int compareTo(final ListenerHandler<T> other)
+    public int compareTo(final ListenerHandler other)
     {
         return this.listenerInfo.compareTo(other.listenerInfo);
     }
@@ -61,17 +63,17 @@
         return this.contextServiceId;
     }
 
-    public T getListener()
+    public EventListener getListener()
     {
         return listener;
     }
 
-    protected void setListener(final T f)
+    protected void setListener(final EventListener f)
     {
         this.listener = f;
     }
 
-    public ListenerInfo<T> getListenerInfo()
+    public ListenerInfo getListenerInfo()
     {
         return this.listenerInfo;
     }
@@ -138,7 +140,7 @@
         {
             return false;
         }
-        final ListenerHandler<T> other = (ListenerHandler<T>) obj;
+        final ListenerHandler other = (ListenerHandler) obj;
         return listenerInfo.equals(other.listenerInfo);
     }
 }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/WhiteboardListenerHandler.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/WhiteboardListenerHandler.java
index b17210a..a9edbe6 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/WhiteboardListenerHandler.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/WhiteboardListenerHandler.java
@@ -16,6 +16,8 @@
  */
 package org.apache.felix.http.base.internal.handler;
 
+import java.util.EventListener;
+
 import org.apache.felix.http.base.internal.context.ExtServletContext;
 import org.apache.felix.http.base.internal.runtime.ListenerInfo;
 import org.osgi.framework.BundleContext;
@@ -25,13 +27,13 @@
 /**
  * Listener handler for listeners registered through the http whiteboard.
  */
-public final class WhiteboardListenerHandler<T> extends ListenerHandler<T>
+public final class WhiteboardListenerHandler extends ListenerHandler
 {
     private final BundleContext bundleContext;
 
     public WhiteboardListenerHandler(final long contextServiceId,
             final ExtServletContext context,
-            final ListenerInfo<T> listenerInfo,
+            final ListenerInfo listenerInfo,
             final BundleContext bundleContext)
     {
         super(contextServiceId, context, listenerInfo);
@@ -47,8 +49,8 @@
             return -1;
         }
 
-        final ServiceReference<T> serviceReference = getListenerInfo().getServiceReference();
-        final ServiceObjects<T> so = this.bundleContext.getServiceObjects(serviceReference);
+        final ServiceReference<EventListener> serviceReference = getListenerInfo().getServiceReference();
+        final ServiceObjects<EventListener> so = this.bundleContext.getServiceObjects(serviceReference);
 
         this.setListener((so == null ? null : so.getService()));
 
@@ -67,13 +69,13 @@
     @Override
     public boolean destroy()
     {
-        final T s = this.getListener();
+        final EventListener s = this.getListener();
         if ( s != null )
         {
             if ( super.destroy() )
             {
 
-                final ServiceObjects<T> so = this.bundleContext.getServiceObjects(getListenerInfo().getServiceReference());
+                final ServiceObjects<EventListener> so = this.bundleContext.getServiceObjects(getListenerInfo().getServiceReference());
                 if (so != null)
                 {
                     so.ungetService(s);
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/EventListenerRegistry.java b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/EventListenerRegistry.java
index 392ba71..132c71f 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/EventListenerRegistry.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/EventListenerRegistry.java
@@ -35,14 +35,7 @@
 import javax.servlet.http.HttpSessionListener;
 
 import org.apache.felix.http.base.internal.handler.ListenerHandler;
-import org.apache.felix.http.base.internal.runtime.HttpSessionAttributeListenerInfo;
-import org.apache.felix.http.base.internal.runtime.HttpSessionIdListenerInfo;
-import org.apache.felix.http.base.internal.runtime.HttpSessionListenerInfo;
 import org.apache.felix.http.base.internal.runtime.ListenerInfo;
-import org.apache.felix.http.base.internal.runtime.ServletContextAttributeListenerInfo;
-import org.apache.felix.http.base.internal.runtime.ServletContextListenerInfo;
-import org.apache.felix.http.base.internal.runtime.ServletRequestAttributeListenerInfo;
-import org.apache.felix.http.base.internal.runtime.ServletRequestListenerInfo;
 import org.osgi.service.http.runtime.dto.FailedListenerDTO;
 import org.osgi.service.http.runtime.dto.ListenerDTO;
 import org.osgi.service.http.runtime.dto.ServletContextDTO;
@@ -91,154 +84,88 @@
     }
 
     /**
-     * Add servlet context listener
+     * Add  listeners
      *
-     * @param handler
+     * @param listener handler
      */
-    public void addServletContextListener(@Nonnull final ListenerHandler<ServletContextListener> handler)
+    public void addListeners(@Nonnull final ListenerHandler handler)
     {
-        this.contextListeners.add(handler);
+        if ( handler.getListenerInfo().isListenerType(ServletContextListener.class.getName()))
+        {
+            this.contextListeners.add(handler);
+        }
+        if ( handler.getListenerInfo().isListenerType(ServletContextAttributeListener.class.getName()))
+        {
+            this.contextAttributeListeners.add(handler);
+        }
+        if ( handler.getListenerInfo().isListenerType(HttpSessionListener.class.getName()))
+        {
+            this.sessionListeners.add(handler);
+        }
+        if ( handler.getListenerInfo().isListenerType(HttpSessionIdListener.class.getName()))
+        {
+            this.sessionIdListeners.add(handler);
+        }
+        if ( handler.getListenerInfo().isListenerType(HttpSessionAttributeListener.class.getName()))
+        {
+            this.sessionAttributeListeners.add(handler);
+        }
+        if ( handler.getListenerInfo().isListenerType(ServletRequestListener.class.getName()))
+        {
+            this.requestListeners.add(handler);
+        }
+        if ( handler.getListenerInfo().isListenerType(ServletRequestAttributeListener.class.getName()))
+        {
+            this.requestAttributeListeners.add(handler);
+        }
     }
 
     /**
-     * Remove servlet context listener
+     * Remove listeners
      *
      * @param info
      */
-    public void removeServletContextListener(@Nonnull final ServletContextListenerInfo info)
+    public void removeListeners(@Nonnull final ListenerInfo info)
     {
-        this.contextListeners.remove(info);
+        if ( info.isListenerType(ServletContextListener.class.getName()))
+        {
+            this.contextListeners.remove(info);
+        }
+        if ( info.isListenerType(ServletContextAttributeListener.class.getName()))
+        {
+            this.contextAttributeListeners.remove(info);
+        }
+        if ( info.isListenerType(HttpSessionListener.class.getName()))
+        {
+            this.sessionListeners.remove(info);
+        }
+        if ( info.isListenerType(HttpSessionIdListener.class.getName()))
+        {
+            this.sessionIdListeners.remove(info);
+        }
+        if ( info.isListenerType(HttpSessionAttributeListener.class.getName()))
+        {
+            this.sessionAttributeListeners.remove(info);
+        }
+        if ( info.isListenerType(ServletRequestListener.class.getName()))
+        {
+            this.requestListeners.remove(info);
+        }
+        if ( info.isListenerType(ServletRequestAttributeListener.class.getName()))
+        {
+            this.requestAttributeListeners.remove(info);
+        }
     }
 
-    /**
-     * Add servlet context attribute listener
-     *
-     * @param handler
-     */
-    public void addServletContextAttributeListener(@Nonnull final ListenerHandler<ServletContextAttributeListener> handler)
-    {
-        this.contextAttributeListeners.add(handler);
-    }
-
-    /**
-     * Remove servlet context attribute listener
-     *
-     * @param info
-     */
-    public void removeServletContextAttributeListener(@Nonnull final ServletContextAttributeListenerInfo info)
-    {
-        this.contextAttributeListeners.remove(info);
-    }
-
-    /**
-     * Add session attribute listener
-     *
-     * @param handler
-     */
-    public void addSessionAttributeListener(@Nonnull final ListenerHandler<HttpSessionAttributeListener> handler)
-    {
-        this.sessionAttributeListeners.add(handler);
-    }
-
-    /**
-     * Remove session attribute listener
-     *
-     * @param info
-     */
-    public void removeSessionAttributeListener(@Nonnull final HttpSessionAttributeListenerInfo info)
-    {
-        this.sessionAttributeListeners.remove(info);
-    }
-
-    /**
-     * Add session listener
-     *
-     * @param handler
-     */
-    public void addSessionListener(@Nonnull final ListenerHandler<HttpSessionListener> handler)
-    {
-        this.sessionListeners.add(handler);
-    }
-
-    /**
-     * Remove session listener
-     *
-     * @param info
-     */
-    public void removeSessionListener(@Nonnull final HttpSessionListenerInfo info)
-    {
-        this.sessionListeners.remove(info);
-    }
-
-    /**
-     * Add session id listener
-     *
-     * @param handler
-     */
-    public void addSessionIdListener(@Nonnull final ListenerHandler<HttpSessionIdListener> handler)
-    {
-        this.sessionIdListeners.add(handler);
-    }
-
-    /**
-     * Remove session id listener
-     *
-     * @param info
-     */
-    public void removeSessionIdListener(@Nonnull final HttpSessionIdListenerInfo info)
-    {
-        this.sessionIdListeners.remove(info);
-    }
-
-    /**
-     * Add request listener
-     *
-     * @param handler
-     */
-    public void addServletRequestListener(@Nonnull final ListenerHandler<ServletRequestListener> handler)
-    {
-        this.requestListeners.add(handler);
-    }
-
-    /**
-     * Remove request listener
-     *
-     * @param info
-     */
-    public void removeServletRequestListener(@Nonnull final ServletRequestListenerInfo info)
-    {
-        this.requestListeners.remove(info);
-    }
-
-    /**
-     * Add request attribute listener
-     *
-     * @param handler
-     */
-    public void addServletRequestAttributeListener(@Nonnull final ListenerHandler<ServletRequestAttributeListener> handler)
-    {
-        this.requestAttributeListeners.add(handler);
-    }
-
-    /**
-     * Remove request attribute listener
-     *
-     * @param info
-     */
-    public void removeServletRequestAttributeListener(@Nonnull final ServletRequestAttributeListenerInfo info)
-    {
-        this.requestAttributeListeners.remove(info);
-    }
-
-    public ListenerHandler<ServletContextListener> getServletContextListener(@Nonnull final ListenerInfo<ServletContextListener> info)
+    public ListenerHandler getServletContextListener(@Nonnull final ListenerInfo info)
     {
         return this.contextListeners.getListenerHandler(info);
     }
 
     public void contextInitialized() {
-        for (final ListenerHandler<ServletContextListener> l : contextListeners.getActiveHandlers())
+        for (final ListenerHandler l : contextListeners.getActiveHandlers())
         {
-            final ServletContextListener listener = l.getListener();
+            final ServletContextListener listener = (ServletContextListener)l.getListener();
             if ( listener != null )
             {
                 listener.contextInitialized(new ServletContextEvent(l.getContext()));
@@ -247,9 +174,9 @@
     }
 
     public void contextDestroyed() {
-        for (final ListenerHandler<ServletContextListener> l : contextListeners.getActiveHandlers())
+        for (final ListenerHandler l : contextListeners.getActiveHandlers())
         {
-            final ServletContextListener listener = l.getListener();
+            final ServletContextListener listener = (ServletContextListener) l.getListener();
             if ( listener != null )
             {
                 listener.contextDestroyed(new ServletContextEvent(l.getContext()));
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/HandlerRegistry.java b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/HandlerRegistry.java
index a3fd974..e419cac 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/HandlerRegistry.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/HandlerRegistry.java
@@ -26,9 +26,7 @@
 
 import org.apache.felix.http.base.internal.handler.FilterHandler;
 import org.apache.felix.http.base.internal.handler.ServletHandler;
-import org.apache.felix.http.base.internal.runtime.FilterInfo;
 import org.apache.felix.http.base.internal.runtime.ServletContextHelperInfo;
-import org.apache.felix.http.base.internal.runtime.ServletInfo;
 import org.apache.felix.http.base.internal.runtime.dto.FailedDTOHolder;
 import org.osgi.service.http.runtime.dto.ServletContextDTO;
 
@@ -112,29 +110,7 @@
         }
     }
 
-    public void addFilter(@Nonnull final FilterHandler handler)
-    {
-        final PerContextHandlerRegistry reg = this.getRegistry(handler.getContextServiceId());
-        // TODO - check whether we need to handle the null case as well
-        //        it shouldn't be required as we only get here if the context exists
-        if ( reg != null )
-        {
-            reg.addFilter(handler);
-        }
-    }
-
-    public void removeFilter(final long contextId, @Nonnull final FilterInfo info, final boolean destroy)
-    {
-        final PerContextHandlerRegistry reg = this.getRegistry(contextId);
-        // TODO - check whether we need to handle the null case as well
-        //        it shouldn't be required as we only get here if the context exists
-        if ( reg != null )
-        {
-            reg.removeFilter(info, destroy);
-        }
-    }
-
-    private PerContextHandlerRegistry getRegistry(final long key)
+    public PerContextHandlerRegistry getRegistry(final long key)
     {
         final List<PerContextHandlerRegistry> list = this.registrations;
         for(final PerContextHandlerRegistry r : list)
@@ -196,29 +172,6 @@
         return EMPTY_FILTER_HANDLER;
     }
 
-    public void addServlet(final ServletHandler handler)
-    {
-        final PerContextHandlerRegistry reg = this.getRegistry(handler.getContextServiceId());
-        // TODO - check whether we need to handle the null case as well
-        //        it shouldn't be required as we only get here if the context exists
-        if ( reg != null )
-        {
-            reg.addServlet(handler);
-        }
-    }
-
-    public void removeServlet(final long contextId, final ServletInfo info, final boolean destroy)
-    {
-        final PerContextHandlerRegistry reg = this.getRegistry(contextId);
-        // TODO - check whether we need to handle the null case as well
-        //        it shouldn't be required as we only get here if the context exists
-        if ( reg != null )
-        {
-            reg.removeServlet(info, destroy);
-        }
-
-    }
-
     public PathResolution resolveServlet(@Nonnull final String requestURI)
     {
         final List<PerContextHandlerRegistry> regs = this.registrations;
@@ -265,8 +218,8 @@
         return null;
     }
 
-    public boolean getRuntimeInfo(final ServletContextDTO dto,
-            final FailedDTOHolder failedDTOHolder)
+    public boolean getRuntimeInfo(@Nonnull final ServletContextDTO dto,
+            @Nonnull final FailedDTOHolder failedDTOHolder)
     {
         final PerContextHandlerRegistry reg = this.getRegistry(dto.serviceId);
         if ( reg != null )
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ListenerMap.java b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ListenerMap.java
index fdbc4f0..da56b8c 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ListenerMap.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ListenerMap.java
@@ -18,6 +18,7 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.EventListener;
 import java.util.Iterator;
 import java.util.List;
 import java.util.NoSuchElementException;
@@ -30,7 +31,7 @@
 import org.osgi.service.http.runtime.dto.FailedListenerDTO;
 import org.osgi.service.http.runtime.dto.ListenerDTO;
 
-public class ListenerMap<T> {
+public class ListenerMap<T extends EventListener> {
 
     private volatile List<ListenerRegistrationStatus<T>> handlers = Collections.emptyList();
 
@@ -44,9 +45,9 @@
     private static final class ListenerRegistrationStatus<T> implements Comparable<ListenerRegistrationStatus<T>>
     {
         private final int result;
-        private final ListenerHandler<T> handler;
+        private final ListenerHandler handler;
 
-        public ListenerRegistrationStatus(@Nonnull final ListenerHandler<T> handler, final int result)
+        public ListenerRegistrationStatus(@Nonnull final ListenerHandler handler, final int result)
         {
             this.handler = handler;
             this.result = result;
@@ -57,7 +58,7 @@
             return this.result;
         }
 
-        public @Nonnull ListenerHandler<T> getHandler()
+        public @Nonnull ListenerHandler getHandler()
         {
             return this.handler;
         }
@@ -79,7 +80,7 @@
         this.handlers = Collections.emptyList();
     }
 
-    public synchronized void add(final ListenerHandler<T> handler)
+    public synchronized void add(final ListenerHandler handler)
     {
         final int reason = handler.init();
         final ListenerRegistrationStatus<T> status = new ListenerRegistrationStatus<T>(handler, reason);
@@ -90,7 +91,7 @@
         this.handlers = newList;
     }
 
-    public synchronized void remove(final ListenerInfo<T> info)
+    public synchronized void remove(final ListenerInfo info)
     {
         final List<ListenerRegistrationStatus<T>> newList = new ArrayList<ListenerMap.ListenerRegistrationStatus<T>>(this.handlers);
         final Iterator<ListenerRegistrationStatus<T>> i = newList.iterator();
@@ -110,7 +111,7 @@
         }
     }
 
-    public ListenerHandler<T> getListenerHandler(@Nonnull final ListenerInfo<T> info)
+    public ListenerHandler getListenerHandler(@Nonnull final ListenerInfo info)
     {
         final List<ListenerRegistrationStatus<T>> list = this.handlers;
         for(final ListenerRegistrationStatus<T> status : list)
@@ -123,14 +124,14 @@
         return null;
     }
 
-    public Iterable<ListenerHandler<T>> getActiveHandlers()
+    public Iterable<ListenerHandler> getActiveHandlers()
     {
         final List<ListenerRegistrationStatus<T>> list = this.handlers;
         final Iterator<ListenerRegistrationStatus<T>> iter = list.iterator();
-        final Iterator<ListenerHandler<T>> newIter = new Iterator<ListenerHandler<T>>()
+        final Iterator<ListenerHandler> newIter = new Iterator<ListenerHandler>()
         {
 
-            private ListenerHandler<T> next;
+            private ListenerHandler next;
 
             {
                 peek();
@@ -156,13 +157,13 @@
             }
 
             @Override
-            public ListenerHandler<T> next()
+            public ListenerHandler next()
             {
                 if ( this.next == null )
                 {
                     throw new NoSuchElementException();
                 }
-                final ListenerHandler<T> result = this.next;
+                final ListenerHandler result = this.next;
                 peek();
                 return result;
             }
@@ -173,11 +174,11 @@
                 throw new UnsupportedOperationException();
             }
         };
-        return new Iterable<ListenerHandler<T>>()
+        return new Iterable<ListenerHandler>()
         {
 
             @Override
-            public Iterator<ListenerHandler<T>> iterator()
+            public Iterator<ListenerHandler> iterator()
             {
                 return newIter;
             }
@@ -186,7 +187,7 @@
 
     public Iterable<T> getActiveListeners()
     {
-        final Iterator<ListenerHandler<T>> iter = this.getActiveHandlers().iterator();
+        final Iterator<ListenerHandler> iter = this.getActiveHandlers().iterator();
         final Iterator<T> newIter = new Iterator<T>()
         {
 
@@ -196,13 +197,14 @@
                 peek();
             }
 
+            @SuppressWarnings("unchecked")
             private void peek()
             {
                 next = null;
                 while ( next == null && iter.hasNext() )
                 {
-                    final ListenerHandler<T> handler = iter.next();
-                    next = handler.getListener();
+                    final ListenerHandler handler = iter.next();
+                    next = (T)handler.getListener();
                 }
             }
 
@@ -260,10 +262,6 @@
                     if ( dto.serviceId == status.getHandler().getListenerInfo().getServiceId() )
                     {
                         found = true;
-                        final String[] types = new String[dto.types.length + 1];
-                        System.arraycopy(dto.types, 0, types, 0, dto.types.length);
-                        types[dto.types.length] = status.getHandler().getListenerInfo().getListenerName();
-                        dto.types = types;
                     }
                     index++;
                 }
@@ -284,10 +282,6 @@
                          && dto.failureReason == status.getResult() )
                     {
                         found = true;
-                        final String[] types = new String[dto.types.length + 1];
-                        System.arraycopy(dto.types, 0, types, 0, dto.types.length);
-                        types[dto.types.length] = status.getHandler().getListenerInfo().getListenerName();
-                        dto.types = types;
                     }
                     index++;
                 }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java
index 51e942e..cf9d624 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java
@@ -20,13 +20,24 @@
 import javax.annotation.Nonnull;
 import javax.servlet.DispatcherType;
 
+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.HttpServiceServletHandler;
+import org.apache.felix.http.base.internal.handler.ListenerHandler;
 import org.apache.felix.http.base.internal.handler.ServletHandler;
+import org.apache.felix.http.base.internal.handler.WhiteboardFilterHandler;
+import org.apache.felix.http.base.internal.handler.WhiteboardListenerHandler;
+import org.apache.felix.http.base.internal.handler.WhiteboardServletHandler;
 import org.apache.felix.http.base.internal.runtime.FilterInfo;
+import org.apache.felix.http.base.internal.runtime.ListenerInfo;
+import org.apache.felix.http.base.internal.runtime.ResourceInfo;
 import org.apache.felix.http.base.internal.runtime.ServletContextHelperInfo;
 import org.apache.felix.http.base.internal.runtime.ServletInfo;
 import org.apache.felix.http.base.internal.runtime.dto.FailedDTOHolder;
 import org.apache.felix.http.base.internal.service.HttpServiceFactory;
+import org.apache.felix.http.base.internal.service.ResourceServlet;
+import org.apache.felix.http.base.internal.whiteboard.ContextHandler;
+import org.osgi.service.http.runtime.dto.DTOConstants;
 import org.osgi.service.http.runtime.dto.ServletContextDTO;
 
 /**
@@ -145,33 +156,142 @@
     }
 
     /**
-     * Add a servlet
-     * @param handler The servlet handler
+     * Register a servlet.
+     * @param contextInfo The servlet context helper info
+     * @param servletInfo The servlet info
      */
-    public void addServlet(@Nonnull final ServletHandler handler)
+    public int registerServlet(@Nonnull final ContextHandler contextHandler,
+            @Nonnull final ServletInfo servletInfo)
     {
+        final ExtServletContext context = contextHandler.getServletContext(servletInfo.getServiceReference().getBundle());
+        if ( context == null )
+        {
+            return DTOConstants.FAILURE_REASON_SERVLET_CONTEXT_FAILURE;
+        }
+        final ServletHandler handler = new WhiteboardServletHandler(
+                contextHandler.getContextInfo().getServiceId(),
+                context,
+                servletInfo, contextHandler.getBundleContext());
         this.servletRegistry.addServlet(handler);
         this.errorPageRegistry.addServlet(handler);
+        return -1;
     }
 
     /**
-     * Remove a servlet
-     * @param info The servlet info
+     * Unregister a servlet
+     * @param contextInfo The servlet context helper info
+     * @param servletInfo The servlet info
      */
-    public void removeServlet(@Nonnull final ServletInfo info, final boolean destroy)
+    public void unregisterServlet(@Nonnull final ContextHandler contextHandler, @Nonnull final ServletInfo servletInfo)
     {
-        this.servletRegistry.removeServlet(info, destroy);
-        this.errorPageRegistry.removeServlet(info, destroy);
+        this.servletRegistry.removeServlet(servletInfo, true);
+        this.errorPageRegistry.removeServlet(servletInfo, true);
+        contextHandler.ungetServletContext(servletInfo.getServiceReference().getBundle());
     }
 
-    public void addFilter(@Nonnull final FilterHandler handler)
+    /**
+     * Register a filter
+     * @param contextInfo The servlet context helper info
+     * @param filterInfo The filter info
+     */
+    public int registerFilter(@Nonnull  final ContextHandler contextHandler,
+            @Nonnull final FilterInfo filterInfo)
     {
+        final ExtServletContext context = contextHandler.getServletContext(filterInfo.getServiceReference().getBundle());
+        if ( context == null )
+        {
+            return DTOConstants.FAILURE_REASON_SERVLET_CONTEXT_FAILURE;
+        }
+        final FilterHandler handler = new WhiteboardFilterHandler(
+                contextHandler.getContextInfo().getServiceId(),
+                context,
+                filterInfo, contextHandler.getBundleContext());
         this.filterRegistry.addFilter(handler);
+        return -1;
     }
 
-    public void removeFilter(@Nonnull final FilterInfo info, final boolean destroy)
+    /**
+     * Unregister a filter
+     * @param contextInfo The servlet context helper info
+     * @param filterInfo The filter info
+     */
+    public void unregisterFilter(@Nonnull final ContextHandler contextHandler, @Nonnull final FilterInfo filterInfo)
     {
-        this.filterRegistry.removeFilter(info, destroy);
+        this.filterRegistry.removeFilter(filterInfo, true);
+        contextHandler.ungetServletContext(filterInfo.getServiceReference().getBundle());
+    }
+
+    /**
+     * Register listeners
+     *
+     * @param contextHandler The context handler
+     * @param info The listener info
+     * @return {@code -1} on successful registration, failure code otherwise
+     */
+    public int registerListeners(@Nonnull final ContextHandler contextHandler,
+            @Nonnull final ListenerInfo info)
+    {
+        final ExtServletContext context = contextHandler.getServletContext(info.getServiceReference().getBundle());
+        if ( context == null )
+        {
+            return DTOConstants.FAILURE_REASON_SERVLET_CONTEXT_FAILURE;
+        }
+        final ListenerHandler handler = new WhiteboardListenerHandler(
+                contextHandler.getContextInfo().getServiceId(),
+                context,
+                info,
+                contextHandler.getBundleContext());
+        this.eventListenerRegistry.addListeners(handler);
+        return -1;
+    }
+
+    /**
+     * Unregister listeners
+     *
+     * @param contextHandler The context handler
+     * @param info The listener info
+     */
+    public void unregisterListeners(@Nonnull final ContextHandler contextHandler, @Nonnull final ListenerInfo info)
+    {
+        this.eventListenerRegistry.removeListeners(info);
+        contextHandler.ungetServletContext(info.getServiceReference().getBundle());
+    }
+
+    /**
+     * Register a resource.
+     * @param contextInfo The servlet context helper info
+     * @param resourceInfo The resource info
+     */
+    public int registerResource(@Nonnull final ContextHandler contextHandler,
+            @Nonnull final ResourceInfo resourceInfo)
+    {
+        final ServletInfo servletInfo = new ServletInfo(resourceInfo);
+
+        final ExtServletContext context = contextHandler.getServletContext(servletInfo.getServiceReference().getBundle());
+        if ( context == null )
+        {
+            return DTOConstants.FAILURE_REASON_SERVLET_CONTEXT_FAILURE;
+        }
+
+        final ServletHandler handler = new HttpServiceServletHandler(
+                contextHandler.getContextInfo().getServiceId(),
+                context,
+                servletInfo, new ResourceServlet(resourceInfo.getPrefix()));
+
+        this.servletRegistry.addServlet(handler);
+        return -1;
+    }
+
+    /**
+     * Unregister a resource.
+     * @param contextInfo The servlet context helper info
+     * @param resourceInfo The resource info
+     */
+    public void unregisterResource(@Nonnull final ContextHandler contextHandler, @Nonnull final ResourceInfo resourceInfo)
+    {
+        final ServletInfo servletInfo = new ServletInfo(resourceInfo);
+        this.servletRegistry.removeServlet(servletInfo, true);
+        contextHandler.ungetServletContext(servletInfo.getServiceReference().getBundle());
     }
 
     public FilterHandler[] getFilterHandlers(@CheckForNull final ServletHandler servletHandler,
@@ -211,4 +331,40 @@
         // collect listeners
         this.eventListenerRegistry.getRuntimeInfo(dto, failedDTOHolder.failedListenerDTOs);
     }
+
+    /**
+     * Add a filter for the http service.
+     * @param handler The filter handler
+     */
+    public void registerFilter(@Nonnull final FilterHandler handler) {
+        this.filterRegistry.addFilter(handler);
+    }
+
+    /**
+     * Add a servlet for the http service.
+     * @param handler The servlet handler
+     */
+    public void registerServlet(@Nonnull final ServletHandler handler) {
+        this.servletRegistry.addServlet(handler);
+        this.errorPageRegistry.addServlet(handler);
+    }
+
+    /**
+     * Remove a servlet for the http service.
+     * @param servletInfo The servlet info
+     * @param destroy Destroy the servlet
+     */
+    public void unregisterServlet(@Nonnull final ServletInfo servletInfo, final boolean destroy) {
+        this.servletRegistry.removeServlet(servletInfo, destroy);
+        this.errorPageRegistry.removeServlet(servletInfo, destroy);
+    }
+
+    /**
+     * Remove a filter for the http service.
+     * @param info The filter info
+     * @param destroy Destroy the filter
+     */
+    public void unregisterFilter(@Nonnull final FilterInfo info, final boolean destroy) {
+        this.filterRegistry.removeFilter(info, destroy);
+    }
 }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/HttpSessionAttributeListenerInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/HttpSessionAttributeListenerInfo.java
deleted file mode 100644
index da52c22..0000000
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/HttpSessionAttributeListenerInfo.java
+++ /dev/null
@@ -1,34 +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.runtime;
-
-import javax.servlet.http.HttpSessionAttributeListener;
-
-import org.osgi.framework.ServiceReference;
-
-/**
- * Info object for registered servlet context listeners
- */
-public final class HttpSessionAttributeListenerInfo extends ListenerInfo<HttpSessionAttributeListener>
-{
-    public HttpSessionAttributeListenerInfo(final ServiceReference<HttpSessionAttributeListener> ref)
-    {
-        super(ref, HttpSessionAttributeListener.class.getName());
-    }
-}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/HttpSessionIdListenerInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/HttpSessionIdListenerInfo.java
deleted file mode 100644
index 0d8296d..0000000
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/HttpSessionIdListenerInfo.java
+++ /dev/null
@@ -1,34 +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.runtime;
-
-import javax.servlet.http.HttpSessionIdListener;
-
-import org.osgi.framework.ServiceReference;
-
-/**
- * Info object for registered http session id listeners
- */
-public final class HttpSessionIdListenerInfo extends ListenerInfo<HttpSessionIdListener>
-{
-    public HttpSessionIdListenerInfo(final ServiceReference<HttpSessionIdListener> ref)
-    {
-        super(ref, HttpSessionIdListener.class.getName());
-    }
-}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/HttpSessionListenerInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/HttpSessionListenerInfo.java
deleted file mode 100644
index 3473993..0000000
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/HttpSessionListenerInfo.java
+++ /dev/null
@@ -1,34 +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.runtime;
-
-import javax.servlet.http.HttpSessionListener;
-
-import org.osgi.framework.ServiceReference;
-
-/**
- * Info object for registered servlet context listeners
- */
-public final class HttpSessionListenerInfo extends ListenerInfo<HttpSessionListener>
-{
-    public HttpSessionListenerInfo(final ServiceReference<HttpSessionListener> ref)
-    {
-        super(ref, HttpSessionListener.class.getName());
-    }
-}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ListenerInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ListenerInfo.java
index b758bd0..9b3eeb5 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ListenerInfo.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ListenerInfo.java
@@ -18,24 +18,58 @@
  */
 package org.apache.felix.http.base.internal.runtime;
 
+import java.util.EventListener;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+import javax.servlet.ServletContextAttributeListener;
+import javax.servlet.ServletContextListener;
+import javax.servlet.ServletRequestAttributeListener;
+import javax.servlet.ServletRequestListener;
+import javax.servlet.http.HttpSessionAttributeListener;
+import javax.servlet.http.HttpSessionIdListener;
+import javax.servlet.http.HttpSessionListener;
+
+import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
 
 /**
  * Info object for registered listeners.
  */
-public abstract class ListenerInfo<T> extends WhiteboardServiceInfo<T>
+public class ListenerInfo extends WhiteboardServiceInfo<EventListener>
 {
+    private static final Set<String> ALLOWED_INTERFACES;
+    static {
+        ALLOWED_INTERFACES = new HashSet<String>();
+        ALLOWED_INTERFACES.add(HttpSessionAttributeListener.class.getName());
+        ALLOWED_INTERFACES.add(HttpSessionIdListener.class.getName());
+        ALLOWED_INTERFACES.add(HttpSessionListener.class.getName());
+        ALLOWED_INTERFACES.add(ServletContextAttributeListener.class.getName());
+        ALLOWED_INTERFACES.add(ServletContextListener.class.getName());
+        ALLOWED_INTERFACES.add(ServletRequestAttributeListener.class.getName());
+        ALLOWED_INTERFACES.add(ServletRequestListener.class.getName());
+    }
 
     private final String enabled;
 
-    private final String listenerName;
+    private final String[] types;
 
-    public ListenerInfo(final ServiceReference<T> ref, final String listenerName)
+    public ListenerInfo(final ServiceReference<EventListener> ref)
     {
         super(ref);
         this.enabled = this.getStringProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER);
-        this.listenerName = listenerName;
+        final String[] objectClass = (String[])ref.getProperty(Constants.OBJECTCLASS);
+        final Set<String> names = new HashSet<String>();
+        for(final String name : objectClass)
+        {
+            if ( ALLOWED_INTERFACES.contains(name) )
+            {
+                names.add(name);
+            }
+        }
+        this.types = names.toArray(new String[names.size()]);
     }
 
     @Override
@@ -44,8 +78,20 @@
         return super.isValid() && "true".equalsIgnoreCase(this.enabled);
     }
 
-    public String getListenerName()
+    public String[] getListenerTypes()
     {
-        return this.listenerName;
+        return this.types;
+    }
+
+    public boolean isListenerType(@Nonnull final String className)
+    {
+        for(final String t : this.types)
+        {
+            if ( t.equals(className) )
+            {
+                return true;
+            }
+        }
+        return false;
     }
 }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextAttributeListenerInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextAttributeListenerInfo.java
deleted file mode 100644
index 3384557..0000000
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextAttributeListenerInfo.java
+++ /dev/null
@@ -1,35 +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.runtime;
-
-import javax.servlet.ServletContextAttributeListener;
-
-import org.osgi.framework.ServiceReference;
-
-/**
- * Info object for registered servlet context attribute listeners
- */
-public final class ServletContextAttributeListenerInfo extends ListenerInfo<ServletContextAttributeListener>
-{
-
-    public ServletContextAttributeListenerInfo(final ServiceReference<ServletContextAttributeListener> ref)
-    {
-        super(ref, ServletContextAttributeListener.class.getName());
-    }
-}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextListenerInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextListenerInfo.java
deleted file mode 100644
index 7300276..0000000
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextListenerInfo.java
+++ /dev/null
@@ -1,34 +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.runtime;
-
-import javax.servlet.ServletContextListener;
-
-import org.osgi.framework.ServiceReference;
-
-/**
- * Info object for registered servlet context listeners
- */
-public final class ServletContextListenerInfo extends ListenerInfo<ServletContextListener>
-{
-    public ServletContextListenerInfo(final ServiceReference<ServletContextListener> ref)
-    {
-        super(ref, ServletContextListener.class.getName());
-    }
-}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletRequestAttributeListenerInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletRequestAttributeListenerInfo.java
deleted file mode 100644
index 7eb86d4..0000000
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletRequestAttributeListenerInfo.java
+++ /dev/null
@@ -1,34 +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.runtime;
-
-import javax.servlet.ServletRequestAttributeListener;
-
-import org.osgi.framework.ServiceReference;
-
-/**
- * Info object for registered servlet context listeners
- */
-public final class ServletRequestAttributeListenerInfo extends ListenerInfo<ServletRequestAttributeListener>
-{
-    public ServletRequestAttributeListenerInfo(final ServiceReference<ServletRequestAttributeListener> ref)
-    {
-        super(ref, ServletRequestAttributeListener.class.getName());
-    }
-}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletRequestListenerInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletRequestListenerInfo.java
deleted file mode 100644
index f1e41cd..0000000
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletRequestListenerInfo.java
+++ /dev/null
@@ -1,34 +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.runtime;
-
-import javax.servlet.ServletRequestListener;
-
-import org.osgi.framework.ServiceReference;
-
-/**
- * Info object for registered servlet context listeners
- */
-public final class ServletRequestListenerInfo extends ListenerInfo<ServletRequestListener>
-{
-    public ServletRequestListenerInfo(final ServiceReference<ServletRequestListener> ref)
-    {
-        super(ref, ServletRequestListener.class.getName());
-    }
-}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/FailedDTOHolder.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/FailedDTOHolder.java
index fc2e5d2..73b00dc 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/FailedDTOHolder.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/FailedDTOHolder.java
@@ -101,7 +101,7 @@
         }
         else if (info instanceof ListenerInfo)
         {
-            final FailedListenerDTO dto = (FailedListenerDTO)ListenerDTOBuilder.build((ListenerInfo<?>)info, failureCode);
+            final FailedListenerDTO dto = (FailedListenerDTO)ListenerDTOBuilder.build((ListenerInfo)info, failureCode);
             dto.servletContextId = contextId;
             this.failedListenerDTOs.add(dto);
         }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ListenerDTOBuilder.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ListenerDTOBuilder.java
index a6972c3..775d85c 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ListenerDTOBuilder.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/ListenerDTOBuilder.java
@@ -18,17 +18,6 @@
  */
 package org.apache.felix.http.base.internal.runtime.dto;
 
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.servlet.ServletContextAttributeListener;
-import javax.servlet.ServletContextListener;
-import javax.servlet.ServletRequestAttributeListener;
-import javax.servlet.ServletRequestListener;
-import javax.servlet.http.HttpSessionAttributeListener;
-import javax.servlet.http.HttpSessionIdListener;
-import javax.servlet.http.HttpSessionListener;
-
 import org.apache.felix.http.base.internal.handler.ListenerHandler;
 import org.apache.felix.http.base.internal.runtime.ListenerInfo;
 import org.osgi.service.http.runtime.dto.FailedListenerDTO;
@@ -36,24 +25,12 @@
 
 public final class ListenerDTOBuilder
 {
-    private static final Set<String> ALLOWED_INTERFACES;
-    static {
-        ALLOWED_INTERFACES = new HashSet<String>();
-        ALLOWED_INTERFACES.add(HttpSessionAttributeListener.class.getName());
-        ALLOWED_INTERFACES.add(HttpSessionIdListener.class.getName());
-        ALLOWED_INTERFACES.add(HttpSessionListener.class.getName());
-        ALLOWED_INTERFACES.add(ServletContextAttributeListener.class.getName());
-        ALLOWED_INTERFACES.add(ServletContextListener.class.getName());
-        ALLOWED_INTERFACES.add(ServletRequestAttributeListener.class.getName());
-        ALLOWED_INTERFACES.add(ServletRequestListener.class.getName());
-    }
-
-    public static ListenerDTO build(final ListenerInfo<?> info, final int reason)
+   public static ListenerDTO build(final ListenerInfo info, final int reason)
     {
         final ListenerDTO dto = (reason == -1 ? new ListenerDTO() : new FailedListenerDTO());
 
         dto.serviceId = info.getServiceId();
-        dto.types = new String[] {info.getListenerName()};
+        dto.types = info.getListenerTypes();
 
         if ( reason != -1 )
         {
@@ -63,7 +40,7 @@
         return dto;
     }
 
-    public static ListenerDTO build(final ListenerHandler<?> handler, final int reason)
+    public static ListenerDTO build(final ListenerHandler handler, final int reason)
     {
         final ListenerDTO dto = build(handler.getListenerInfo(), reason);
         dto.servletContextId = handler.getContextServiceId();
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceRuntimeImpl.java b/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceRuntimeImpl.java
index 6a9f76c..f829cb1 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceRuntimeImpl.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceRuntimeImpl.java
@@ -49,7 +49,7 @@
     @Override
     public RuntimeDTO getRuntimeDTO()
     {
-        final RuntimeDTOBuilder runtimeDTOBuilder = new RuntimeDTOBuilder(contextManager.getRuntimeInfo(registry),
+        final RuntimeDTOBuilder runtimeDTOBuilder = new RuntimeDTOBuilder(contextManager.getRuntimeInfo(),
                 this.serviceReference);
         return runtimeDTOBuilder.build();
     }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/service/SharedHttpServiceImpl.java b/http/base/src/main/java/org/apache/felix/http/base/internal/service/SharedHttpServiceImpl.java
index c24b870..ea25eb4 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/service/SharedHttpServiceImpl.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/service/SharedHttpServiceImpl.java
@@ -51,9 +51,9 @@
     /**
      * Register a filter
      */
-    public boolean registerFilter(@Nonnull final FilterHandler holder)
+    public boolean registerFilter(@Nonnull final FilterHandler handler)
     {
-        this.handlerRegistry.addFilter(holder);
+        this.handlerRegistry.getRegistry(handler.getContextServiceId()).registerFilter(handler);
         return true;
     }
 
@@ -65,7 +65,7 @@
             @Nonnull final Servlet servlet,
             @Nonnull final ServletInfo servletInfo) throws ServletException, NamespaceException
     {
-        final ServletHandler holder = new HttpServiceServletHandler(httpContext, servletInfo, servlet);
+        final ServletHandler handler = new HttpServiceServletHandler(httpContext, servletInfo, servlet);
 
         synchronized (this.aliasMap)
         {
@@ -73,9 +73,9 @@
             {
                 throw new NamespaceException("Alias " + alias + " is already in use.");
             }
-            this.handlerRegistry.addServlet(holder);
+            this.handlerRegistry.getRegistry(handler.getContextServiceId()).registerServlet(handler);
 
-            this.aliasMap.put(alias, holder);
+            this.aliasMap.put(alias, handler);
         }
     }
 
@@ -86,14 +86,14 @@
     {
         synchronized (this.aliasMap)
         {
-            final ServletHandler holder = this.aliasMap.remove(alias);
-            if (holder == null)
+            final ServletHandler handler = this.aliasMap.remove(alias);
+            if (handler == null)
             {
                 throw new IllegalArgumentException("Nothing registered at " + alias);
             }
 
-            final Servlet s = holder.getServlet();
-            this.handlerRegistry.removeServlet(HttpServiceFactory.HTTP_SERVICE_CONTEXT_SERVICE_ID, holder.getServletInfo(), true);
+            final Servlet s = handler.getServlet();
+            this.handlerRegistry.getRegistry(handler.getContextServiceId()).unregisterServlet(handler.getServletInfo(), true);
             return s;
         }
     }
@@ -110,7 +110,7 @@
                     final Map.Entry<String, ServletHandler> entry = i.next();
                     if (entry.getValue().getServlet() == servlet)
                     {
-                        this.handlerRegistry.removeServlet(HttpServiceFactory.HTTP_SERVICE_CONTEXT_SERVICE_ID, entry.getValue().getServletInfo(), destroy);
+                        this.handlerRegistry.getRegistry(entry.getValue().getContextServiceId()).unregisterServlet(entry.getValue().getServletInfo(), destroy);
 
                         i.remove();
                         break;
@@ -121,11 +121,11 @@
         }
     }
 
-    public void unregisterFilter(final FilterHandler filter, final boolean destroy)
+    public void unregisterFilter(final FilterHandler handler, final boolean destroy)
     {
-        if (filter != null)
+        if (handler != null)
         {
-            this.handlerRegistry.removeFilter(filter.getContextServiceId(), filter.getFilterInfo(), destroy);
+            this.handlerRegistry.getRegistry(handler.getContextServiceId()).unregisterFilter(handler.getFilterInfo(), destroy);
         }
     }
 }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ContextHandler.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ContextHandler.java
index 9a57ca2..604bc2c 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ContextHandler.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ContextHandler.java
@@ -24,6 +24,7 @@
 import javax.servlet.ServletContext;
 
 import org.apache.felix.http.base.internal.context.ExtServletContext;
+import org.apache.felix.http.base.internal.registry.HandlerRegistry;
 import org.apache.felix.http.base.internal.registry.PerContextHandlerRegistry;
 import org.apache.felix.http.base.internal.runtime.ServletContextHelperInfo;
 import org.osgi.framework.Bundle;
@@ -58,6 +59,11 @@
         this.bundle = bundle;
     }
 
+    public BundleContext getBundleContext()
+    {
+        return this.bundle.getBundleContext();
+    }
+
     public ServletContextHelperInfo getContextInfo()
     {
         return this.info;
@@ -73,7 +79,7 @@
      * Activate this context.
      * @return {@code true} if it succeeded.
      */
-    public boolean activate(final WhiteboardHttpService httpService)
+    public boolean activate(final HandlerRegistry registry)
     {
         this.registry = new PerContextHandlerRegistry(this.info);
         this.sharedContext = new SharedServletContextImpl(webContext,
@@ -89,7 +95,7 @@
         }
         else
         {
-            httpService.registerContext(this.registry);
+            registry.add(this.registry);
         }
         return activate;
     }
@@ -97,9 +103,9 @@
     /**
      * Deactivate this context.
      */
-    public void deactivate(final WhiteboardHttpService httpService)
+    public void deactivate(final HandlerRegistry registry)
     {
-        httpService.unregisterContext(this);
+        registry.remove(this.info);
         this.registry = null;
         this.sharedContext = null;
         this.ungetServletContext(bundle);
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/FailureStateHandler.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/FailureStateHandler.java
index 60285ca..19cf77e 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/FailureStateHandler.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/FailureStateHandler.java
@@ -101,7 +101,7 @@
         return false;
     }
 
-    public void getRuntime(final FailedDTOHolder failedDTOHolder) {
+    public void getRuntimeInfo(final FailedDTOHolder failedDTOHolder) {
         for(final Map.Entry<AbstractInfo<?>, FailureStatus> entry : this.serviceFailures.entrySet() )
         {
             final Iterator<Map.Entry<Integer, Set<Long>>> i = entry.getValue().reasonToContextsMapping.entrySet().iterator();
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardHttpService.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardHttpService.java
deleted file mode 100644
index b6149e8..0000000
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardHttpService.java
+++ /dev/null
@@ -1,341 +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 javax.annotation.Nonnull;
-import javax.servlet.ServletContextAttributeListener;
-import javax.servlet.ServletContextListener;
-import javax.servlet.ServletRequestAttributeListener;
-import javax.servlet.ServletRequestListener;
-import javax.servlet.http.HttpSessionAttributeListener;
-import javax.servlet.http.HttpSessionIdListener;
-import javax.servlet.http.HttpSessionListener;
-
-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.HttpServiceServletHandler;
-import org.apache.felix.http.base.internal.handler.ListenerHandler;
-import org.apache.felix.http.base.internal.handler.ServletHandler;
-import org.apache.felix.http.base.internal.handler.WhiteboardFilterHandler;
-import org.apache.felix.http.base.internal.handler.WhiteboardListenerHandler;
-import org.apache.felix.http.base.internal.handler.WhiteboardServletHandler;
-import org.apache.felix.http.base.internal.registry.HandlerRegistry;
-import org.apache.felix.http.base.internal.registry.PerContextHandlerRegistry;
-import org.apache.felix.http.base.internal.runtime.FilterInfo;
-import org.apache.felix.http.base.internal.runtime.HttpSessionAttributeListenerInfo;
-import org.apache.felix.http.base.internal.runtime.HttpSessionIdListenerInfo;
-import org.apache.felix.http.base.internal.runtime.HttpSessionListenerInfo;
-import org.apache.felix.http.base.internal.runtime.ResourceInfo;
-import org.apache.felix.http.base.internal.runtime.ServletContextAttributeListenerInfo;
-import org.apache.felix.http.base.internal.runtime.ServletContextListenerInfo;
-import org.apache.felix.http.base.internal.runtime.ServletInfo;
-import org.apache.felix.http.base.internal.runtime.ServletRequestAttributeListenerInfo;
-import org.apache.felix.http.base.internal.runtime.ServletRequestListenerInfo;
-import org.apache.felix.http.base.internal.service.ResourceServlet;
-import org.osgi.framework.BundleContext;
-import org.osgi.service.http.runtime.dto.DTOConstants;
-
-public final class WhiteboardHttpService
-{
-    private final HandlerRegistry handlerRegistry;
-
-    private final BundleContext bundleContext;
-
-    /**
-     * Create a new whiteboard http service
-     * @param bundleContext
-     * @param handlerRegistry
-     */
-    public WhiteboardHttpService(final BundleContext bundleContext,
-            final HandlerRegistry handlerRegistry)
-    {
-        this.handlerRegistry = handlerRegistry;
-        this.bundleContext = bundleContext;
-    }
-
-    /**
-     * Register a servlet.
-     * @param contextInfo The servlet context helper info
-     * @param servletInfo The servlet info
-     */
-    public int registerServlet(@Nonnull final ContextHandler contextHandler,
-            @Nonnull final ServletInfo servletInfo)
-    {
-        final ExtServletContext context = contextHandler.getServletContext(servletInfo.getServiceReference().getBundle());
-        if ( context == null )
-        {
-            return DTOConstants.FAILURE_REASON_SERVLET_CONTEXT_FAILURE;
-        }
-        final ServletHandler holder = new WhiteboardServletHandler(
-                contextHandler.getContextInfo().getServiceId(),
-                context,
-                servletInfo, bundleContext);
-        handlerRegistry.addServlet(holder);
-        return -1;
-    }
-
-    /**
-     * Unregister a servlet
-     * @param contextInfo The servlet context helper info
-     * @param servletInfo The servlet info
-     */
-    public void unregisterServlet(@Nonnull final ContextHandler contextHandler, @Nonnull final ServletInfo servletInfo)
-    {
-        handlerRegistry.removeServlet(contextHandler.getContextInfo().getServiceId(), servletInfo, true);
-        contextHandler.ungetServletContext(servletInfo.getServiceReference().getBundle());
-    }
-
-    /**
-     * Register a filter
-     * @param contextInfo The servlet context helper info
-     * @param filterInfo The filter info
-     */
-    public int registerFilter(@Nonnull  final ContextHandler contextHandler,
-            @Nonnull final FilterInfo filterInfo)
-    {
-        final ExtServletContext context = contextHandler.getServletContext(filterInfo.getServiceReference().getBundle());
-        if ( context == null )
-        {
-            return DTOConstants.FAILURE_REASON_SERVLET_CONTEXT_FAILURE;
-        }
-        final FilterHandler holder = new WhiteboardFilterHandler(
-                contextHandler.getContextInfo().getServiceId(),
-                context,
-                filterInfo, bundleContext);
-        handlerRegistry.addFilter(holder);
-        return -1;
-    }
-
-    /**
-     * Unregister a filter
-     * @param contextInfo The servlet context helper info
-     * @param filterInfo The filter info
-     */
-    public void unregisterFilter(@Nonnull final ContextHandler contextHandler, @Nonnull final FilterInfo filterInfo)
-    {
-        handlerRegistry.removeFilter(contextHandler.getContextInfo().getServiceId(), filterInfo, true);
-        contextHandler.ungetServletContext(filterInfo.getServiceReference().getBundle());
-    }
-
-    public int registerListener(@Nonnull final ContextHandler contextHandler,
-            @Nonnull final ServletContextListenerInfo info)
-    {
-        final ExtServletContext context = contextHandler.getServletContext(info.getServiceReference().getBundle());
-        if ( context == null )
-        {
-            return DTOConstants.FAILURE_REASON_SERVLET_CONTEXT_FAILURE;
-        }
-        final ListenerHandler<ServletContextListener> handler = new WhiteboardListenerHandler<ServletContextListener>(
-                contextHandler.getContextInfo().getServiceId(),
-                context,
-                info,
-                bundleContext);
-        contextHandler.getRegistry().getEventListenerRegistry().addServletContextListener(handler);
-        return -1;
-    }
-
-    public void unregisterListener(@Nonnull final ContextHandler contextHandler, @Nonnull final ServletContextListenerInfo info)
-    {
-        contextHandler.getRegistry().getEventListenerRegistry().removeServletContextListener(info);
-        contextHandler.ungetServletContext(info.getServiceReference().getBundle());
-    }
-
-    public int registerListener(@Nonnull final ContextHandler contextHandler,
-            @Nonnull final ServletContextAttributeListenerInfo info)
-    {
-        final ExtServletContext context = contextHandler.getServletContext(info.getServiceReference().getBundle());
-        if ( context == null )
-        {
-            return DTOConstants.FAILURE_REASON_SERVLET_CONTEXT_FAILURE;
-        }
-        final ListenerHandler<ServletContextAttributeListener> handler = new WhiteboardListenerHandler<ServletContextAttributeListener>(
-                contextHandler.getContextInfo().getServiceId(),
-                context,
-                info,
-                bundleContext);
-        contextHandler.getRegistry().getEventListenerRegistry().addServletContextAttributeListener(handler);
-        return -1;
-    }
-
-    public void unregisterListener(@Nonnull final ContextHandler contextHandler, @Nonnull final ServletContextAttributeListenerInfo info)
-    {
-        contextHandler.getRegistry().getEventListenerRegistry().removeServletContextAttributeListener(info);
-        contextHandler.ungetServletContext(info.getServiceReference().getBundle());
-    }
-
-    public int registerListener(@Nonnull final ContextHandler contextHandler,
-            @Nonnull final HttpSessionListenerInfo info)
-    {
-        final ExtServletContext context = contextHandler.getServletContext(info.getServiceReference().getBundle());
-        if ( context == null )
-        {
-            return DTOConstants.FAILURE_REASON_SERVLET_CONTEXT_FAILURE;
-        }
-        final ListenerHandler<HttpSessionListener> handler = new WhiteboardListenerHandler<HttpSessionListener>(
-                contextHandler.getContextInfo().getServiceId(),
-                context,
-                info,
-                bundleContext);
-        contextHandler.getRegistry().getEventListenerRegistry().addSessionListener(handler);
-        return -1;
-    }
-
-    public void unregisterListener(@Nonnull final ContextHandler contextHandler, @Nonnull final HttpSessionListenerInfo info)
-    {
-        contextHandler.getRegistry().getEventListenerRegistry().removeSessionListener(info);
-        contextHandler.ungetServletContext(info.getServiceReference().getBundle());
-    }
-
-    public int registerListener(@Nonnull final ContextHandler contextHandler,
-            @Nonnull final HttpSessionIdListenerInfo info)
-    {
-        final ExtServletContext context = contextHandler.getServletContext(info.getServiceReference().getBundle());
-        if ( context == null )
-        {
-            return DTOConstants.FAILURE_REASON_SERVLET_CONTEXT_FAILURE;
-        }
-        final ListenerHandler<HttpSessionIdListener> handler = new WhiteboardListenerHandler<HttpSessionIdListener>(
-                contextHandler.getContextInfo().getServiceId(),
-                context,
-                info,
-                bundleContext);
-        contextHandler.getRegistry().getEventListenerRegistry().addSessionIdListener(handler);
-        return -1;
-    }
-
-    public void unregisterListener(@Nonnull final ContextHandler contextHandler, @Nonnull final HttpSessionIdListenerInfo info)
-    {
-        contextHandler.getRegistry().getEventListenerRegistry().removeSessionIdListener(info);
-        contextHandler.ungetServletContext(info.getServiceReference().getBundle());
-    }
-
-    public int registerListener(@Nonnull final ContextHandler contextHandler,
-            @Nonnull final HttpSessionAttributeListenerInfo info)
-    {
-        final ExtServletContext context = contextHandler.getServletContext(info.getServiceReference().getBundle());
-        if ( context == null )
-        {
-            return DTOConstants.FAILURE_REASON_SERVLET_CONTEXT_FAILURE;
-        }
-        final ListenerHandler<HttpSessionAttributeListener> handler = new WhiteboardListenerHandler<HttpSessionAttributeListener>(
-                contextHandler.getContextInfo().getServiceId(),
-                context,
-                info,
-                bundleContext);
-        contextHandler.getRegistry().getEventListenerRegistry().addSessionAttributeListener(handler);
-        return -1;
-    }
-
-    public void unregisterListener(@Nonnull final ContextHandler contextHandler, @Nonnull final HttpSessionAttributeListenerInfo info)
-    {
-        contextHandler.getRegistry().getEventListenerRegistry().removeSessionAttributeListener(info);
-        contextHandler.ungetServletContext(info.getServiceReference().getBundle());
-    }
-
-    public int registerListener(@Nonnull final ContextHandler contextHandler,
-            @Nonnull final ServletRequestListenerInfo info)
-    {
-        final ExtServletContext context = contextHandler.getServletContext(info.getServiceReference().getBundle());
-        if ( context == null )
-        {
-            return DTOConstants.FAILURE_REASON_SERVLET_CONTEXT_FAILURE;
-        }
-        final ListenerHandler<ServletRequestListener> handler = new WhiteboardListenerHandler<ServletRequestListener>(
-                contextHandler.getContextInfo().getServiceId(),
-                context,
-                info,
-                bundleContext);
-        contextHandler.getRegistry().getEventListenerRegistry().addServletRequestListener(handler);
-        return -1;
-    }
-
-    public void unregisterListener(@Nonnull final ContextHandler contextHandler, @Nonnull final ServletRequestListenerInfo info)
-    {
-        contextHandler.getRegistry().getEventListenerRegistry().removeServletRequestListener(info);
-        contextHandler.ungetServletContext(info.getServiceReference().getBundle());
-    }
-
-    public int registerListener(@Nonnull final ContextHandler contextHandler,
-            @Nonnull final ServletRequestAttributeListenerInfo info)
-    {
-        final ExtServletContext context = contextHandler.getServletContext(info.getServiceReference().getBundle());
-        if ( context == null )
-        {
-            return DTOConstants.FAILURE_REASON_SERVLET_CONTEXT_FAILURE;
-        }
-        final ListenerHandler<ServletRequestAttributeListener> handler = new WhiteboardListenerHandler<ServletRequestAttributeListener>(
-                contextHandler.getContextInfo().getServiceId(),
-                context,
-                info,
-                bundleContext);
-        contextHandler.getRegistry().getEventListenerRegistry().addServletRequestAttributeListener(handler);
-        return -1;
-    }
-
-    public void unregisterListener(@Nonnull final ContextHandler contextHandler, @Nonnull final ServletRequestAttributeListenerInfo info)
-    {
-        contextHandler.getRegistry().getEventListenerRegistry().removeServletRequestAttributeListener(info);
-        contextHandler.ungetServletContext(info.getServiceReference().getBundle());
-    }
-
-    /**
-     * Register a resource.
-     * @param contextInfo The servlet context helper info
-     * @param resourceInfo The resource info
-     */
-    public int registerResource(@Nonnull final ContextHandler contextHandler,
-            @Nonnull final ResourceInfo resourceInfo)
-    {
-        final ServletInfo servletInfo = new ServletInfo(resourceInfo);
-
-        final ExtServletContext context = contextHandler.getServletContext(servletInfo.getServiceReference().getBundle());
-        if ( context == null )
-        {
-            return DTOConstants.FAILURE_REASON_SERVLET_CONTEXT_FAILURE;
-        }
-
-        final ServletHandler holder = new HttpServiceServletHandler(
-                contextHandler.getContextInfo().getServiceId(),
-                context,
-                servletInfo, new ResourceServlet(resourceInfo.getPrefix()));
-
-        handlerRegistry.addServlet(holder);
-        return -1;
-    }
-
-    /**
-     * Unregister a resource.
-     * @param contextInfo The servlet context helper info
-     * @param resourceInfo The resource info
-     */
-    public void unregisterResource(@Nonnull final ContextHandler contextHandler, @Nonnull final ResourceInfo resourceInfo)
-    {
-        final ServletInfo servletInfo = new ServletInfo(resourceInfo);
-        handlerRegistry.removeServlet(contextHandler.getContextInfo().getServiceId(), servletInfo, true);
-        contextHandler.ungetServletContext(servletInfo.getServiceReference().getBundle());
-    }
-
-    public void registerContext(@Nonnull final PerContextHandlerRegistry registry)
-    {
-        this.handlerRegistry.add(registry);
-    }
-
-    public void unregisterContext(@Nonnull final ContextHandler contextHandler)
-    {
-        this.handlerRegistry.remove(contextHandler.getContextInfo());
-    }
-}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java
index dcf17c7..844fb5d 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java
@@ -47,16 +47,10 @@
 import org.apache.felix.http.base.internal.registry.HandlerRegistry;
 import org.apache.felix.http.base.internal.runtime.AbstractInfo;
 import org.apache.felix.http.base.internal.runtime.FilterInfo;
-import org.apache.felix.http.base.internal.runtime.HttpSessionAttributeListenerInfo;
-import org.apache.felix.http.base.internal.runtime.HttpSessionIdListenerInfo;
-import org.apache.felix.http.base.internal.runtime.HttpSessionListenerInfo;
+import org.apache.felix.http.base.internal.runtime.ListenerInfo;
 import org.apache.felix.http.base.internal.runtime.ResourceInfo;
-import org.apache.felix.http.base.internal.runtime.ServletContextAttributeListenerInfo;
 import org.apache.felix.http.base.internal.runtime.ServletContextHelperInfo;
-import org.apache.felix.http.base.internal.runtime.ServletContextListenerInfo;
 import org.apache.felix.http.base.internal.runtime.ServletInfo;
-import org.apache.felix.http.base.internal.runtime.ServletRequestAttributeListenerInfo;
-import org.apache.felix.http.base.internal.runtime.ServletRequestListenerInfo;
 import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
 import org.apache.felix.http.base.internal.runtime.dto.FailedDTOHolder;
 import org.apache.felix.http.base.internal.runtime.dto.RegistryRuntime;
@@ -65,14 +59,9 @@
 import org.apache.felix.http.base.internal.service.HttpServiceRuntimeImpl;
 import org.apache.felix.http.base.internal.util.MimeTypes;
 import org.apache.felix.http.base.internal.whiteboard.tracker.FilterTracker;
-import org.apache.felix.http.base.internal.whiteboard.tracker.HttpSessionAttributeListenerTracker;
-import org.apache.felix.http.base.internal.whiteboard.tracker.HttpSessionListenerTracker;
+import org.apache.felix.http.base.internal.whiteboard.tracker.ListenersTracker;
 import org.apache.felix.http.base.internal.whiteboard.tracker.ResourceTracker;
-import org.apache.felix.http.base.internal.whiteboard.tracker.ServletContextAttributeListenerTracker;
 import org.apache.felix.http.base.internal.whiteboard.tracker.ServletContextHelperTracker;
-import org.apache.felix.http.base.internal.whiteboard.tracker.ServletContextListenerTracker;
-import org.apache.felix.http.base.internal.whiteboard.tracker.ServletRequestAttributeListenerTracker;
-import org.apache.felix.http.base.internal.whiteboard.tracker.ServletRequestListenerTracker;
 import org.apache.felix.http.base.internal.whiteboard.tracker.ServletTracker;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
@@ -104,7 +93,7 @@
     /** A map with all servlet/filter registrations, mapped by abstract info. */
     private final Map<WhiteboardServiceInfo<?>, List<ContextHandler>> servicesMap = new HashMap<WhiteboardServiceInfo<?>, List<ContextHandler>>();
 
-    private final WhiteboardHttpService httpService;
+    private final HandlerRegistry registry;
 
     private final FailureStateHandler failureStateHandler = new FailureStateHandler();
 
@@ -130,7 +119,7 @@
     {
         this.bundleContext = bundleContext;
         this.httpServiceFactory = httpServiceFactory;
-        this.httpService = new WhiteboardHttpService(this.bundleContext, registry);
+        this.registry = registry;
         this.serviceRuntime = new HttpServiceRuntimeImpl(registry, this);
         this.plugin = new HttpServicePlugin(bundleContext, this.serviceRuntime);
     }
@@ -182,18 +171,11 @@
                     }
                 }, props);
         addTracker(new FilterTracker(this.bundleContext, this));
-        addTracker(new ServletTracker(this.bundleContext, this));
+        addTracker(new ListenersTracker(this.bundleContext, this));
         addTracker(new ResourceTracker(this.bundleContext, this));
-
-        addTracker(new HttpSessionListenerTracker(this.bundleContext, this));
-        addTracker(new HttpSessionAttributeListenerTracker(this.bundleContext, this));
-
         addTracker(new ServletContextHelperTracker(this.bundleContext, this));
-        addTracker(new ServletContextListenerTracker(this.bundleContext, this));
-        addTracker(new ServletContextAttributeListenerTracker(this.bundleContext, this));
+        addTracker(new ServletTracker(this.bundleContext, this));
 
-        addTracker(new ServletRequestListenerTracker(this.bundleContext, this));
-        addTracker(new ServletRequestAttributeListenerTracker(this.bundleContext, this));
         this.plugin.register();
     }
 
@@ -284,7 +266,7 @@
      */
     private boolean activate(final ContextHandler handler)
     {
-        if ( !handler.activate(this.httpService) )
+        if ( !handler.activate(this.registry) )
         {
             return false;
         }
@@ -299,7 +281,7 @@
                 {
                     this.failureStateHandler.remove(entry.getKey());
                 }
-                if ( entry.getKey() instanceof ServletContextListenerInfo )
+                if ( entry.getKey() instanceof ListenerInfo && ((ListenerInfo)entry.getKey()).isListenerType(ServletContextListener.class.getName()) )
                 {
                     // servlet context listeners will be registered directly
                     this.registerWhiteboardService(handler, entry.getKey());
@@ -340,7 +322,7 @@
             {
                 if ( !this.failureStateHandler.remove(entry.getKey(), handler.getContextInfo().getServiceId()) )
                 {
-                    if ( entry.getKey() instanceof ServletContextListenerInfo )
+                    if ( entry.getKey() instanceof ListenerInfo && ((ListenerInfo)entry.getKey()).isListenerType(ServletContextListener.class.getName()) )
                     {
                         listeners.add(entry.getKey());
                     }
@@ -364,7 +346,7 @@
             this.unregisterWhiteboardService(handler, info);
         }
 
-        handler.deactivate(this.httpService);
+        handler.deactivate(this.registry);
     }
 
     /**
@@ -573,12 +555,12 @@
                         for(final ContextHandler h : handlerList)
                         {
                             this.registerWhiteboardService(h, info);
-                            if ( info instanceof ServletContextListenerInfo )
+                            if ( info instanceof ListenerInfo && ((ListenerInfo)info).isListenerType(ServletContextListener.class.getName()) )
                             {
-                                final ListenerHandler<ServletContextListener> handler = h.getRegistry().getEventListenerRegistry().getServletContextListener((ServletContextListenerInfo)info);
+                                final ListenerHandler handler = h.getRegistry().getEventListenerRegistry().getServletContextListener((ListenerInfo)info);
                                 if ( handler != null )
                                 {
-                                    final ServletContextListener listener = handler.getListener();
+                                    final ServletContextListener listener = (ServletContextListener)handler.getListener();
                                     if ( listener != null )
                                     {
                                         listener.contextInitialized(new ServletContextEvent(handler.getContext()));
@@ -618,12 +600,12 @@
                     {
                         if ( !failureStateHandler.remove(info, h.getContextInfo().getServiceId()) )
                         {
-                            if ( info instanceof ServletContextListenerInfo )
+                            if ( info instanceof ListenerInfo && ((ListenerInfo)info).isListenerType(ServletContextListener.class.getName()) )
                             {
-                                final ListenerHandler<ServletContextListener> handler = h.getRegistry().getEventListenerRegistry().getServletContextListener((ServletContextListenerInfo)info);
+                                final ListenerHandler handler = h.getRegistry().getEventListenerRegistry().getServletContextListener((ListenerInfo)info);
                                 if ( handler != null )
                                 {
-                                    final ServletContextListener listener = handler.getListener();
+                                    final ServletContextListener listener = (ServletContextListener) handler.getListener();
                                     if ( listener != null )
                                     {
                                         listener.contextDestroyed(new ServletContextEvent(handler.getContext()));
@@ -651,44 +633,20 @@
             int failureCode = -1;
             if ( info instanceof ServletInfo )
             {
-                failureCode = this.httpService.registerServlet(handler, (ServletInfo)info);
+                failureCode = handler.getRegistry().registerServlet(handler, (ServletInfo)info);
             }
             else if ( info instanceof FilterInfo )
             {
-                failureCode = this.httpService.registerFilter(handler, (FilterInfo)info);
+                failureCode = handler.getRegistry().registerFilter(handler, (FilterInfo)info);
             }
             else if ( info instanceof ResourceInfo )
             {
-                failureCode = this.httpService.registerResource(handler, (ResourceInfo)info);
+                failureCode = handler.getRegistry().registerResource(handler, (ResourceInfo)info);
             }
 
-            else if ( info instanceof ServletContextListenerInfo )
+            else if ( info instanceof ListenerInfo )
             {
-                failureCode = this.httpService.registerListener(handler, (ServletContextListenerInfo) info);
-            }
-            else if ( info instanceof ServletContextAttributeListenerInfo )
-            {
-                failureCode = this.httpService.registerListener(handler, (ServletContextAttributeListenerInfo) info);
-            }
-            else if ( info instanceof HttpSessionListenerInfo )
-            {
-                failureCode = this.httpService.registerListener(handler, (HttpSessionListenerInfo) info);
-            }
-            else if ( info instanceof HttpSessionAttributeListenerInfo )
-            {
-                failureCode = this.httpService.registerListener(handler, (HttpSessionAttributeListenerInfo) info);
-            }
-            else if ( info instanceof HttpSessionIdListenerInfo )
-            {
-                failureCode = this.httpService.registerListener(handler, (HttpSessionIdListenerInfo) info);
-            }
-            else if ( info instanceof ServletRequestListenerInfo )
-            {
-                failureCode = this.httpService.registerListener(handler, (ServletRequestListenerInfo) info);
-            }
-            else if ( info instanceof ServletRequestAttributeListenerInfo )
-            {
-                failureCode = this.httpService.registerListener(handler, (ServletRequestAttributeListenerInfo) info);
+                failureCode = handler.getRegistry().registerListeners(handler, (ListenerInfo) info);
             }
             else
             {
@@ -720,44 +678,20 @@
         {
             if ( info instanceof ServletInfo )
             {
-                this.httpService.unregisterServlet(handler, (ServletInfo)info);
+                handler.getRegistry().unregisterServlet(handler, (ServletInfo)info);
             }
             else if ( info instanceof FilterInfo )
             {
-                this.httpService.unregisterFilter(handler, (FilterInfo)info);
+                handler.getRegistry().unregisterFilter(handler, (FilterInfo)info);
             }
             else if ( info instanceof ResourceInfo )
             {
-                this.httpService.unregisterResource(handler, (ResourceInfo)info);
+                handler.getRegistry().unregisterResource(handler, (ResourceInfo)info);
             }
 
-            else if ( info instanceof ServletContextListenerInfo )
+            else if ( info instanceof ListenerInfo )
             {
-                this.httpService.unregisterListener(handler, (ServletContextListenerInfo) info);
-            }
-            else if ( info instanceof ServletContextAttributeListenerInfo )
-            {
-                this.httpService.unregisterListener(handler, (ServletContextAttributeListenerInfo) info);
-            }
-            else if ( info instanceof HttpSessionListenerInfo )
-            {
-                this.httpService.unregisterListener(handler, (HttpSessionListenerInfo) info);
-            }
-            else if ( info instanceof HttpSessionAttributeListenerInfo )
-            {
-                this.httpService.unregisterListener(handler, (HttpSessionAttributeListenerInfo) info);
-            }
-            else if ( info instanceof HttpSessionIdListenerInfo )
-            {
-                this.httpService.unregisterListener(handler, (HttpSessionIdListenerInfo) info);
-            }
-            else if ( info instanceof ServletRequestListenerInfo )
-            {
-                this.httpService.unregisterListener(handler, (ServletRequestListenerInfo) info);
-            }
-            else if ( info instanceof ServletRequestAttributeListenerInfo )
-            {
-                this.httpService.unregisterListener(handler, (ServletRequestAttributeListenerInfo) info);
+                handler.getRegistry().unregisterListeners(handler, (ListenerInfo) info);
             }
         }
         catch (final Exception e)
@@ -807,7 +741,7 @@
         return null;
     }
 
-    public RegistryRuntime getRuntimeInfo(final HandlerRegistry registry)
+    public RegistryRuntime getRuntimeInfo()
     {
         final FailedDTOHolder failedDTOHolder = new FailedDTOHolder();
 
@@ -833,7 +767,7 @@
                     contextHandlerList.add(list.get(0));
                 }
             }
-            this.failureStateHandler.getRuntime(failedDTOHolder);
+            this.failureStateHandler.getRuntimeInfo(failedDTOHolder);
         }
         Collections.sort(contextHandlerList);
 
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
deleted file mode 100644
index 64f2003..0000000
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/HttpSessionAttributeListenerTracker.java
+++ /dev/null
@@ -1,38 +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 javax.servlet.http.HttpSessionAttributeListener;
-
-import org.apache.felix.http.base.internal.runtime.HttpSessionAttributeListenerInfo;
-import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
-import org.apache.felix.http.base.internal.whiteboard.WhiteboardManager;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-
-public final class HttpSessionAttributeListenerTracker extends WhiteboardServiceTracker<HttpSessionAttributeListener>
-{
-    public HttpSessionAttributeListenerTracker(final BundleContext context, final WhiteboardManager manager)
-    {
-        super(manager, context, createListenerFilterExpression(HttpSessionAttributeListener.class));
-    }
-
-    @Override
-    protected WhiteboardServiceInfo<HttpSessionAttributeListener> getServiceInfo(final ServiceReference<HttpSessionAttributeListener> ref) {
-        return new HttpSessionAttributeListenerInfo(ref);
-    }
-}
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
deleted file mode 100644
index 1256862..0000000
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/HttpSessionIdListenerTracker.java
+++ /dev/null
@@ -1,38 +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 javax.servlet.http.HttpSessionIdListener;
-
-import org.apache.felix.http.base.internal.runtime.HttpSessionIdListenerInfo;
-import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
-import org.apache.felix.http.base.internal.whiteboard.WhiteboardManager;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-
-public final class HttpSessionIdListenerTracker extends WhiteboardServiceTracker<HttpSessionIdListener>
-{
-    public HttpSessionIdListenerTracker(final BundleContext context, final WhiteboardManager manager)
-    {
-        super(manager, context, createListenerFilterExpression(HttpSessionIdListener.class));
-    }
-
-    @Override
-    protected WhiteboardServiceInfo<HttpSessionIdListener> getServiceInfo(final ServiceReference<HttpSessionIdListener> ref) {
-        return new HttpSessionIdListenerInfo(ref);
-    }
-}
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
deleted file mode 100644
index cc351fa..0000000
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/HttpSessionListenerTracker.java
+++ /dev/null
@@ -1,38 +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 javax.servlet.http.HttpSessionListener;
-
-import org.apache.felix.http.base.internal.runtime.HttpSessionListenerInfo;
-import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
-import org.apache.felix.http.base.internal.whiteboard.WhiteboardManager;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-
-public final class HttpSessionListenerTracker extends WhiteboardServiceTracker<HttpSessionListener>
-{
-    public HttpSessionListenerTracker(final BundleContext context, final WhiteboardManager manager)
-    {
-        super(manager, context, createListenerFilterExpression(HttpSessionListener.class));
-    }
-
-    @Override
-    protected WhiteboardServiceInfo<HttpSessionListener> getServiceInfo(final ServiceReference<HttpSessionListener> ref) {
-        return new HttpSessionListenerInfo(ref);
-    }
-}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ListenersTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ListenersTracker.java
new file mode 100644
index 0000000..e758f7b
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ListenersTracker.java
@@ -0,0 +1,66 @@
+/*
+ * 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 java.util.EventListener;
+
+import javax.servlet.ServletContextAttributeListener;
+import javax.servlet.ServletContextListener;
+import javax.servlet.ServletRequestAttributeListener;
+import javax.servlet.ServletRequestListener;
+import javax.servlet.http.HttpSessionAttributeListener;
+import javax.servlet.http.HttpSessionIdListener;
+import javax.servlet.http.HttpSessionListener;
+
+import org.apache.felix.http.base.internal.runtime.ListenerInfo;
+import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
+import org.apache.felix.http.base.internal.whiteboard.WhiteboardManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
+
+public final class ListenersTracker extends WhiteboardServiceTracker<EventListener>
+{
+    /**
+     * Create a filter expression for all supported listener.
+     */
+    private static String createListenersFilterExpression()
+    {
+        return String.format("(&" +
+                             "(|(objectClass=%s)(objectClass=%s)(objectClass=%s)(objectClass=%s)(objectClass=%s)(objectClass=%s)(objectClass=%s))" +
+                             "(%s=*)(!(%s~=false)))",
+                HttpSessionAttributeListener.class.getName(),
+                HttpSessionIdListener.class.getName(),
+                HttpSessionListener.class.getName(),
+                ServletContextListener.class.getName(),
+                ServletContextAttributeListener.class.getName(),
+                ServletRequestListener.class.getName(),
+                ServletRequestAttributeListener.class.getName(),
+                HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER,
+                HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER);
+    }
+
+    public ListenersTracker(final BundleContext context, final WhiteboardManager manager)
+    {
+        super(manager, context, createListenersFilterExpression());
+    }
+
+    @Override
+    protected WhiteboardServiceInfo<EventListener> getServiceInfo(final ServiceReference<EventListener> ref) {
+        return new ListenerInfo(ref);
+    }
+}
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
deleted file mode 100644
index f0edbf2..0000000
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextAttributeListenerTracker.java
+++ /dev/null
@@ -1,38 +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 javax.servlet.ServletContextAttributeListener;
-
-import org.apache.felix.http.base.internal.runtime.ServletContextAttributeListenerInfo;
-import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
-import org.apache.felix.http.base.internal.whiteboard.WhiteboardManager;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-
-public final class ServletContextAttributeListenerTracker extends WhiteboardServiceTracker<ServletContextAttributeListener>
-{
-    public ServletContextAttributeListenerTracker(final BundleContext context, final WhiteboardManager manager)
-    {
-        super(manager, context, createListenerFilterExpression(ServletContextAttributeListener.class));
-    }
-
-    @Override
-    protected WhiteboardServiceInfo<ServletContextAttributeListener> getServiceInfo(final ServiceReference<ServletContextAttributeListener> ref) {
-        return new ServletContextAttributeListenerInfo(ref);
-    }
-}
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
deleted file mode 100644
index bc48043..0000000
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextListenerTracker.java
+++ /dev/null
@@ -1,38 +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 javax.servlet.ServletContextListener;
-
-import org.apache.felix.http.base.internal.runtime.ServletContextListenerInfo;
-import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
-import org.apache.felix.http.base.internal.whiteboard.WhiteboardManager;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-
-public final class ServletContextListenerTracker extends WhiteboardServiceTracker<ServletContextListener>
-{
-    public ServletContextListenerTracker(final BundleContext context, final WhiteboardManager manager)
-    {
-        super(manager, context, createListenerFilterExpression(ServletContextListener.class));
-    }
-
-    @Override
-    protected WhiteboardServiceInfo<ServletContextListener> getServiceInfo(final ServiceReference<ServletContextListener> ref) {
-        return new ServletContextListenerInfo(ref);
-    }
-}
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
deleted file mode 100644
index 1931d3a..0000000
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletRequestAttributeListenerTracker.java
+++ /dev/null
@@ -1,38 +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 javax.servlet.ServletRequestAttributeListener;
-
-import org.apache.felix.http.base.internal.runtime.ServletRequestAttributeListenerInfo;
-import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
-import org.apache.felix.http.base.internal.whiteboard.WhiteboardManager;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-
-public final class ServletRequestAttributeListenerTracker extends WhiteboardServiceTracker<ServletRequestAttributeListener>
-{
-    public ServletRequestAttributeListenerTracker(final BundleContext context, final WhiteboardManager manager)
-    {
-        super(manager, context, createListenerFilterExpression(ServletRequestAttributeListener.class));
-    }
-
-    @Override
-    protected WhiteboardServiceInfo<ServletRequestAttributeListener> getServiceInfo(final ServiceReference<ServletRequestAttributeListener> ref) {
-        return new ServletRequestAttributeListenerInfo(ref);
-    }
-}
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
deleted file mode 100644
index e7c2eca..0000000
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletRequestListenerTracker.java
+++ /dev/null
@@ -1,38 +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 javax.servlet.ServletRequestListener;
-
-import org.apache.felix.http.base.internal.runtime.ServletRequestListenerInfo;
-import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
-import org.apache.felix.http.base.internal.whiteboard.WhiteboardManager;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-
-public final class ServletRequestListenerTracker extends WhiteboardServiceTracker<ServletRequestListener>
-{
-    public ServletRequestListenerTracker(final BundleContext context, final WhiteboardManager manager)
-    {
-        super(manager, context, createListenerFilterExpression(ServletRequestListener.class));
-    }
-
-    @Override
-    protected WhiteboardServiceInfo<ServletRequestListener> getServiceInfo(final ServiceReference<ServletRequestListener> ref) {
-        return new ServletRequestListenerInfo(ref);
-    }
-}
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
index 4d32e1d..e19b860 100644
--- 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
@@ -25,7 +25,6 @@
 import org.osgi.framework.Constants;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
-import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
 import org.osgi.util.tracker.ServiceTracker;
 
 /**
@@ -39,17 +38,6 @@
     /** Map containing all info objects reported from the trackers. */
     private final Map<Long, WhiteboardServiceInfo<T>> allInfos = new ConcurrentHashMap<Long, WhiteboardServiceInfo<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
diff --git a/http/base/src/test/java/org/apache/felix/http/base/internal/registry/HandlerRegistryTest.java b/http/base/src/test/java/org/apache/felix/http/base/internal/registry/HandlerRegistryTest.java
index 08834df..ba24f25 100644
--- a/http/base/src/test/java/org/apache/felix/http/base/internal/registry/HandlerRegistryTest.java
+++ b/http/base/src/test/java/org/apache/felix/http/base/internal/registry/HandlerRegistryTest.java
@@ -73,7 +73,7 @@
         assertTrue(registry.getRuntimeInfo(dto, holder));
         assertEquals("Precondition", 0, dto.servletDTOs.length);
 
-        registry.addServlet(handler);
+        registry.getRegistry(handler.getContextServiceId()).registerServlet(handler);
         Mockito.verify(servlet, Mockito.times(1)).init(Mockito.any(ServletConfig.class));
         assertTrue(registry.getRuntimeInfo(dto, holder));
         assertEquals(1, dto.servletDTOs.length);
@@ -81,13 +81,13 @@
 
         final ServletInfo info2 = new ServletInfo("bar", "/bar", 0, Collections.<String, String> emptyMap());
         ServletHandler handler2 = new HttpServiceServletHandler(null, info2, Mockito.mock(Servlet.class));
-        registry.addServlet(handler2);
+        registry.getRegistry(handler.getContextServiceId()).registerServlet(handler2);
         assertTrue(registry.getRuntimeInfo(dto, holder));
         assertEquals(2, dto.servletDTOs.length);
 
         final ServletInfo info3 = new ServletInfo("zar", "/foo", 0, Collections.<String, String> emptyMap());
         ServletHandler handler3 = new HttpServiceServletHandler(null,info3, Mockito.mock(Servlet.class));
-        registry.addServlet(handler3);
+        registry.getRegistry(handler.getContextServiceId()).registerServlet(handler3);
         assertTrue(registry.getRuntimeInfo(dto, holder));
         assertEquals(2, dto.servletDTOs.length);
         assertEquals(1, holder.failedServletDTOs.size());
diff --git a/http/base/src/test/java/org/apache/felix/http/base/internal/whiteboard/FailureStateHandlerTest.java b/http/base/src/test/java/org/apache/felix/http/base/internal/whiteboard/FailureStateHandlerTest.java
index 14da25d..09eaa06 100644
--- a/http/base/src/test/java/org/apache/felix/http/base/internal/whiteboard/FailureStateHandlerTest.java
+++ b/http/base/src/test/java/org/apache/felix/http/base/internal/whiteboard/FailureStateHandlerTest.java
@@ -17,25 +17,44 @@
 package org.apache.felix.http.base.internal.whiteboard;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
 
 import org.apache.felix.http.base.internal.runtime.ServletInfo;
 import org.apache.felix.http.base.internal.runtime.dto.FailedDTOHolder;
 import org.junit.Test;
 import org.osgi.service.http.runtime.dto.DTOConstants;
+import org.osgi.service.http.runtime.dto.FailedServletDTO;
 
 public class FailureStateHandlerTest {
 
+    private void assertContainsExactly(final List<FailedServletDTO> dtos, final long[] contextIds)
+    {
+        assertEquals(dtos.size(), contextIds.length);
+        final Set<Long> set = new HashSet<Long>();
+        for(final long l : contextIds)
+        {
+            set.add(l);
+        }
+        for(final FailedServletDTO dto : dtos)
+        {
+            assertTrue(set.remove(dto.servletContextId));
+        }
+    }
+
     @Test public void testAddRemoveNoContext()
     {
-        final ServletInfo info = new ServletInfo("test", "/test", 3, Collections.EMPTY_MAP);
+        final ServletInfo info = new ServletInfo("test", "/test", 3, Collections.<String, String> emptyMap());
 
         final FailureStateHandler handler = new FailureStateHandler();
         handler.add(info, DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE);
 
         final FailedDTOHolder holder = new FailedDTOHolder();
-        handler.getRuntime(holder);
+        handler.getRuntimeInfo(holder);
 
         assertEquals(1, holder.failedServletDTOs.size());
         assertEquals(DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE, holder.failedServletDTOs.get(0).failureReason);
@@ -43,35 +62,34 @@
         holder.failedServletDTOs.clear();
 
         handler.remove(info);
-        handler.getRuntime(holder);
+        handler.getRuntimeInfo(holder);
 
         assertEquals(0, holder.failedServletDTOs.size());
     }
 
     @Test public void testAddRemoveContext()
     {
-        final ServletInfo info1 = new ServletInfo("test", "/test", 3, Collections.EMPTY_MAP);
-        final ServletInfo info2 = new ServletInfo("test", "/test", 4, Collections.EMPTY_MAP);
+        final ServletInfo info1 = new ServletInfo("test", "/test", 3, Collections.<String, String> emptyMap());
+        final ServletInfo info2 = new ServletInfo("test", "/test", 4, Collections.<String, String> emptyMap());
 
         final FailureStateHandler handler = new FailureStateHandler();
         handler.add(info1, 1L, DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE);
         handler.add(info2, 2L, DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE);
 
         final FailedDTOHolder holder = new FailedDTOHolder();
-        handler.getRuntime(holder);
+        handler.getRuntimeInfo(holder);
 
         assertEquals(2, holder.failedServletDTOs.size());
         assertEquals(DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE, holder.failedServletDTOs.get(0).failureReason);
         assertEquals(DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE, holder.failedServletDTOs.get(1).failureReason);
-        assertEquals(1L, holder.failedServletDTOs.get(0).servletContextId);
-        assertEquals(2L, holder.failedServletDTOs.get(1).servletContextId);
+        assertContainsExactly(holder.failedServletDTOs, new long[] {1L, 2L});
 
 
         handler.remove(info1, 1L);
         handler.remove(info2, 2L);
 
         holder.failedServletDTOs.clear();
-        handler.getRuntime(holder);
+        handler.getRuntimeInfo(holder);
 
         assertEquals(0, holder.failedServletDTOs.size());
     }