/* * Created on Jul 20, 2005 */ package cyrille.servlet; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.Properties; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * <p> * Chain of {@link ServletContextListener} defined in a configuration file * </p> * <p> * Configuration : relies on web.xml < listener > init param * {@link #CONFIGURATION_FILE_PARAMETER_NAME} (<code>configuration-file</code>) * </p> * <p> * Logging policy : we mostly log at debug level. Each {@link ServletContextListener} of the chain * is expected to log at info level if necessary * </p> * * @author <a href="mailto:cleclerc@pobox.com">Cyrille Le Clerc</a> */ public class ServletContextListenerChain implements ServletContextListener { private static final String CONFIGURATION_FILE_PARAMETER_NAME = "ServletContextListenerChainConfigurationFile"; private static final Log log = LogFactory.getLog(ServletContextListenerChain.class); /** * Chain of {@link ServletContextListener} to invoked */ private ServletContextListener[] servletContextListeners; /** * <p> * Invoke {@link ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent)} on * each element of the chain * </p> * <p> * If an exception occurs invoking a {@link ServletContextListener}, the message is logged and * next element of the chain is processed * </p> * * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent) */ public void contextDestroyed(ServletContextEvent servletContextEvent) { for (int i = 0; i < this.servletContextListeners.length; i++) { ServletContextListener servletContextListener = this.servletContextListeners[i]; try { servletContextListener.contextDestroyed(servletContextEvent); log.debug("ServletContextListener 'servletContextListener." + i + "'='" + servletContextListener + " unloaded"); } catch (Throwable t) { log.error("Exception invoking contextDestroyed on 'servletContextListener." + i + "'='" + servletContextListener + "': " + t.toString(), t); } } } /** * <p> * Load each {@link ServletContextListener} of the chain and invoke * {@link ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent)} on each * one * </p> * <p> * If an exception occurs loading or invoking a {@link ServletContextListener}, the message is * logged and next element of the chain is processed * </p> * * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent) */ public void contextInitialized(ServletContextEvent servletContextEvent) { String configurationFile = servletContextEvent.getServletContext().getInitParameter(CONFIGURATION_FILE_PARAMETER_NAME); if (configurationFile == null) { log.error("Missing <context-param> '" + CONFIGURATION_FILE_PARAMETER_NAME + "' in web.xml"); log.error("Abort ServletContextListenerChain initialization"); return; } InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(configurationFile); if (in == null) { log.error("ServletContextListenerChain configuration file described in '" + configurationFile + "' not found"); log.error("Abort ServletContextListenerChain initialization"); return; } log.debug("Load ServletContextListeners from configuration file '" + configurationFile + "'"); Properties properties = new Properties(); try { properties.load(in); } catch (Exception e) { log.error("Exception loading ServletContextListenerChain configuration file '" + configurationFile + "' : " + e.toString(), e); log.error("Abort ServletContextListenerChain initialization"); return; } List servletContextListenersList = new ArrayList(); int i = 0; String servletContextListenerClassName; while ((servletContextListenerClassName = properties.getProperty(configurationFile, "servletContextListener." + i)) != null) { try { Class servletContextListenerClass = Class.forName(servletContextListenerClassName, true, Thread.currentThread() .getContextClassLoader()); ServletContextListener servletContextListener = (ServletContextListener) servletContextListenerClass.newInstance(); log.debug("ServletContextListener 'servletContextListener." + i + "'='" + servletContextListener + " loaded"); servletContextListenersList.add(servletContextListener); } catch (Throwable t) { log.error( "Exception loading 'servletContextListener." + i + "'='" + servletContextListenerClassName + "': " + t.toString(), t); log.error("WARNING 'servletContextListener." + i + "'='" + servletContextListenerClassName + "' will NOT be loaded"); } i++; } this.servletContextListeners = (ServletContextListener[]) servletContextListenersList.toArray(new ServletContextListener[0]); for (i = 0; i < this.servletContextListeners.length; i++) { ServletContextListener servletContextListener = this.servletContextListeners[i]; try { servletContextListener.contextInitialized(servletContextEvent); } catch (Throwable t) { log.error("Exception invoking contextInitialized on 'servletContextListener." + i + "'='" + servletContextListener + "': " + t.toString(), t); } } } @Override public String toString() { return new ToStringBuilder(this).append("servletContextListeners", this.servletContextListeners).toString(); } }