/** * Copyright (C) 2009 eXo Platform SAS. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.exoplatform.web; import java.util.EventObject; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.http.HttpSessionEvent; import org.exoplatform.commons.utils.PropertyManager; import org.exoplatform.container.ExoContainer; import org.exoplatform.container.ExoContainerContext; import org.exoplatform.container.PortalContainer; import org.exoplatform.container.RootContainer; import org.exoplatform.container.RootContainer.PortalContainerPostInitTask; import org.exoplatform.container.web.AbstractHttpSessionListener; import org.exoplatform.services.listener.ListenerService; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; /** * This class is used to broadcast any "HttpEvent" to allow the rest of the platform to be notified without changing the web.xml * file. * * Created by The eXo Platform SAS Author : Nicolas Filotto nicolas.filotto@exoplatform.com 25 sept. 2009 */ public class GenericHttpListener extends AbstractHttpSessionListener implements ServletContextListener { /** * The name of the "session created" event */ public static final String SESSION_CREATED = "org.exoplatform.web.GenericHttpListener.sessionCreated"; /** * The name of the "session destroyed" event */ public static final String SESSION_DESTROYED = "org.exoplatform.web.GenericHttpListener.sessionDestroyed"; /** * The name of the "context initialized" event */ public static final String CONTEXT_INITIALIZED = "org.exoplatform.web.GenericHttpListener.contextInitialized"; /** * The name of the "context destroyed" event */ public static final String CONTEXT_DESTROYED = "org.exoplatform.web.GenericHttpListener.contextDestroyed"; /** * Logger. */ private static Log log = ExoLogger.getLogger("portal:GenericHttpListener"); /** * This method is called when a HTTP session of a Portal instance is created. * * In this method, we: 1) first get the portal instance name for which the session is created. 2) Put the portal instance in * the Portal ThreadLocal 3) Broadcast the SESSION_CREATED event 4) Flush the {@link ThreadLocal} for the PortalContainer */ @Override protected void onSessionCreated(ExoContainer container, HttpSessionEvent event) { try { broadcast((PortalContainer) container, SESSION_CREATED, event); } catch (Exception ex) { log.error("Error on sessionCreated", ex); } } /** * This method is called when a HTTP session of a Portal instance is destroyed. * * In this method, we: 1) first get the portal instance name for which the session is created. 2) Put the portal instance in * the Portal ThreadLocal 3) Broadcast the SESSION_DESTROYED event 4) Flush the {@link ThreadLocal} for the PortalContainer */ @Override protected void onSessionDestroyed(ExoContainer container, HttpSessionEvent event) { try { broadcast((PortalContainer) container, SESSION_DESTROYED, event); } catch (Exception ex) { log.error("Error on sessionDestroyed", ex); } } /** * This method is called when the {@link ServletContext} of the Portal is destroyed. * * In this method, we: 1) first get the portal instance name for which the session is created. 2) Put the portal instance in * the Portal ThreadLocal 3) Broadcast the CONTEXT_DESTROYED event 4) Flush the {@link ThreadLocal} for the PortalContainer */ public void contextDestroyed(ServletContextEvent event) { boolean hasBeenSet = false; final ExoContainer oldContainer = ExoContainerContext.getCurrentContainer(); try { PortalContainer portalContainer = PortalContainer.getInstanceIfPresent(); if (portalContainer == null) { portalContainer = PortalContainer.getCurrentInstance(event.getServletContext()); PortalContainer.setInstance(portalContainer); hasBeenSet = true; } final String ctxName = event.getServletContext().getServletContextName(); if (!PortalContainer.isPortalContainerNameDisabled(ctxName) && portalContainer instanceof PortalContainer) { // The portal container corresponding to the current servlet context could be found broadcast(portalContainer, CONTEXT_DESTROYED, event); } else if (PropertyManager.isDevelopping()) { log.info("The portal environment could not be set for the webapp '" + ctxName + "' because this servlet context has not been defined as a " + "dependency of any portal container or it is a disabled portal" + " container, the contextDestroyed event will be ignored"); } } catch (Exception ex) { log.error("Error on contextDestroyed", ex); } finally { if (hasBeenSet) { PortalContainer.setInstance(null); ExoContainerContext.setCurrentContainer(oldContainer); } } } /** * This method is called when the {@link ServletContext} of the Portal is initialized. * * In this method, we: 1) first get the portal instance name for which the session is created. 2) Put the portal instance in * the Portal ThreadLocal 3) Broadcast the CONTEXT_INITIALIZED event 4) Flush the {@link ThreadLocal} for the * PortalContainer */ public void contextInitialized(final ServletContextEvent event) { final PortalContainerPostInitTask task = new PortalContainerPostInitTask() { public void execute(ServletContext scontext, PortalContainer portalContainer) { try { broadcast(portalContainer, CONTEXT_INITIALIZED, event); } catch (Exception ex) { log.error("Error on contextInitialized", ex); } } }; ServletContext ctx = event.getServletContext(); RootContainer.getInstance().addInitTask(event.getServletContext(), task); } /** * @see org.exoplatform.container.web.AbstractHttpSessionListener#requirePortalEnvironment() */ @Override protected boolean requirePortalEnvironment() { return true; } /** * Allow the rest of the application to be notified when an HttpEvent happens * * @param portalContainer the related portal container * @param eventName the name of the event to broadcast * @param event the notification event */ private <T extends EventObject> void broadcast(PortalContainer portalContainer, String eventName, T event) { try { ListenerService listenerService = (ListenerService) portalContainer .getComponentInstanceOfType(ListenerService.class); listenerService.broadcast(eventName, portalContainer, event); } catch (Exception e) { log.warn("Cannot broadcast the event '" + eventName + "'", e); } } }