| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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.apache.cocoon.servlet; |
| |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.StringTokenizer; |
| |
| import javax.servlet.ServletContext; |
| import javax.servlet.ServletContextAttributeEvent; |
| import javax.servlet.ServletContextAttributeListener; |
| import javax.servlet.ServletContextEvent; |
| import javax.servlet.ServletContextListener; |
| import javax.servlet.http.HttpSessionActivationListener; |
| import javax.servlet.http.HttpSessionAttributeListener; |
| import javax.servlet.http.HttpSessionBindingEvent; |
| import javax.servlet.http.HttpSessionBindingListener; |
| import javax.servlet.http.HttpSessionEvent; |
| import javax.servlet.http.HttpSessionListener; |
| |
| /** |
| * This listener can be used as a wrapper around "real" listeners to |
| * support the reloading class loader. |
| * |
| * @version $Id$ |
| */ |
| public class ReloadingListener |
| implements HttpSessionListener, |
| ServletContextListener, |
| HttpSessionActivationListener, |
| HttpSessionAttributeListener, |
| HttpSessionBindingListener, |
| ServletContextAttributeListener { |
| |
| private static final String SERVLET_CONTEXT_CREATED = "CLC"; |
| |
| private static final String SERVLET_CONTEXT_DESTROYED = "CLD"; |
| |
| private static final String SESSION_CREATED = "SEC"; |
| |
| private static final String SESSION_DESTROYED = "SED"; |
| |
| private static final String SESSION_ACTIVATED = "SEAC"; |
| |
| private static final String SESSION_PASSIVATE = "SEDE"; |
| |
| private static final String VALUE_BOUND = "VB"; |
| |
| private static final String VALUE_UNBOUND = "VUB"; |
| |
| private static final String ATTR_REPLACED = "ARE"; |
| |
| private static final String ATTR_REMOVED = "ADE"; |
| |
| private static final String ATTR_ADDED = "AAD"; |
| |
| private static final String CONTEXT_ATTR_REPLACED = "CARE"; |
| |
| private static final String CONTEXT_ATTR_REMOVED = "CADE"; |
| |
| private static final String CONTEXT_ATTR_ADDED = "CAAD"; |
| |
| protected List httpSessionListeners = new ArrayList(); |
| |
| protected List servletContextListeners = new ArrayList(); |
| |
| protected List httpSessionActivationListeners = new ArrayList(); |
| |
| protected List httpSessionBindingListeners = new ArrayList(); |
| |
| protected List servletContextAttributeListeners = new ArrayList(); |
| |
| protected List httpSessionAttributeListeners = new ArrayList(); |
| |
| protected ServletContext context; |
| |
| protected void init(ServletContext context) { |
| this.context = context; |
| // Create the listeners |
| final ClassLoader old = Thread.currentThread().getContextClassLoader(); |
| try { |
| Thread.currentThread().setContextClassLoader(ReloadingClassloaderManager.getClassLoader(this.context)); |
| final String listenersConfig = context.getInitParameter(ReloadingListener.class.getName()); |
| if ( listenersConfig != null ) { |
| final StringTokenizer st = new StringTokenizer(listenersConfig, " \t\r\n\f;,", false); |
| while ( st.hasMoreTokens() ) { |
| final String className = st.nextToken(); |
| try { |
| ClassLoader cl = ReloadingClassloaderManager.getClassLoader(this.context); |
| Class listenerClass = cl.loadClass(className); |
| final Object listener = listenerClass.newInstance(); |
| ClassLoader listenerClassloader = listener.getClass().getClassLoader(); |
| System.out.println("ReloadingListener: ReloadingClassloaderManager.getClassLoader().getClass()=" + className + "; cl=" + ReloadingClassloaderManager.getClassLoader(this.context).getClass().getName()); |
| System.out.println("ReloadingListener: listener.getClass().getClassloader()=" + listenerClassloader); |
| if ( listener instanceof HttpSessionListener ) { |
| this.httpSessionListeners.add(listener); |
| } |
| if ( listener instanceof ServletContextListener ) { |
| this.servletContextListeners.add(listener); |
| } |
| if ( listener instanceof HttpSessionActivationListener ) { |
| this.httpSessionActivationListeners.add(listener); |
| } |
| if ( listener instanceof HttpSessionAttributeListener ) { |
| this.httpSessionAttributeListeners.add(listener); |
| } |
| if ( listener instanceof HttpSessionBindingListener ) { |
| this.httpSessionBindingListeners.add(listener); |
| } |
| if ( listener instanceof ServletContextAttributeListener ) { |
| this.servletContextAttributeListeners.add(listener); |
| } |
| } catch (Exception e) { |
| throw new RuntimeException("Cannot load listener " + className, e); |
| } |
| } |
| } |
| } finally { |
| Thread.currentThread().setContextClassLoader(old); |
| } |
| } |
| |
| protected void invoke(List listeners, String identifier, Object event) { |
| if ( ReloadingClassloaderManager.getClassLoader(this.context) != null ) { |
| final ClassLoader old = Thread.currentThread().getContextClassLoader(); |
| try { |
| Thread.currentThread().setContextClassLoader(ReloadingClassloaderManager.getClassLoader(this.context)); |
| final Iterator i = listeners.iterator(); |
| while ( i.hasNext() ) { |
| final Object listener = i.next(); |
| try { |
| if ( ReloadingListener.SERVLET_CONTEXT_CREATED.equals(identifier) ) { |
| ((ServletContextListener)listener).contextInitialized((ServletContextEvent)event); |
| } else if ( ReloadingListener.SERVLET_CONTEXT_DESTROYED.equals(identifier) ) { |
| ((ServletContextListener)listener).contextDestroyed((ServletContextEvent)event); |
| } else if ( ReloadingListener.SESSION_CREATED.equals(identifier) ) { |
| ((HttpSessionListener)listener).sessionCreated((HttpSessionEvent)event); |
| } else if ( ReloadingListener.SESSION_DESTROYED.equals(identifier) ) { |
| ((HttpSessionListener)listener).sessionDestroyed((HttpSessionEvent)event); |
| } else if ( ReloadingListener.VALUE_BOUND.equals(identifier) ) { |
| ((HttpSessionBindingListener)listener).valueBound((HttpSessionBindingEvent)event); |
| } else if ( ReloadingListener.VALUE_UNBOUND.equals(identifier) ) { |
| ((HttpSessionBindingListener)listener).valueUnbound((HttpSessionBindingEvent)event); |
| } else if ( ReloadingListener.ATTR_ADDED.equals(identifier) ) { |
| ((HttpSessionAttributeListener)listener).attributeAdded((HttpSessionBindingEvent)event); |
| } else if ( ReloadingListener.ATTR_REMOVED.equals(identifier) ) { |
| ((HttpSessionAttributeListener)listener).attributeRemoved((HttpSessionBindingEvent)event); |
| } else if ( ReloadingListener.ATTR_REPLACED.equals(identifier) ) { |
| ((HttpSessionAttributeListener)listener).attributeReplaced((HttpSessionBindingEvent)event); |
| } else if ( ReloadingListener.CONTEXT_ATTR_ADDED.equals(identifier) ) { |
| ((ServletContextAttributeListener)listener).attributeAdded((ServletContextAttributeEvent)event); |
| } else if ( ReloadingListener.CONTEXT_ATTR_REMOVED.equals(identifier) ) { |
| ((ServletContextAttributeListener)listener).attributeRemoved((ServletContextAttributeEvent)event); |
| } else if ( ReloadingListener.CONTEXT_ATTR_REPLACED.equals(identifier) ) { |
| ((ServletContextAttributeListener)listener).attributeReplaced((ServletContextAttributeEvent)event); |
| } else if ( ReloadingListener.SESSION_ACTIVATED.equals(identifier) ) { |
| ((HttpSessionActivationListener)listener).sessionDidActivate((HttpSessionEvent)event); |
| } else if ( ReloadingListener.SESSION_PASSIVATE.equals(identifier) ) { |
| ((HttpSessionActivationListener)listener).sessionWillPassivate((HttpSessionEvent)event); |
| } |
| } catch (Exception e) { |
| throw new RuntimeException("Cannot invoke listener " + listener, e); |
| } |
| } |
| } finally { |
| Thread.currentThread().setContextClassLoader(old); |
| } |
| } |
| } |
| |
| /** |
| * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent) |
| */ |
| public void contextDestroyed(ServletContextEvent contextEvent) { |
| this.invoke(this.servletContextListeners, ReloadingListener.SERVLET_CONTEXT_DESTROYED, contextEvent); |
| } |
| |
| /** |
| * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent) |
| */ |
| public void contextInitialized(ServletContextEvent contextEvent) { |
| final ServletContext context = contextEvent.getServletContext(); |
| this.init(context); |
| |
| this.invoke(this.servletContextListeners, ReloadingListener.SERVLET_CONTEXT_CREATED, contextEvent); |
| } |
| |
| /** |
| * @see javax.servlet.http.HttpSessionListener#sessionCreated(javax.servlet.http.HttpSessionEvent) |
| */ |
| public void sessionCreated(HttpSessionEvent event) { |
| this.invoke(this.httpSessionListeners, ReloadingListener.SESSION_CREATED, event); |
| } |
| |
| /** |
| * @see javax.servlet.http.HttpSessionListener#sessionDestroyed(javax.servlet.http.HttpSessionEvent) |
| */ |
| public void sessionDestroyed(HttpSessionEvent event) { |
| this.invoke(this.httpSessionListeners, ReloadingListener.SESSION_DESTROYED, event); |
| } |
| |
| /** |
| * @see javax.servlet.http.HttpSessionBindingListener#valueBound(javax.servlet.http.HttpSessionBindingEvent) |
| */ |
| public void valueBound(HttpSessionBindingEvent event) { |
| this.invoke(this.httpSessionBindingListeners, ReloadingListener.VALUE_BOUND, event); |
| } |
| |
| /** |
| * @see javax.servlet.http.HttpSessionBindingListener#valueUnbound(javax.servlet.http.HttpSessionBindingEvent) |
| */ |
| public void valueUnbound(HttpSessionBindingEvent event) { |
| this.invoke(this.httpSessionBindingListeners, ReloadingListener.VALUE_UNBOUND, event); |
| } |
| |
| /** |
| * @see javax.servlet.http.HttpSessionAttributeListener#attributeAdded(javax.servlet.http.HttpSessionBindingEvent) |
| */ |
| public void attributeAdded(HttpSessionBindingEvent event) { |
| this.invoke(this.httpSessionAttributeListeners, ReloadingListener.ATTR_ADDED, event); |
| } |
| |
| /** |
| * @see javax.servlet.http.HttpSessionAttributeListener#attributeRemoved(javax.servlet.http.HttpSessionBindingEvent) |
| */ |
| public void attributeRemoved(HttpSessionBindingEvent event) { |
| this.invoke(this.httpSessionAttributeListeners, ReloadingListener.ATTR_REMOVED, event); |
| } |
| |
| /** |
| * @see javax.servlet.http.HttpSessionAttributeListener#attributeReplaced(javax.servlet.http.HttpSessionBindingEvent) |
| */ |
| public void attributeReplaced(HttpSessionBindingEvent event) { |
| this.invoke(this.httpSessionAttributeListeners, ReloadingListener.ATTR_REPLACED, event); |
| } |
| |
| /** |
| * @see javax.servlet.http.HttpSessionActivationListener#sessionDidActivate(javax.servlet.http.HttpSessionEvent) |
| */ |
| public void sessionDidActivate(HttpSessionEvent event) { |
| this.invoke(this.httpSessionActivationListeners, ReloadingListener.SESSION_ACTIVATED, event); |
| } |
| |
| /** |
| * @see javax.servlet.http.HttpSessionActivationListener#sessionWillPassivate(javax.servlet.http.HttpSessionEvent) |
| */ |
| public void sessionWillPassivate(HttpSessionEvent event) { |
| this.invoke(this.httpSessionActivationListeners, ReloadingListener.SESSION_PASSIVATE, event); |
| } |
| |
| /** |
| * @see javax.servlet.ServletContextAttributeListener#attributeAdded(javax.servlet.ServletContextAttributeEvent) |
| */ |
| public void attributeAdded(ServletContextAttributeEvent event) { |
| this.invoke(this.servletContextAttributeListeners, ReloadingListener.CONTEXT_ATTR_ADDED, event); |
| } |
| |
| /** |
| * @see javax.servlet.ServletContextAttributeListener#attributeRemoved(javax.servlet.ServletContextAttributeEvent) |
| */ |
| public void attributeRemoved(ServletContextAttributeEvent event) { |
| this.invoke(this.servletContextAttributeListeners, ReloadingListener.CONTEXT_ATTR_REMOVED, event); |
| } |
| |
| /** |
| * @see javax.servlet.ServletContextAttributeListener#attributeReplaced(javax.servlet.ServletContextAttributeEvent) |
| */ |
| public void attributeReplaced(ServletContextAttributeEvent event) { |
| this.invoke(this.servletContextAttributeListeners, ReloadingListener.CONTEXT_ATTR_REPLACED, event); |
| } |
| } |