Index: core/src/com/icesoft/faces/util/event/servlet/ContextEventRepeater.java =================================================================== --- core/src/com/icesoft/faces/util/event/servlet/ContextEventRepeater.java (revision 16734) +++ core/src/com/icesoft/faces/util/event/servlet/ContextEventRepeater.java Wed May 28 17:28:10 CST 2008 @@ -90,9 +90,9 @@ * */ public class ContextEventRepeater -implements HttpSessionListener, ServletContextListener { + implements HttpSessionListener, ServletContextListener { private static final String MESSAGING_CONTEXT_EVENT_PUBLISHER_CLASS_NAME = - "com.icesoft.faces.util.event.servlet.MessagingContextEventPublisher"; + "com.icesoft.faces.util.event.servlet.MessagingContextEventPublisher"; private static final Log LOG = LogFactory.getLog(ContextEventRepeater.class); @@ -115,10 +115,10 @@ * @param contextEventListener the listener to be added. */ public synchronized static void addListener( - final ContextEventListener contextEventListener) { + final ContextEventListener contextEventListener) { if (contextEventListener == null || - listeners.containsKey(contextEventListener)) { + listeners.containsKey(contextEventListener)) { return; } @@ -139,11 +139,11 @@ SessionDispatcherListener.contextDestroyed(event); ContextDestroyedEvent contextDestroyedEvent = - new ContextDestroyedEvent(event); + new ContextDestroyedEvent(event); Iterator it = listeners.keySet().iterator(); while (it.hasNext()) { ((ContextEventListener) it.next()). - contextDestroyed(contextDestroyedEvent); + contextDestroyed(contextDestroyedEvent); } listeners.clear(); bufferedContextEvents.clear(); @@ -158,48 +158,48 @@ } if (LOG.isInfoEnabled()) { ServletContext servletContext = - contextDestroyedEvent.getServletContext(); + contextDestroyedEvent.getServletContext(); LOG.info( - "Servlet Context Name: " + - servletContext.getServletContextName() + ", " + - "Server Info: " + servletContext.getServerInfo()); + "Servlet Context Name: " + + servletContext.getServletContextName() + ", " + + "Server Info: " + servletContext.getServerInfo()); } } public synchronized void contextInitialized( - final ServletContextEvent event) { + final ServletContextEvent event) { SessionDispatcherListener.contextInitialized(event); Configuration _configuration = - new ServletContextConfiguration( - "com.icesoft.faces", event.getServletContext()); + new ServletContextConfiguration( + "com.icesoft.faces", event.getServletContext()); // checking if Asynchronous HTTP Service is available... boolean isAsyncHttpServiceAvailable = isAsyncHttpServiceAvailable(); if (LOG.isInfoEnabled()) { LOG.info( - "Asynchronous HTTP Service available: " + - isAsyncHttpServiceAvailable); + "Asynchronous HTTP Service available: " + + isAsyncHttpServiceAvailable); } if (isAsyncHttpServiceAvailable && - _configuration.getAttribute( - "blockingRequestHandler", - _configuration.getAttributeAsBoolean( - "async.server", true) ? - "icefaces-ahs" : - "icefaces"). - equalsIgnoreCase("icefaces-ahs")) { + _configuration.getAttribute( + "blockingRequestHandler", + _configuration.getAttributeAsBoolean( + "async.server", true) ? + "icefaces-ahs" : + "icefaces"). + equalsIgnoreCase("icefaces-ahs")) { try { contextEventPublisher = - (ContextEventPublisher) - Class.forName( - MESSAGING_CONTEXT_EVENT_PUBLISHER_CLASS_NAME). - newInstance(); + (ContextEventPublisher) + Class.forName( + MESSAGING_CONTEXT_EVENT_PUBLISHER_CLASS_NAME). + newInstance(); contextEventPublisher.setContextEventRepeater(this); try { contextEventPublisher.publish( - new ContextInitializedEvent(event)); + new ContextInitializedEvent(event)); } catch (Exception exception) { contextEventPublisher = null; if (LOG.isDebugEnabled()) { @@ -213,31 +213,31 @@ } catch (IllegalAccessException exception) { if (LOG.isFatalEnabled()) { LOG.fatal( - "Failed to access constructor of " + - "MessagingContextEventPublisher!", - exception); + "Failed to access constructor of " + + "MessagingContextEventPublisher!", + exception); } } catch (InstantiationException exception) { if (LOG.isFatalEnabled()) { LOG.fatal( - "Failed to " + - "instantiate MessagingContextEventPublisher!", - exception); + "Failed to " + + "instantiate MessagingContextEventPublisher!", + exception); } } } } public synchronized static void iceFacesIdDisposed( - final HttpSession source, final String iceFacesId) { + final HttpSession source, final String iceFacesId) { ICEfacesIDDisposedEvent iceFacesIdDisposedEvent = - new ICEfacesIDDisposedEvent(source, iceFacesId); + new ICEfacesIDDisposedEvent(source, iceFacesId); bufferedContextEvents.put(iceFacesIdDisposedEvent, source); Iterator _listeners = listeners.keySet().iterator(); while (_listeners.hasNext()) { ((ContextEventListener) _listeners.next()). - iceFacesIdDisposed(iceFacesIdDisposedEvent); + iceFacesIdDisposed(iceFacesIdDisposedEvent); } if (contextEventPublisher != null) { try { @@ -250,8 +250,8 @@ } if (LOG.isTraceEnabled()) { LOG.trace( - "ICEfaces ID disposed: " + - iceFacesIdDisposedEvent.getICEfacesID()); + "ICEfaces ID disposed: " + + iceFacesIdDisposedEvent.getICEfacesID()); } } @@ -264,15 +264,15 @@ * @param iceFacesId the ICEfaces ID. */ public synchronized static void iceFacesIdRetrieved( - final HttpSession source, final String iceFacesId) { + final HttpSession source, final String iceFacesId) { ICEfacesIDRetrievedEvent iceFacesIdRetrievedEvent = - new ICEfacesIDRetrievedEvent(source, iceFacesId); + new ICEfacesIDRetrievedEvent(source, iceFacesId); bufferedContextEvents.put(iceFacesIdRetrievedEvent, source); Iterator _listeners = listeners.keySet().iterator(); while (_listeners.hasNext()) { ((ContextEventListener) _listeners.next()). - iceFacesIdRetrieved(iceFacesIdRetrievedEvent); + iceFacesIdRetrieved(iceFacesIdRetrievedEvent); } if (contextEventPublisher != null) { try { @@ -285,8 +285,8 @@ } if (LOG.isTraceEnabled()) { LOG.trace( - "ICEfaces ID retrieved: " + - iceFacesIdRetrievedEvent.getICEfacesID()); + "ICEfaces ID retrieved: " + + iceFacesIdRetrievedEvent.getICEfacesID()); } } @@ -315,12 +315,13 @@ * @param event the HTTP session event. */ public synchronized void sessionDestroyed(final HttpSessionEvent event) { + SessionDispatcherListener.sessionDestroyed(event); SessionDestroyedEvent sessionDestroyedEvent = - new SessionDestroyedEvent(event); + new SessionDestroyedEvent(event); Iterator _listeners = listeners.keySet().iterator(); while (_listeners.hasNext()) { ((ContextEventListener) _listeners.next()). - sessionDestroyed(sessionDestroyedEvent); + sessionDestroyed(sessionDestroyedEvent); } removeBufferedEvents(event.getSession()); if (contextEventPublisher != null) { @@ -346,16 +347,16 @@ * @param viewNumber the view number. */ public synchronized static void viewNumberRetrieved( - final HttpSession source, final String icefacesID, - final int viewNumber) { + final HttpSession source, final String icefacesID, + final int viewNumber) { ViewNumberRetrievedEvent viewNumberRetrievedEvent = - new ViewNumberRetrievedEvent(source, icefacesID, viewNumber); + new ViewNumberRetrievedEvent(source, icefacesID, viewNumber); bufferedContextEvents.put(viewNumberRetrievedEvent, source); Iterator _listeners = listeners.keySet().iterator(); while (_listeners.hasNext()) { ((ContextEventListener) _listeners.next()). - viewNumberRetrieved(viewNumberRetrievedEvent); + viewNumberRetrieved(viewNumberRetrievedEvent); } if (contextEventPublisher != null) { try { @@ -368,23 +369,23 @@ } if (LOG.isTraceEnabled()) { LOG.trace( - "View Number: " + viewNumberRetrievedEvent.getViewNumber()); + "View Number: " + viewNumberRetrievedEvent.getViewNumber()); } } ContextEvent[] getBufferedContextEvents() { Set _contextEventSet = bufferedContextEvents.keySet(); return - (ContextEvent[]) - _contextEventSet.toArray( - new ContextEvent[_contextEventSet.size()]); + (ContextEvent[]) + _contextEventSet.toArray( + new ContextEvent[_contextEventSet.size()]); } private boolean isAsyncHttpServiceAvailable() { try { this.getClass().getClassLoader().loadClass( - "com.icesoft.faces.async.server." + - "AsyncHttpServerAdaptingServlet"); + "com.icesoft.faces.async.server." + + "AsyncHttpServerAdaptingServlet"); return true; } catch (ClassNotFoundException exception) { return false; @@ -392,7 +393,7 @@ } private synchronized static void removeBufferedEvents( - final HttpSession session) { + final HttpSession session) { Iterator it = bufferedContextEvents.keySet().iterator(); Object event = null; @@ -408,17 +409,17 @@ } private synchronized static void sendBufferedEvents( - final ContextEventListener contextEventListener) { + final ContextEventListener contextEventListener) { Iterator it = bufferedContextEvents.keySet().iterator(); while (it.hasNext()) { Object event = it.next(); if (event instanceof ICEfacesIDRetrievedEvent) { contextEventListener.iceFacesIdRetrieved( - (ICEfacesIDRetrievedEvent) event); + (ICEfacesIDRetrievedEvent) event); } else if (event instanceof ViewNumberRetrievedEvent) { contextEventListener.viewNumberRetrieved( - (ViewNumberRetrievedEvent) event); + (ViewNumberRetrievedEvent) event); } } } Index: core/src/com/icesoft/faces/webapp/http/servlet/SessionDispatcher.java =================================================================== --- core/src/com/icesoft/faces/webapp/http/servlet/SessionDispatcher.java (revision 16734) +++ core/src/com/icesoft/faces/webapp/http/servlet/SessionDispatcher.java Wed May 28 17:28:10 CST 2008 @@ -9,6 +9,8 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpSessionEvent; +import javax.servlet.http.HttpSessionListener; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; @@ -20,8 +22,7 @@ //having a static field here is ok because web applications are started in separate classloaders private final static Log Log = LogFactory.getLog(SessionDispatcher.class); private final static List SessionDispatchers = new ArrayList(); - private final static List SessionMonitors = new ArrayList(); - private final static List SessionIDs = new ArrayList(); + private final static Map SessionMonitors = new HashMap(); private Map sessionBoundServers = new HashMap(); private PseudoServlet invalidRequestServlet; @@ -56,8 +57,8 @@ //synchronize access in case there are multiple SessionDispatcher instances created private static void notifyIfNew(HttpSession session) { - synchronized (SessionIDs) { - if (!SessionIDs.contains(session.getId())) { + synchronized (SessionMonitors) { + if (!SessionMonitors.containsKey(session.getId())) { notifySessionInitialized(session); } } @@ -100,8 +101,8 @@ * Create new session bound servers. */ private static void notifySessionInitialized(HttpSession session) { - SessionIDs.add(session.getId()); Monitor monitor = new Monitor(session); + SessionMonitors.put(session.getId(), monitor); Iterator i = SessionDispatchers.iterator(); while (i.hasNext()) { @@ -115,19 +116,23 @@ } private static void notifySessionShutdown(final HttpSession session) { + synchronized (SessionMonitors) { + String sessionID = session.getId(); + //avoid executing this method twice + if (!SessionMonitors.containsKey(sessionID)) { + return; + } - //shutdown session bound servers - Iterator i = SessionDispatchers.iterator(); - while (i.hasNext()) { - try { - SessionDispatcher sessionDispatcher = (SessionDispatcher) i.next(); - sessionDispatcher.sessionShutdown(session); - } catch (Exception e) { - Log.error(e); - } - } + //shutdown session bound servers + Iterator i = SessionDispatchers.iterator(); + while (i.hasNext()) { + try { + SessionDispatcher sessionDispatcher = (SessionDispatcher) i.next(); + sessionDispatcher.sessionShutdown(session); + } catch (Exception e) { + Log.error(e); + } + } - //invalidate session and discard session ID - synchronized (SessionIDs) { i = SessionDispatchers.iterator(); while (i.hasNext()) { try { @@ -138,13 +143,12 @@ } } - String sessionID = session.getId(); try { session.invalidate(); } catch (IllegalStateException e) { Log.info("Session already invalidated."); } finally { - SessionIDs.remove(sessionID); + SessionMonitors.remove(sessionID); } } } @@ -154,7 +158,7 @@ return ((SessionDispatcher) SessionDispatchers.get(0)).lookupServlet(session); } - public static class Listener implements ServletContextListener { + public static class Listener implements ServletContextListener, HttpSessionListener { private boolean run = true; public void contextInitialized(ServletContextEvent servletContextEvent) { @@ -162,8 +166,8 @@ public void run() { while (run) { try { - //iterate over the sessions using a copying iterator - Iterator iterator = new ArrayList(SessionMonitors).iterator(); + //iterate over the session monitors using a copying iterator + Iterator iterator = new ArrayList(SessionMonitors.values()).iterator(); while (iterator.hasNext()) { final Monitor sessionMonitor = (Monitor) iterator.next(); sessionMonitor.shutdownIfExpired(); @@ -183,9 +187,16 @@ public void contextDestroyed(ServletContextEvent servletContextEvent) { run = false; } + + public void sessionCreated(HttpSessionEvent event) { - } + } + public void sessionDestroyed(HttpSessionEvent event) { + notifySessionShutdown(event.getSession()); + } + } + public static class Monitor { private HttpSession session; private long lastAccess; @@ -193,7 +204,6 @@ private Monitor(HttpSession session) { this.session = session; this.lastAccess = session.getLastAccessedTime(); - SessionMonitors.add(this); } public void touchSession() { @@ -212,7 +222,6 @@ } public void shutdown() { - SessionMonitors.remove(this); notifySessionShutdown(session); }