blob: da4b3a56ec8189c4bcd2a8ade3cb9a04cfb7d95a [file] [log] [blame]
/*
* 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);
}
}