diff options
author | Juan Gonzalez | 2017-01-20 11:48:47 +0000 |
---|---|---|
committer | Juan Gonzalez | 2017-02-15 15:55:58 +0000 |
commit | d27f1bdb863b15aac929c81fc55fd536259ab9b2 (patch) | |
tree | ede910f814904511ade134a96424e8809ecdb33e | |
parent | d071f6db6f8663fe86b9a372def46efc5b0bfeb8 (diff) | |
download | rt.equinox.bundles-d27f1bdb863b15aac929c81fc55fd536259ab9b2.tar.gz rt.equinox.bundles-d27f1bdb863b15aac929c81fc55fd536259ab9b2.tar.xz rt.equinox.bundles-d27f1bdb863b15aac929c81fc55fd536259ab9b2.zip |
Bug 510753 [http servlet] Invoke session listeners when unregistering them. Fix ListenerRegistration.equals so it gets actually removed from available EventListenersY20170216-1515Y20170216-1450Y20170216-1000I20170221-2000I20170220-2000I20170219-2000I20170218-2000I20170217-2000I20170216-2000I20170216-0140I20170215-2000
Signed-off-by: Juan Gonzalez <juangon@gmail.com>
4 files changed, 136 insertions, 6 deletions
diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/ServletTest.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/ServletTest.java index b2c1a24da..a0f8b4863 100644 --- a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/ServletTest.java +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/ServletTest.java @@ -39,6 +39,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import javax.servlet.Filter; @@ -49,6 +50,7 @@ import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; import javax.servlet.ServletContextAttributeListener; +import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.ServletException; import javax.servlet.ServletRequest; @@ -3127,6 +3129,85 @@ public class ServletTest extends BaseTest { } @Test + public void test_Listener11() throws Exception { + + final AtomicInteger listenerBalance = new AtomicInteger(0); + final AtomicReference<HttpSession> sessionReference = new AtomicReference<HttpSession>(); + + ServletContextListener scl = new ServletContextListener() { + + @Override + public void contextInitialized(ServletContextEvent arg0) { + } + + @Override + public void contextDestroyed(ServletContextEvent arg0) { + listenerBalance.decrementAndGet(); + } + }; + + HttpSessionListener sl = new HttpSessionListener() { + + @Override + public void sessionDestroyed(HttpSessionEvent se) { + listenerBalance.incrementAndGet(); + } + + @Override + public void sessionCreated(HttpSessionEvent se) { + } + }; + + Servlet sA = new HttpServlet() { + private static final long serialVersionUID = 1L; + + @Override + protected void doGet( + HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + + HttpSession session = req.getSession(); + sessionReference.set(session); + + session.setAttribute("testAttribute", "testValue"); + PrintWriter writer = resp.getWriter(); + writer.write("S11 requested"); + } + }; + + Collection<ServiceRegistration<?>> registrations = new ArrayList<ServiceRegistration<?>>(); + try { + Dictionary<String, String> scListenerProps = new Hashtable<String, String>(); + scListenerProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER, "true"); + registrations.add(getBundleContext().registerService(ServletContextListener.class, scl, scListenerProps)); + + Dictionary<String, String> sListenerProps = new Hashtable<String, String>(); + sListenerProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER, "true"); + registrations.add(getBundleContext().registerService(HttpSessionListener.class, sl, sListenerProps)); + + Dictionary<String, String> servletProps1 = new Hashtable<String, String>(); + servletProps1.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, "S11"); + servletProps1.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/s11"); + registrations.add(getBundleContext().registerService(Servlet.class, sA, servletProps1)); + + String result = requestAdvisor.request("s11"); + Assert.assertEquals("S11 requested", result); + } + finally { + for (ServiceRegistration<?> registration : registrations) { + registration.unregister(); + } + } + + //Emulate session expiration to check sessionListener + //is only called once (when unregister) + HttpSession session = sessionReference.get(); + + session.invalidate(); + + Assert.assertEquals(0, listenerBalance.get()); + } + public void test_Async1() throws Exception { Servlet s1 = new BaseAsyncServlet("test_Listener8"); diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/ContextController.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/ContextController.java index a2d4a7227..019c6a3fb 100644 --- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/ContextController.java +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/ContextController.java @@ -15,9 +15,7 @@ import java.net.URI; import java.net.URISyntaxException; import java.security.AccessController; import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ConcurrentSkipListSet; +import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Pattern; import javax.servlet.*; @@ -786,6 +784,12 @@ public class ContextController { } } + public Map<String, HttpSessionAdaptor> getActiveSessions() { + checkShutdown(); + + return activeSessions; + } + public Set<EndpointRegistration<?>> getEndpointRegistrations() { checkShutdown(); diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/ListenerRegistration.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/ListenerRegistration.java index ccbaf4d84..99c9e6625 100644 --- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/ListenerRegistration.java +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/ListenerRegistration.java @@ -12,11 +12,12 @@ package org.eclipse.equinox.http.servlet.internal.registration; import java.lang.reflect.*; -import java.util.EventListener; -import java.util.List; +import java.util.*; import javax.servlet.*; +import javax.servlet.http.*; import org.eclipse.equinox.http.servlet.internal.context.ContextController; import org.eclipse.equinox.http.servlet.internal.context.ContextController.ServiceHolder; +import org.eclipse.equinox.http.servlet.internal.servlet.HttpSessionAdaptor; import org.osgi.framework.wiring.BundleWiring; import org.osgi.service.http.runtime.dto.ListenerDTO; @@ -65,6 +66,18 @@ public class ListenerRegistration extends Registration<EventListener, ListenerDT super.destroy(); + if (classes.contains(HttpSessionBindingListener.class) || + classes.contains(HttpSessionAttributeListener.class) || + classes.contains(HttpSessionListener.class)) { + + Map<String, HttpSessionAdaptor> activeSessions = + contextController.getActiveSessions(); + + for (HttpSessionAdaptor adaptor : activeSessions.values()) { + adaptor.invokeSessionListeners(classes, super.getT()); + } + } + if (classes.contains(ServletContextListener.class)) { ServletContextListener servletContextListener = (ServletContextListener)super.getT(); @@ -88,7 +101,7 @@ public class ListenerRegistration extends Registration<EventListener, ListenerDT ListenerRegistration listenerRegistration = (ListenerRegistration)obj; - return super.getT().equals(listenerRegistration.getT()); + return listenerRegistration.getT().equals(super.getT()); } @Override diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpSessionAdaptor.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpSessionAdaptor.java index 6e6b27c1c..c53578bfc 100644 --- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpSessionAdaptor.java +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpSessionAdaptor.java @@ -274,6 +274,38 @@ public class HttpSessionAdaptor implements HttpSession, Serializable { controller.removeActiveSession(session); } + public void invokeSessionListeners (List<Class<? extends EventListener>> classes, EventListener listener) { + if (classes == null) { + return; + } + + for (Class<? extends EventListener> clazz : classes) { + if (clazz.equals(HttpSessionListener.class)){ + HttpSessionEvent sessionEvent = new HttpSessionEvent(this); + HttpSessionListener httpSessionListener = (HttpSessionListener) listener; + httpSessionListener.sessionDestroyed(sessionEvent); + } + + if (clazz.equals(HttpSessionBindingListener.class) || clazz.equals(HttpSessionAttributeListener.class)) { + Enumeration<String> attributeNames = getAttributeNames(); + while (attributeNames.hasMoreElements()) { + String attributeName = attributeNames.nextElement(); + HttpSessionBindingEvent sessionBindingEvent = new HttpSessionBindingEvent(this, attributeName); + + if (clazz.equals(HttpSessionBindingListener.class)) { + HttpSessionBindingListener httpSessionBindingListener = (HttpSessionBindingListener) listener; + httpSessionBindingListener.valueUnbound(sessionBindingEvent); + } + + if (clazz.equals(HttpSessionAttributeListener.class)) { + HttpSessionAttributeListener httpSessionAttributeListener = (HttpSessionAttributeListener) listener; + httpSessionAttributeListener.attributeRemoved(sessionBindingEvent); + } + } + } + } + } + /**@deprecated*/ public void putValue(String arg0, Object arg1) { setAttribute(arg0, arg1); |