You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by fm...@apache.org on 2011/01/10 08:04:24 UTC

svn commit: r1057092 - in /felix/trunk/http/base/src: main/java/org/apache/felix/http/base/internal/ main/java/org/apache/felix/http/base/internal/context/ main/java/org/apache/felix/http/base/internal/listener/ main/java/org/apache/felix/http/base/int...

Author: fmeschbe
Date: Mon Jan 10 07:04:23 2011
New Revision: 1057092

URL: http://svn.apache.org/viewvc?rev=1057092&view=rev
Log:
FELIX-1962 Support for listeners in the base bundle: Context Attribute and Request Attribute as well as request events are handled from within. Session and Session Attribute events are handled through a hook request to be installed in the actual servlet container. This works with the EventDispatcher class similarly to the DispatcherServlet.

Added:
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/EventDispatcher.java   (with props)
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/AbstractListenerManager.java   (with props)
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/HttpSessionAttributeListenerManager.java   (with props)
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/HttpSessionListenerManager.java   (with props)
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletContextAttributeListenerManager.java   (with props)
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletRequestAttributeListenerManager.java   (with props)
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletRequestListenerManager.java   (with props)
Modified:
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/AbstractHttpActivator.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/DispatcherServlet.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/context/ServletContextImpl.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/context/ServletContextManager.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceImpl.java
    felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/context/ServletContextImplTest.java
    felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/context/ServletContextManagerTest.java

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/AbstractHttpActivator.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/AbstractHttpActivator.java?rev=1057092&r1=1057091&r2=1057092&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/AbstractHttpActivator.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/AbstractHttpActivator.java Mon Jan 10 07:04:23 2011
@@ -20,6 +20,7 @@ public abstract class AbstractHttpActiva
     extends AbstractActivator
 {
     private DispatcherServlet dispatcher;
+    private EventDispatcher eventDispatcher;
     private HttpServiceController controller;
 
     protected final DispatcherServlet getDispatcherServlet()
@@ -27,6 +28,11 @@ public abstract class AbstractHttpActiva
         return this.dispatcher;
     }
 
+    protected final EventDispatcher getEventDispatcher()
+    {
+        return this.eventDispatcher;
+    }
+
     protected final HttpServiceController getHttpServiceController()
     {
         return this.controller;
@@ -37,6 +43,7 @@ public abstract class AbstractHttpActiva
     {
         this.controller = new HttpServiceController(getBundleContext());
         this.dispatcher = new DispatcherServlet(this.controller);
+        this.eventDispatcher = new EventDispatcher(this.controller);
     }
 
     protected void doStop()

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/DispatcherServlet.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/DispatcherServlet.java?rev=1057092&r1=1057091&r2=1057092&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/DispatcherServlet.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/DispatcherServlet.java Mon Jan 10 07:04:23 2011
@@ -18,9 +18,16 @@ package org.apache.felix.http.base.inter
 
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
 import javax.servlet.http.HttpServletResponse;
+import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
 import javax.servlet.ServletConfig;
+import javax.servlet.ServletRequestAttributeEvent;
+import javax.servlet.ServletRequestEvent;
+
+import org.apache.felix.http.base.internal.listener.ServletRequestAttributeListenerManager;
+
 import java.io.IOException;
 
 public final class DispatcherServlet
@@ -52,6 +59,67 @@ public final class DispatcherServlet
     protected void service(HttpServletRequest req, HttpServletResponse res)
         throws ServletException, IOException
     {
-        this.controller.getDispatcher().dispatch(req, res);
+        final ServletRequestEvent sre = new ServletRequestEvent(getServletContext(), req);
+        this.controller.getRequestListener().requestInitialized(sre);
+        try
+        {
+            req = new AttributeEventRequest(getServletContext(), this.controller.getRequestAttributeListener(), req);
+            this.controller.getDispatcher().dispatch(req, res);
+        }
+        finally
+        {
+            this.controller.getRequestListener().requestDestroyed(sre);
+        }
+    }
+
+    private static class AttributeEventRequest extends HttpServletRequestWrapper
+    {
+
+        private final ServletContext servletContext;
+        private final ServletRequestAttributeListenerManager requestAttributeListener;
+
+        public AttributeEventRequest(ServletContext servletContext,
+            ServletRequestAttributeListenerManager requestAttributeListener, HttpServletRequest request)
+        {
+            super(request);
+            this.servletContext = servletContext;
+            this.requestAttributeListener = requestAttributeListener;
+        }
+
+        public void setAttribute(String name, Object value)
+        {
+            if (value == null)
+            {
+                this.removeAttribute(name);
+            }
+            else if (name != null)
+            {
+                Object oldValue = this.getAttribute(name);
+                super.setAttribute(name, value);
+
+                if (oldValue == null)
+                {
+                    requestAttributeListener.attributeAdded(new ServletRequestAttributeEvent(servletContext, this,
+                        name, value));
+                }
+                else
+                {
+                    requestAttributeListener.attributeReplaced(new ServletRequestAttributeEvent(servletContext, this,
+                        name, oldValue));
+                }
+            }
+        }
+
+        public void removeAttribute(String name)
+        {
+            Object oldValue = this.getAttribute(name);
+            super.removeAttribute(name);
+
+            if (oldValue != null)
+            {
+                requestAttributeListener.attributeRemoved(new ServletRequestAttributeEvent(servletContext, this, name,
+                    oldValue));
+            }
+        }
     }
 }

Added: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/EventDispatcher.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/EventDispatcher.java?rev=1057092&view=auto
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/EventDispatcher.java (added)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/EventDispatcher.java Mon Jan 10 07:04:23 2011
@@ -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;
+
+import javax.servlet.http.HttpSessionAttributeListener;
+import javax.servlet.http.HttpSessionBindingEvent;
+import javax.servlet.http.HttpSessionEvent;
+import javax.servlet.http.HttpSessionListener;
+
+/**
+ * The <code>EventDispatcher</code> dispatches events sent from the servlet
+ * container (embedded Jetty or container in which the framework is running
+ * in bridged mode) to any {@link HttpSessionAttributeListener} or
+ * {@link HttpSessionListener} services.
+ */
+public class EventDispatcher implements HttpSessionAttributeListener, HttpSessionListener
+{
+
+    private final HttpServiceController controller;
+
+    EventDispatcher(final HttpServiceController controller)
+    {
+        this.controller = controller;
+    }
+
+    public void sessionCreated(HttpSessionEvent se)
+    {
+        controller.getSessionListener().sessionCreated(se);
+    }
+
+    public void sessionDestroyed(HttpSessionEvent se)
+    {
+        controller.getSessionListener().sessionDestroyed(se);
+    }
+
+    public void attributeAdded(HttpSessionBindingEvent se)
+    {
+        controller.getSessionAttributeListener().attributeAdded(se);
+    }
+
+    public void attributeRemoved(HttpSessionBindingEvent se)
+    {
+        controller.getSessionAttributeListener().attributeRemoved(se);
+    }
+
+    public void attributeReplaced(HttpSessionBindingEvent se)
+    {
+        controller.getSessionAttributeListener().attributeReplaced(se);
+    }
+}

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/EventDispatcher.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/EventDispatcher.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java?rev=1057092&r1=1057091&r2=1057092&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java Mon Jan 10 07:04:23 2011
@@ -16,15 +16,22 @@
  */
 package org.apache.felix.http.base.internal;
 
+import java.util.Hashtable;
+
+import javax.servlet.ServletContext;
+
+import org.apache.felix.http.api.ExtHttpService;
+import org.apache.felix.http.base.internal.dispatch.Dispatcher;
+import org.apache.felix.http.base.internal.handler.HandlerRegistry;
+import org.apache.felix.http.base.internal.listener.HttpSessionAttributeListenerManager;
+import org.apache.felix.http.base.internal.listener.HttpSessionListenerManager;
+import org.apache.felix.http.base.internal.listener.ServletContextAttributeListenerManager;
+import org.apache.felix.http.base.internal.listener.ServletRequestAttributeListenerManager;
+import org.apache.felix.http.base.internal.listener.ServletRequestListenerManager;
+import org.apache.felix.http.base.internal.service.HttpServiceFactory;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.http.HttpService;
-import org.apache.felix.http.base.internal.handler.HandlerRegistry;
-import org.apache.felix.http.base.internal.dispatch.Dispatcher;
-import org.apache.felix.http.base.internal.service.HttpServiceFactory;
-import org.apache.felix.http.api.ExtHttpService;
-import javax.servlet.ServletContext;
-import java.util.Hashtable;
 
 public final class HttpServiceController
 {
@@ -32,6 +39,11 @@ public final class HttpServiceController
     private final HandlerRegistry registry;
     private final Dispatcher dispatcher;
     private final Hashtable<String, Object> serviceProps;
+    private final ServletContextAttributeListenerManager contextAttributeListener;
+    private final ServletRequestListenerManager requestListener;
+    private final ServletRequestAttributeListenerManager requestAttributeListener;
+    private final HttpSessionListenerManager sessionListener;
+    private final HttpSessionAttributeListenerManager sessionAttributeListener;
     private ServiceRegistration serviceReg;
 
     public HttpServiceController(BundleContext bundleContext)
@@ -40,6 +52,11 @@ public final class HttpServiceController
         this.registry = new HandlerRegistry();
         this.dispatcher = new Dispatcher(this.registry);
         this.serviceProps = new Hashtable<String, Object>();
+        this.contextAttributeListener = new ServletContextAttributeListenerManager(bundleContext);
+        this.requestListener = new ServletRequestListenerManager(bundleContext);
+        this.requestAttributeListener = new ServletRequestAttributeListenerManager(bundleContext);
+        this.sessionListener = new HttpSessionListenerManager(bundleContext);
+        this.sessionAttributeListener = new HttpSessionAttributeListenerManager(bundleContext);
     }
 
     public Dispatcher getDispatcher()
@@ -47,6 +64,31 @@ public final class HttpServiceController
         return this.dispatcher;
     }
 
+    public ServletContextAttributeListenerManager getContextAttributeListener()
+    {
+        return contextAttributeListener;
+    }
+
+    public ServletRequestListenerManager getRequestListener()
+    {
+        return requestListener;
+    }
+
+    public ServletRequestAttributeListenerManager getRequestAttributeListener()
+    {
+        return requestAttributeListener;
+    }
+
+    public HttpSessionListenerManager getSessionListener()
+    {
+        return sessionListener;
+    }
+
+    public HttpSessionAttributeListenerManager getSessionAttributeListener()
+    {
+        return sessionAttributeListener;
+    }
+
     public void setProperties(Hashtable<String, Object> props)
     {
         this.serviceProps.clear();
@@ -59,7 +101,13 @@ public final class HttpServiceController
 
     public void register(ServletContext servletContext)
     {
-        HttpServiceFactory factory = new HttpServiceFactory(servletContext, this.registry);
+        this.contextAttributeListener.open();
+        this.requestListener.open();
+        this.requestAttributeListener.open();
+        this.sessionListener.open();
+        this.sessionAttributeListener.open();
+
+        HttpServiceFactory factory = new HttpServiceFactory(servletContext, this.registry, this.contextAttributeListener);
         String[] ifaces = new String[] { HttpService.class.getName(), ExtHttpService.class.getName() };
         this.serviceReg = this.bundleContext.registerService(ifaces, factory, this.serviceProps);
     }
@@ -70,6 +118,12 @@ public final class HttpServiceController
             return;
         }
 
+        this.sessionAttributeListener.close();
+        this.sessionListener.close();
+        this.contextAttributeListener.close();
+        this.requestListener.close();
+        this.requestAttributeListener.close();
+
         try {
             this.serviceReg.unregister();
             this.registry.removeAll();

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/context/ServletContextImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/context/ServletContextImpl.java?rev=1057092&r1=1057091&r2=1057092&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/context/ServletContextImpl.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/context/ServletContextImpl.java Mon Jan 10 07:04:23 2011
@@ -16,22 +16,29 @@
  */
 package org.apache.felix.http.base.internal.context;
 
-import org.osgi.service.http.HttpContext;
-import org.osgi.framework.Bundle;
-import org.apache.felix.http.base.internal.util.MimeTypes;
-import org.apache.felix.http.base.internal.logger.SystemLogger;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 
-import javax.servlet.ServletContext;
 import javax.servlet.RequestDispatcher;
 import javax.servlet.Servlet;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextAttributeEvent;
+import javax.servlet.ServletContextAttributeListener;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
-import java.net.URL;
-import java.io.InputStream;
-import java.io.IOException;
+
+import org.apache.felix.http.base.internal.logger.SystemLogger;
+import org.apache.felix.http.base.internal.util.MimeTypes;
+import org.osgi.framework.Bundle;
+import org.osgi.service.http.HttpContext;
 
 public final class ServletContextImpl
     implements ExtServletContext
@@ -40,13 +47,16 @@ public final class ServletContextImpl
     private final ServletContext context;
     private final HttpContext httpContext;
     private final Map<String, Object> attributes;
+    private final ServletContextAttributeListener attributeListener;
 
-    public ServletContextImpl(Bundle bundle, ServletContext context, HttpContext httpContext)
+    public ServletContextImpl(Bundle bundle, ServletContext context, HttpContext httpContext,
+        ServletContextAttributeListener attributeListener)
     {
         this.bundle = bundle;
         this.context = context;
         this.httpContext = httpContext;
         this.attributes = new ConcurrentHashMap<String, Object>();
+        this.attributeListener = attributeListener;
     }
 
     public String getContextPath()
@@ -78,7 +88,7 @@ public final class ServletContextImpl
 
         Set<String> set = new HashSet<String>();
         while (paths.hasMoreElements()) {
-            set.add((String)paths.nextElement());
+            set.add((String) paths.nextElement());
         }
 
         return set;
@@ -149,14 +159,31 @@ public final class ServletContextImpl
 
     public void setAttribute(String name, Object value)
     {
-        if ((name != null) && (value != null)) {
-            this.attributes.put(name, value);
+        if (value == null)
+        {
+            this.removeAttribute(name);
+        }
+        else if (name != null)
+        {
+            Object oldValue = this.attributes.put(name, value);
+            if (oldValue == null)
+            {
+                attributeListener.attributeAdded(new ServletContextAttributeEvent(this, name, value));
+            }
+            else
+            {
+                attributeListener.attributeReplaced(new ServletContextAttributeEvent(this, name, oldValue));
+            }
         }
     }
 
     public void removeAttribute(String name)
     {
-        this.attributes.remove(name);
+        Object oldValue = this.attributes.remove(name);
+        if (oldValue != null)
+        {
+            attributeListener.attributeRemoved(new ServletContextAttributeEvent(this, name, oldValue));
+        }
     }
 
     @SuppressWarnings("deprecation")

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/context/ServletContextManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/context/ServletContextManager.java?rev=1057092&r1=1057091&r2=1057092&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/context/ServletContextManager.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/context/ServletContextManager.java Mon Jan 10 07:04:23 2011
@@ -16,22 +16,28 @@
  */
 package org.apache.felix.http.base.internal.context;
 
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextAttributeListener;
+
 import org.osgi.framework.Bundle;
 import org.osgi.service.http.HttpContext;
-import javax.servlet.ServletContext;
-import java.util.Map;
-import java.util.HashMap;
 
 public final class ServletContextManager
 {
     private final Bundle bundle;
     private final ServletContext context;
+    private final ServletContextAttributeListener attributeListener;
     private final Map<HttpContext, ExtServletContext> contextMap;
 
-    public ServletContextManager(Bundle bundle, ServletContext context)
+    public ServletContextManager(Bundle bundle, ServletContext context,
+        ServletContextAttributeListener attributeListener)
     {
         this.bundle = bundle;
         this.context = context;
+        this.attributeListener = attributeListener;
         this.contextMap = new HashMap<HttpContext, ExtServletContext>();
     }
 
@@ -49,7 +55,7 @@ public final class ServletContextManager
 
     private ExtServletContext addServletContext(HttpContext httpContext)
     {
-        ExtServletContext context = new ServletContextImpl(this.bundle, this.context, httpContext);
+        ExtServletContext context = new ServletContextImpl(this.bundle, this.context, httpContext, attributeListener);
         this.contextMap.put(httpContext, context);
         return context;
     }

Added: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/AbstractListenerManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/AbstractListenerManager.java?rev=1057092&view=auto
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/AbstractListenerManager.java (added)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/AbstractListenerManager.java Mon Jan 10 07:04:23 2011
@@ -0,0 +1,108 @@
+/*
+ * 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.listener;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+
+public class AbstractListenerManager<ListenerType> extends ServiceTracker
+{
+
+    private ArrayList<ListenerType> allContextListeners;
+
+    private final Object lock;
+
+    protected AbstractListenerManager(BundleContext context, Class<ListenerType> clazz)
+    {
+        super(context, clazz.getName(), null);
+        lock = new Object();
+    }
+
+    @SuppressWarnings("unchecked")
+    protected final Iterator<ListenerType> getContextListeners()
+    {
+        ArrayList<ListenerType> result = allContextListeners;
+        if (result == null)
+        {
+            synchronized (lock)
+            {
+                if (allContextListeners == null)
+                {
+                    Object[] services = getServices();
+                    if (services != null && services.length > 0)
+                    {
+                        result = new ArrayList<ListenerType>(services.length);
+                        for (Object service : services)
+                        {
+                            result.add((ListenerType) service);
+                        }
+                    }
+                    else
+                    {
+                        result = new ArrayList<ListenerType>(0);
+                    }
+                    this.allContextListeners = result;
+                }
+                else
+                {
+                    result = this.allContextListeners;
+                }
+            }
+        }
+        return result.iterator();
+    }
+
+    @Override
+    public Object addingService(ServiceReference reference)
+    {
+        synchronized (lock)
+        {
+            allContextListeners = null;
+        }
+
+        return super.addingService(reference);
+    }
+
+    @Override
+    public void modifiedService(ServiceReference reference, Object service)
+    {
+        synchronized (lock)
+        {
+            allContextListeners = null;
+        }
+
+        super.modifiedService(reference, service);
+    }
+
+    @Override
+    public void removedService(ServiceReference reference, Object service)
+    {
+        synchronized (lock)
+        {
+            allContextListeners = null;
+        }
+
+        super.removedService(reference, service);
+    }
+}

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/AbstractListenerManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/AbstractListenerManager.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/HttpSessionAttributeListenerManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/HttpSessionAttributeListenerManager.java?rev=1057092&view=auto
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/HttpSessionAttributeListenerManager.java (added)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/HttpSessionAttributeListenerManager.java Mon Jan 10 07:04:23 2011
@@ -0,0 +1,68 @@
+/*
+ * 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.listener;
+
+import java.util.Iterator;
+
+import javax.servlet.http.HttpSessionAttributeListener;
+import javax.servlet.http.HttpSessionBindingEvent;
+
+import org.osgi.framework.BundleContext;
+
+/**
+ * The <code>ProxyListener</code> implements the Servlet API 2.4 listener
+ * interfaces forwarding any event calls to registered OSGi services
+ * implementing the respective Servlet API 2.4 listener interface.
+ */
+public class HttpSessionAttributeListenerManager extends AbstractListenerManager<HttpSessionAttributeListener>
+    implements HttpSessionAttributeListener
+{
+
+    public HttpSessionAttributeListenerManager(BundleContext context)
+    {
+        super(context, HttpSessionAttributeListener.class);
+    }
+
+    public void attributeAdded(final HttpSessionBindingEvent se)
+    {
+        final Iterator<HttpSessionAttributeListener> listeners = getContextListeners();
+        while (listeners.hasNext())
+        {
+            listeners.next().attributeAdded(se);
+        }
+    }
+
+    public void attributeRemoved(final HttpSessionBindingEvent se)
+    {
+        final Iterator<HttpSessionAttributeListener> listeners = getContextListeners();
+        while (listeners.hasNext())
+        {
+            listeners.next().attributeRemoved(se);
+        }
+    }
+
+    public void attributeReplaced(final HttpSessionBindingEvent se)
+    {
+        final Iterator<HttpSessionAttributeListener> listeners = getContextListeners();
+        while (listeners.hasNext())
+        {
+            listeners.next().attributeReplaced(se);
+        }
+    }
+}

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/HttpSessionAttributeListenerManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/HttpSessionAttributeListenerManager.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/HttpSessionListenerManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/HttpSessionListenerManager.java?rev=1057092&view=auto
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/HttpSessionListenerManager.java (added)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/HttpSessionListenerManager.java Mon Jan 10 07:04:23 2011
@@ -0,0 +1,59 @@
+/*
+ * 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.listener;
+
+import java.util.Iterator;
+
+import javax.servlet.http.HttpSessionEvent;
+import javax.servlet.http.HttpSessionListener;
+
+import org.osgi.framework.BundleContext;
+
+/**
+ * The <code>ProxyListener</code> implements the Servlet API 2.4 listener
+ * interfaces forwarding any event calls to registered OSGi services
+ * implementing the respective Servlet API 2.4 listener interface.
+ */
+public class HttpSessionListenerManager extends AbstractListenerManager<HttpSessionListener> implements
+    HttpSessionListener
+{
+
+    public HttpSessionListenerManager(BundleContext context)
+    {
+        super(context, HttpSessionListener.class);
+    }
+
+    public void sessionCreated(final HttpSessionEvent se)
+    {
+        final Iterator<HttpSessionListener> listeners = getContextListeners();
+        while (listeners.hasNext())
+        {
+            listeners.next().sessionCreated(se);
+        }
+    }
+
+    public void sessionDestroyed(final HttpSessionEvent se)
+    {
+        final Iterator<HttpSessionListener> listeners = getContextListeners();
+        while (listeners.hasNext())
+        {
+            listeners.next().sessionDestroyed(se);
+        }
+    }
+}

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/HttpSessionListenerManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/HttpSessionListenerManager.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletContextAttributeListenerManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletContextAttributeListenerManager.java?rev=1057092&view=auto
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletContextAttributeListenerManager.java (added)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletContextAttributeListenerManager.java Mon Jan 10 07:04:23 2011
@@ -0,0 +1,68 @@
+/*
+ * 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.listener;
+
+import java.util.Iterator;
+
+import javax.servlet.ServletContextAttributeEvent;
+import javax.servlet.ServletContextAttributeListener;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The <code>ProxyListener</code> implements the Servlet API 2.4 listener
+ * interfaces forwarding any event calls to registered OSGi services
+ * implementing the respective Servlet API 2.4 listener interface.
+ */
+public class ServletContextAttributeListenerManager extends AbstractListenerManager<ServletContextAttributeListener>
+    implements ServletContextAttributeListener
+{
+
+    public ServletContextAttributeListenerManager(BundleContext context)
+    {
+        super(context, ServletContextAttributeListener.class);
+    }
+
+    public void attributeAdded(final ServletContextAttributeEvent scab)
+    {
+        final Iterator<ServletContextAttributeListener> listeners = getContextListeners();
+        while (listeners.hasNext())
+        {
+            listeners.next().attributeAdded(scab);
+        }
+    }
+
+    public void attributeRemoved(final ServletContextAttributeEvent scab)
+    {
+        final Iterator<ServletContextAttributeListener> listeners = getContextListeners();
+        while (listeners.hasNext())
+        {
+            listeners.next().attributeRemoved(scab);
+        }
+    }
+
+    public void attributeReplaced(final ServletContextAttributeEvent scab)
+    {
+        final Iterator<ServletContextAttributeListener> listeners = getContextListeners();
+        while (listeners.hasNext())
+        {
+            listeners.next().attributeReplaced(scab);
+        }
+    }
+
+}

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletContextAttributeListenerManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletContextAttributeListenerManager.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletRequestAttributeListenerManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletRequestAttributeListenerManager.java?rev=1057092&view=auto
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletRequestAttributeListenerManager.java (added)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletRequestAttributeListenerManager.java Mon Jan 10 07:04:23 2011
@@ -0,0 +1,68 @@
+/*
+ * 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.listener;
+
+import java.util.Iterator;
+
+import javax.servlet.ServletRequestAttributeEvent;
+import javax.servlet.ServletRequestAttributeListener;
+
+import org.osgi.framework.BundleContext;
+
+/**
+ * The <code>ProxyListener</code> implements the Servlet API 2.4 listener
+ * interfaces forwarding any event calls to registered OSGi services
+ * implementing the respective Servlet API 2.4 listener interface.
+ */
+public class ServletRequestAttributeListenerManager extends AbstractListenerManager<ServletRequestAttributeListener>
+{
+
+    public ServletRequestAttributeListenerManager(BundleContext context)
+    {
+        super(context, ServletRequestAttributeListener.class);
+    }
+
+    public void attributeAdded(final ServletRequestAttributeEvent srae)
+    {
+        final Iterator<ServletRequestAttributeListener> listeners = getContextListeners();
+        while (listeners.hasNext())
+        {
+            listeners.next().attributeAdded(srae);
+        }
+    }
+
+    public void attributeRemoved(final ServletRequestAttributeEvent srae)
+    {
+        final Iterator<ServletRequestAttributeListener> listeners = getContextListeners();
+        while (listeners.hasNext())
+        {
+            listeners.next().attributeRemoved(srae);
+        }
+    }
+
+    public void attributeReplaced(final ServletRequestAttributeEvent srae)
+    {
+        final Iterator<ServletRequestAttributeListener> listeners = getContextListeners();
+        while (listeners.hasNext())
+        {
+            listeners.next().attributeReplaced(srae);
+        }
+    }
+
+}

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletRequestAttributeListenerManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletRequestAttributeListenerManager.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletRequestListenerManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletRequestListenerManager.java?rev=1057092&view=auto
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletRequestListenerManager.java (added)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletRequestListenerManager.java Mon Jan 10 07:04:23 2011
@@ -0,0 +1,59 @@
+/*
+ * 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.listener;
+
+import java.util.Iterator;
+
+import javax.servlet.ServletRequestEvent;
+import javax.servlet.ServletRequestListener;
+
+import org.osgi.framework.BundleContext;
+
+/**
+ * The <code>ProxyListener</code> implements the Servlet API 2.4 listener
+ * interfaces forwarding any event calls to registered OSGi services
+ * implementing the respective Servlet API 2.4 listener interface.
+ */
+public class ServletRequestListenerManager extends AbstractListenerManager<ServletRequestListener>
+{
+
+    public ServletRequestListenerManager(BundleContext context)
+    {
+        super(context, ServletRequestListener.class);
+    }
+
+    public void requestDestroyed(final ServletRequestEvent sre)
+    {
+        final Iterator<ServletRequestListener> listeners = getContextListeners();
+        while (listeners.hasNext())
+        {
+            listeners.next().requestDestroyed(sre);
+        }
+    }
+
+    public void requestInitialized(final ServletRequestEvent sre)
+    {
+        final Iterator<ServletRequestListener> listeners = getContextListeners();
+        while (listeners.hasNext())
+        {
+            listeners.next().requestInitialized(sre);
+        }
+    }
+
+}

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletRequestListenerManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletRequestListenerManager.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java?rev=1057092&r1=1057091&r2=1057092&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java Mon Jan 10 07:04:23 2011
@@ -16,27 +16,32 @@
  */
 package org.apache.felix.http.base.internal.service;
 
-import org.osgi.framework.ServiceFactory;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextAttributeListener;
+
+import org.apache.felix.http.base.internal.handler.HandlerRegistry;
 import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceFactory;
 import org.osgi.framework.ServiceRegistration;
-import org.apache.felix.http.base.internal.handler.HandlerRegistry;
-import javax.servlet.ServletContext;
 
 public final class HttpServiceFactory
     implements ServiceFactory
 {
     private final ServletContext context;
+    private final ServletContextAttributeListener attributeListener;
     private final HandlerRegistry handlerRegistry;
 
-    public HttpServiceFactory(ServletContext context, HandlerRegistry handlerRegistry)
+    public HttpServiceFactory(ServletContext context, HandlerRegistry handlerRegistry,
+        ServletContextAttributeListener attributeListener)
     {
         this.context = context;
+        this.attributeListener = attributeListener;
         this.handlerRegistry = handlerRegistry;
     }
 
     public Object getService(Bundle bundle, ServiceRegistration reg)
     {
-        return new HttpServiceImpl(bundle, this.context, this.handlerRegistry);
+        return new HttpServiceImpl(bundle, this.context, this.handlerRegistry, attributeListener);
     }
 
     public void ungetService(Bundle bundle, ServiceRegistration reg, Object service)

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceImpl.java?rev=1057092&r1=1057091&r2=1057092&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceImpl.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceImpl.java Mon Jan 10 07:04:23 2011
@@ -39,13 +39,13 @@ public final class HttpServiceImpl
     private final HashSet<Filter> localFilters;
     private final ServletContextManager contextManager;
 
-    public HttpServiceImpl(Bundle bundle, ServletContext context, HandlerRegistry handlerRegistry)
+    public HttpServiceImpl(Bundle bundle, ServletContext context, HandlerRegistry handlerRegistry, ServletContextAttributeListener servletAttributeListener)
     {
         this.bundle = bundle;
         this.handlerRegistry = handlerRegistry;
         this.localServlets = new HashSet<Servlet>();
         this.localFilters = new HashSet<Filter>();
-        this.contextManager = new ServletContextManager(this.bundle, context);
+        this.contextManager = new ServletContextManager(this.bundle, context, servletAttributeListener);
     }
 
     private ExtServletContext getServletContext(HttpContext context)

Modified: felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/context/ServletContextImplTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/context/ServletContextImplTest.java?rev=1057092&r1=1057091&r2=1057092&view=diff
==============================================================================
--- felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/context/ServletContextImplTest.java (original)
+++ felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/context/ServletContextImplTest.java Mon Jan 10 07:04:23 2011
@@ -26,6 +26,9 @@ import org.osgi.service.http.HttpContext
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.ServletContext;
+import javax.servlet.ServletContextAttributeEvent;
+import javax.servlet.ServletContextAttributeListener;
+
 import java.net.URL;
 import java.util.*;
 
@@ -33,6 +36,7 @@ public class ServletContextImplTest
 {
     private Bundle bundle;
     private HttpContext httpContext;
+    private AttributeListener listener;
     private ServletContextImpl context;
 
     @Before
@@ -41,7 +45,8 @@ public class ServletContextImplTest
         this.bundle = Mockito.mock(Bundle.class);
         ServletContext globalContext = Mockito.mock(ServletContext.class);
         this.httpContext = Mockito.mock(HttpContext.class);
-        this.context = new ServletContextImpl(this.bundle, globalContext, this.httpContext);
+        this.listener = new AttributeListener();
+        this.context = new ServletContextImpl(this.bundle, globalContext, this.httpContext, this.listener);
     }
 
     @Test
@@ -50,7 +55,7 @@ public class ServletContextImplTest
     {
         URL url = getClass().getResource("resource.txt");
         Assert.assertNotNull(url);
-        
+
         Mockito.when(this.httpContext.getResource("resource.txt")).thenReturn(url);
         Assert.assertNull(this.context.getResource("/notfound.txt"));
         Assert.assertEquals(url, this.context.getResource("/resource.txt"));
@@ -107,13 +112,24 @@ public class ServletContextImplTest
         Assert.assertNull(this.context.getAttribute("key1"));
 
         this.context.setAttribute("key1", "value1");
+        this.listener.checkAdded("key1", "value1");
         Assert.assertEquals("value1", this.context.getAttribute("key1"));
 
         this.context.removeAttribute("key1");
+        this.listener.checkRemoved("key1", "value1");
         Assert.assertNull(this.context.getAttribute("key1"));
 
         this.context.setAttribute("key1", null);
+        this.listener.checkNull();
         Assert.assertNull(this.context.getAttribute("key1"));
+
+        this.context.setAttribute("key1", "value1");
+        this.listener.checkAdded("key1", "value1");
+        Assert.assertEquals("value1", this.context.getAttribute("key1"));
+
+        this.context.setAttribute("key1", "newValue");
+        this.listener.checkReplaced("key1", "value1");
+        Assert.assertEquals("newValue", this.context.getAttribute("key1"));
     }
 
     @Test
@@ -124,6 +140,7 @@ public class ServletContextImplTest
         Assert.assertFalse(e.hasMoreElements());
 
         this.context.setAttribute("key1", "value1");
+        this.listener.checkAdded("key1", "value1");
         e = this.context.getAttributeNames();
         Assert.assertNotNull(e);
         Assert.assertTrue(e.hasMoreElements());
@@ -175,4 +192,72 @@ public class ServletContextImplTest
         Mockito.when(this.httpContext.handleSecurity(req, res)).thenReturn(false);
         Assert.assertFalse(this.context.handleSecurity(req, res));
     }
+
+    private static class AttributeListener implements ServletContextAttributeListener
+    {
+
+        private int type;
+
+        private String name;
+
+        private Object value;
+
+        public void attributeAdded(ServletContextAttributeEvent scab)
+        {
+            setData(1, scab);
+        }
+
+        public void attributeRemoved(ServletContextAttributeEvent scab)
+        {
+            setData(2, scab);
+        }
+
+        public void attributeReplaced(ServletContextAttributeEvent scab)
+        {
+            setData(3, scab);
+        }
+
+        private void setData(int type, ServletContextAttributeEvent scab)
+        {
+            this.type = type;
+            this.name = scab.getName();
+            this.value = scab.getValue();
+        }
+
+        void checkAdded(String name, Object value)
+        {
+            check(1, name, value);
+        }
+
+        void checkRemoved(String name, Object value)
+        {
+            check(2, name, value);
+        }
+
+        void checkReplaced(String name, Object value)
+        {
+            check(3, name, value);
+        }
+
+        void checkNull()
+        {
+            check(0, null, null);
+        }
+
+        private void check(int type, String name, Object value)
+        {
+            try
+            {
+                Assert.assertEquals(type, this.type);
+                Assert.assertEquals(name, this.name);
+                Assert.assertEquals(value, this.value);
+            }
+            finally
+            {
+                this.type = 0;
+                this.name = null;
+                this.value = null;
+            }
+        }
+    }
 }

Modified: felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/context/ServletContextManagerTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/context/ServletContextManagerTest.java?rev=1057092&r1=1057091&r2=1057092&view=diff
==============================================================================
--- felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/context/ServletContextManagerTest.java (original)
+++ felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/context/ServletContextManagerTest.java Mon Jan 10 07:04:23 2011
@@ -34,7 +34,7 @@ public class ServletContextManagerTest
     {
         Bundle bundle = Mockito.mock(Bundle.class);
         ServletContext globalContext = Mockito.mock(ServletContext.class);
-        this.manager = new ServletContextManager(bundle, globalContext);
+        this.manager = new ServletContextManager(bundle, globalContext, null);
     }
 
     @Test
@@ -54,5 +54,5 @@ public class ServletContextManagerTest
         Assert.assertNotNull(result2);
         Assert.assertNotSame(result1, result2);
     }
-    
+
 }