blob: 99c9e662586c0bb429702bd786fa71f13ed7aee4 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015 Raymond Augé and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Raymond Augé <raymond.auge@liferay.com> - Bug 436698
******************************************************************************/
package org.eclipse.equinox.http.servlet.internal.registration;
import java.lang.reflect.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.eclipse.equinox.http.servlet.internal.context.ContextController;
import org.eclipse.equinox.http.servlet.internal.context.ContextController.ServiceHolder;
import org.eclipse.equinox.http.servlet.internal.servlet.HttpSessionAdaptor;
import org.osgi.framework.wiring.BundleWiring;
import org.osgi.service.http.runtime.dto.ListenerDTO;
/**
* @author Raymond Augé
*/
public class ListenerRegistration extends Registration<EventListener, ListenerDTO> {
private final ServiceHolder<EventListener> listenerHolder;
private final List<Class<? extends EventListener>> classes;
private final EventListener proxy;
private final ServletContext servletContext;
private final ContextController contextController;
private final ClassLoader classLoader;
public ListenerRegistration(
ServiceHolder<EventListener> listenerHolder, List<Class<? extends EventListener>> classes,
ListenerDTO listenerDTO, ServletContext servletContext,
ContextController contextController) {
super(listenerHolder.get(), listenerDTO);
this.listenerHolder = listenerHolder;
this.classes = classes;
this.servletContext = servletContext;
this.contextController = contextController;
classLoader = listenerHolder.getBundle().adapt(BundleWiring.class).getClassLoader();
createContextAttributes();
proxy = (EventListener)Proxy.newProxyInstance(
getClass().getClassLoader(), classes.toArray(new Class[0]),
new EventListenerInvocationHandler());
}
@Override
public synchronized void destroy() {
ClassLoader original = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(classLoader);
contextController.getListenerRegistrations().remove(this);
contextController.getEventListeners().remove(classes, this);
contextController.ungetServletContextHelper(listenerHolder.getBundle());
super.destroy();
if (classes.contains(HttpSessionBindingListener.class) ||
classes.contains(HttpSessionAttributeListener.class) ||
classes.contains(HttpSessionListener.class)) {
Map<String, HttpSessionAdaptor> activeSessions =
contextController.getActiveSessions();
for (HttpSessionAdaptor adaptor : activeSessions.values()) {
adaptor.invokeSessionListeners(classes, super.getT());
}
}
if (classes.contains(ServletContextListener.class)) {
ServletContextListener servletContextListener =
(ServletContextListener)super.getT();
servletContextListener.contextDestroyed(
new ServletContextEvent(servletContext));
}
}
finally {
destroyContextAttributes();
Thread.currentThread().setContextClassLoader(original);
listenerHolder.release();
}
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof ListenerRegistration)) {
return false;
}
ListenerRegistration listenerRegistration = (ListenerRegistration)obj;
return listenerRegistration.getT().equals(super.getT());
}
@Override
public int hashCode() {
return Long.valueOf(getD().serviceId).hashCode();
}
public ServletContext getServletContext() {
return servletContext;
}
@Override
public EventListener getT() {
return proxy;
}
private void createContextAttributes() {
contextController.getProxyContext().createContextAttributes(
contextController);
}
private void destroyContextAttributes() {
contextController.getProxyContext().destroyContextAttributes(
contextController);
}
private class EventListenerInvocationHandler implements InvocationHandler {
public EventListenerInvocationHandler() {
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
ClassLoader original = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(classLoader);
try {
return method.invoke(ListenerRegistration.super.getT(), args);
} catch (InvocationTargetException e) {
throw e.getCause();
}
}
finally {
Thread.currentThread().setContextClassLoader(original);
}
}
}
}