/* * Copyright 2002-2004 the original author or authors. * * Licensed 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.springframework.web.servlet.support; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.servlet.ServletContext; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; import org.springframework.core.OrderComparator; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; /** * Provides support for propagating session events to an * <code>WebApplicationContext</code>. Calls to <code>sessionCreated()</code> * and <code>sessionDestroyed()</code> are subsequently routed to all beans * implementing the <code>HttpSessionListener</code> interface registering in * the application context, after they're sorted using the * <code>OrderComparator</code> * <p> * * Note: error handling is not sorted out yet in this class. The Servlet 2.4 * specification is unclear about what happens to multiple listeners registered * in a web application where one of the listeners throws an unchecked exception * (see the Servlet specification section SRV.10.6). Currently, if an unchecked * exception is thrown by one of the listeners registered in the application * context (retrieved through the <code>ServletContext</code> available from * the <code>HttpSession</code> in the <code>HttpSessionEvent</code>), it * won't be caught by this class hence the other listener registered in the * context won't be notified. This might need to change later on. * <p> * * Motivation: to allow for easy registration of session listeners in an * application context thus letting them profit from the Spring DI features. * <p> * * The <code>WebApplicationContextSessionListener</code> should be wired up as * any other listener in the <code>web.xml</code> file: * <p> * * <pre> * * <listener> * <listener-class>org.springframework.web.servlet.support.WebApplicationContextSessionListener<listener-class> * </listener> * * </pre> * * Note that a WebApplicationContext <i>is </i> required by this listener. The * context is retrieved by calling * {@link WebApplicationContextUtils#getRequiredWebApplicationContext(ServletContext)}, * causing an unchecked exception to be thrown if no context could be found. * <p> * * <b>WARNING UNTESTED!!!</b> * * @see javax.servlet.http.HttpSessionListener * @see org.springframework.core.Ordered * * @author Alef Arendsen */ public final class WebApplicationContextSessionListener implements HttpSessionListener { /** the application context to inspect */ private WebApplicationContext webApplicationContext = null; /** * Inspects the WebApplicationContext for beans implementing the * <code>HttpSessionListener</code> interface, sorts them and propagates * all calls to the listeners. */ public void sessionCreated(HttpSessionEvent evt) { List l = retrieveAllListeners(evt); Iterator it = l.iterator(); while (it.hasNext()) { HttpSessionListener listener = (HttpSessionListener) it.next(); listener.sessionCreated(evt); } } /** * Inspects the WebApplicationContext for beans implementing the * <code>HttpSessionListener</code> interface, sorts them and propagates * all calls to the listeners. */ public void sessionDestroyed(HttpSessionEvent evt) { List l = retrieveAllListeners(evt); Iterator it = l.iterator(); while (it.hasNext()) { HttpSessionListener listener = (HttpSessionListener) it.next(); listener.sessionDestroyed(evt); } } private List retrieveAllListeners(HttpSessionEvent evt) { if (this.webApplicationContext == null) { this.webApplicationContext = retrieveWebApplicationContext(evt); } // retrieve all session listeners and sort Map m = webApplicationContext.getBeansOfType(HttpSessionListener.class, true, true); List l = new ArrayList(m.values()); Collections.sort(l, new OrderComparator()); return l; } private WebApplicationContext retrieveWebApplicationContext( HttpSessionEvent evt) { HttpSession session = evt.getSession(); ServletContext sContext = session.getServletContext(); // requires a web application context, otherwise there's no sense in // registering the listener anyway return WebApplicationContextUtils .getRequiredWebApplicationContext(sContext); } }