| /******************************************************************************* |
| * Copyright (c) 2015 Raymond Augé and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * 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); |
| } |
| } |
| } |
| |
| } |