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.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1057092 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/AbstractHttpActivator.java b/http/base/src/main/java/org/apache/felix/http/base/internal/AbstractHttpActivator.java
index c045700..9f5f847 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/AbstractHttpActivator.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/AbstractHttpActivator.java
@@ -20,6 +20,7 @@
extends AbstractActivator
{
private DispatcherServlet dispatcher;
+ private EventDispatcher eventDispatcher;
private HttpServiceController controller;
protected final DispatcherServlet getDispatcherServlet()
@@ -27,6 +28,11 @@
return this.dispatcher;
}
+ protected final EventDispatcher getEventDispatcher()
+ {
+ return this.eventDispatcher;
+ }
+
protected final HttpServiceController getHttpServiceController()
{
return this.controller;
@@ -37,6 +43,7 @@
{
this.controller = new HttpServiceController(getBundleContext());
this.dispatcher = new DispatcherServlet(this.controller);
+ this.eventDispatcher = new EventDispatcher(this.controller);
}
protected void doStop()
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/DispatcherServlet.java b/http/base/src/main/java/org/apache/felix/http/base/internal/DispatcherServlet.java
index 88504b5..36d21b3 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/DispatcherServlet.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/DispatcherServlet.java
@@ -18,9 +18,16 @@
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 @@
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));
+ }
+ }
}
}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/EventDispatcher.java b/http/base/src/main/java/org/apache/felix/http/base/internal/EventDispatcher.java
new file mode 100644
index 0000000..40092bc
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/EventDispatcher.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;
+
+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);
+ }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java b/http/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java
index 823162b..38cb093 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java
@@ -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 @@
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 @@
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 @@
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 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 @@
return;
}
+ this.sessionAttributeListener.close();
+ this.sessionListener.close();
+ this.contextAttributeListener.close();
+ this.requestListener.close();
+ this.requestAttributeListener.close();
+
try {
this.serviceReg.unregister();
this.registry.removeAll();
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/context/ServletContextImpl.java b/http/base/src/main/java/org/apache/felix/http/base/internal/context/ServletContextImpl.java
index 9860eb9..18977ab 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/context/ServletContextImpl.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/context/ServletContextImpl.java
@@ -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 @@
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 @@
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 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")
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/context/ServletContextManager.java b/http/base/src/main/java/org/apache/felix/http/base/internal/context/ServletContextManager.java
index 2fc3810..835d41e 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/context/ServletContextManager.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/context/ServletContextManager.java
@@ -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 @@
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;
}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/listener/AbstractListenerManager.java b/http/base/src/main/java/org/apache/felix/http/base/internal/listener/AbstractListenerManager.java
new file mode 100644
index 0000000..7ca8ff7
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/listener/AbstractListenerManager.java
@@ -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);
+ }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/listener/HttpSessionAttributeListenerManager.java b/http/base/src/main/java/org/apache/felix/http/base/internal/listener/HttpSessionAttributeListenerManager.java
new file mode 100644
index 0000000..1bad90d
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/listener/HttpSessionAttributeListenerManager.java
@@ -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);
+ }
+ }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/listener/HttpSessionListenerManager.java b/http/base/src/main/java/org/apache/felix/http/base/internal/listener/HttpSessionListenerManager.java
new file mode 100644
index 0000000..890dc48
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/listener/HttpSessionListenerManager.java
@@ -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);
+ }
+ }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletContextAttributeListenerManager.java b/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletContextAttributeListenerManager.java
new file mode 100644
index 0000000..e65704e
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletContextAttributeListenerManager.java
@@ -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);
+ }
+ }
+
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletRequestAttributeListenerManager.java b/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletRequestAttributeListenerManager.java
new file mode 100644
index 0000000..25c1710
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletRequestAttributeListenerManager.java
@@ -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);
+ }
+ }
+
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletRequestListenerManager.java b/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletRequestListenerManager.java
new file mode 100644
index 0000000..627ec5a
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/listener/ServletRequestListenerManager.java
@@ -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);
+ }
+ }
+
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java b/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java
index 2dd1c3a..0e4e3c8 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java
@@ -16,27 +16,32 @@
*/
package org.apache.felix.http.base.internal.service;
-import org.osgi.framework.ServiceFactory;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.ServiceRegistration;
-import org.apache.felix.http.base.internal.handler.HandlerRegistry;
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;
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)
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceImpl.java b/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceImpl.java
index 60e069b..946d21c 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceImpl.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceImpl.java
@@ -39,13 +39,13 @@
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)
diff --git a/http/base/src/test/java/org/apache/felix/http/base/internal/context/ServletContextImplTest.java b/http/base/src/test/java/org/apache/felix/http/base/internal/context/ServletContextImplTest.java
index 4f62064..a31fa6e 100644
--- a/http/base/src/test/java/org/apache/felix/http/base/internal/context/ServletContextImplTest.java
+++ b/http/base/src/test/java/org/apache/felix/http/base/internal/context/ServletContextImplTest.java
@@ -26,6 +26,9 @@
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 @@
{
private Bundle bundle;
private HttpContext httpContext;
+ private AttributeListener listener;
private ServletContextImpl context;
@Before
@@ -41,7 +45,8 @@
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 @@
{
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 @@
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 @@
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 @@
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;
+ }
+ }
+ }
}
diff --git a/http/base/src/test/java/org/apache/felix/http/base/internal/context/ServletContextManagerTest.java b/http/base/src/test/java/org/apache/felix/http/base/internal/context/ServletContextManagerTest.java
index 5fbaa2e..f64d42e 100644
--- a/http/base/src/test/java/org/apache/felix/http/base/internal/context/ServletContextManagerTest.java
+++ b/http/base/src/test/java/org/apache/felix/http/base/internal/context/ServletContextManagerTest.java
@@ -34,7 +34,7 @@
{
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 @@
Assert.assertNotNull(result2);
Assert.assertNotSame(result1, result2);
}
-
+
}