Return-Path: X-Original-To: apmail-tomee-commits-archive@www.apache.org Delivered-To: apmail-tomee-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 59BD4184EF for ; Mon, 18 Jan 2016 18:50:25 +0000 (UTC) Received: (qmail 65636 invoked by uid 500); 18 Jan 2016 18:50:25 -0000 Delivered-To: apmail-tomee-commits-archive@tomee.apache.org Received: (qmail 65605 invoked by uid 500); 18 Jan 2016 18:50:25 -0000 Mailing-List: contact commits-help@tomee.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@tomee.apache.org Delivered-To: mailing list commits@tomee.apache.org Received: (qmail 65596 invoked by uid 99); 18 Jan 2016 18:50:25 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 18 Jan 2016 18:50:25 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 1D650DFEFE; Mon, 18 Jan 2016 18:50:25 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: rmannibucau@apache.org To: commits@tomee.apache.org Message-Id: X-Mailer: ASF-Git Admin Mailer Subject: tomee git commit: TOMEE-1694 use tomcat destroy hook Date: Mon, 18 Jan 2016 18:50:25 +0000 (UTC) Repository: tomee Updated Branches: refs/heads/master fbc4b38f2 -> fde16235f TOMEE-1694 use tomcat destroy hook Project: http://git-wip-us.apache.org/repos/asf/tomee/repo Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/fde16235 Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/fde16235 Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/fde16235 Branch: refs/heads/master Commit: fde16235fbf441016a0b44fb4a234cdc2394754f Parents: fbc4b38 Author: Romain Manni-Bucau Authored: Mon Jan 18 19:50:16 2016 +0100 Committer: Romain Manni-Bucau Committed: Mon Jan 18 19:50:16 2016 +0100 ---------------------------------------------------------------------- .../tomee/catalina/JavaeeInstanceManager.java | 46 ++++- .../tomee/catalina/OpenEJBContextConfig.java | 30 ---- .../JavaEEDefaultServerEnpointConfigurator.java | 166 +------------------ 3 files changed, 45 insertions(+), 197 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tomee/blob/fde16235/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/JavaeeInstanceManager.java ---------------------------------------------------------------------- diff --git a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/JavaeeInstanceManager.java b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/JavaeeInstanceManager.java index 3a4540e..27ab0ac 100644 --- a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/JavaeeInstanceManager.java +++ b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/JavaeeInstanceManager.java @@ -18,6 +18,7 @@ package org.apache.tomee.catalina; import org.apache.openejb.OpenEJBException; import org.apache.openejb.core.WebContext; +import org.apache.openejb.loader.SystemInstance; import org.apache.tomcat.InstanceManager; import org.apache.webbeans.exception.WebBeansConfigurationException; import org.apache.webbeans.exception.WebBeansCreationException; @@ -92,8 +93,17 @@ public class JavaeeInstanceManager implements InstanceManager { if (o == null) { return; } - preDestroy(o, o.getClass()); - webContext.destroy(o); + final Object unwrapped = unwrap(o); + preDestroy(unwrapped, unwrapped.getClass()); + webContext.destroy(unwrapped); + if (unwrapped != o) { // PojoEndpointServer, they create and track a cc so release it + webContext.destroy(o); + } + } + + private Object unwrap(final Object o) { + return "org.apache.tomcat.websocket.pojo.PojoEndpointServer".equals(o.getClass().getName()) ? + WebSocketTypes.unwrapWebSocketPojo(o) : o; } public void inject(final Object o) { @@ -193,4 +203,36 @@ public class JavaeeInstanceManager implements InstanceManager { preDestroy.setAccessible(accessibility); } } + + private static class WebSocketTypes { // extracted for lazy loading + private static final WebSocketTypes WEB_SOCKET_TYPES = new WebSocketTypes(); + private final Method getPojo; + + private WebSocketTypes() { + Method tmp; + try { + tmp = WebSocketTypes.class.getClassLoader() + .loadClass("org.apache.tomcat.websocket.pojo.PojoEndpointBase") + .getDeclaredMethod("getPojo"); + tmp.setAccessible(true); + } catch (final NoSuchMethodException e) { + if ("true".equals(SystemInstance.get().getProperty("tomee.websocket.skip", "false"))) { + tmp = null; + } else { + throw new IllegalStateException(e); + } + } catch (final ClassNotFoundException e) { + tmp = null; // no websocket support + } + getPojo = tmp; + } + + private static Object unwrapWebSocketPojo(final Object o) { + try { + return WEB_SOCKET_TYPES.getPojo == null ? o : WEB_SOCKET_TYPES.getPojo.invoke(o); + } catch (final IllegalAccessException | InvocationTargetException | NullPointerException e) { + return o; + } + } + } } http://git-wip-us.apache.org/repos/asf/tomee/blob/fde16235/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/OpenEJBContextConfig.java ---------------------------------------------------------------------- diff --git a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/OpenEJBContextConfig.java b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/OpenEJBContextConfig.java index 7e2e410..b3d06a4 100644 --- a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/OpenEJBContextConfig.java +++ b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/OpenEJBContextConfig.java @@ -64,10 +64,6 @@ import org.apache.webbeans.web.context.WebConversationFilter; import org.apache.xbean.finder.IAnnotationFinder; import javax.servlet.ServletContainerInitializer; -import javax.servlet.ServletContext; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; -import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.ws.rs.core.Application; import java.io.ByteArrayInputStream; @@ -431,32 +427,6 @@ public class OpenEJBContextConfig extends ContextConfig { final ClassLoader classLoader = context.getLoader().getClassLoader(); - try { - classLoader.loadClass("org.apache.tomcat.websocket.server.DefaultServerEndpointConfigurator"); - context.addServletContainerInitializer(new ServletContainerInitializer() { - @Override - public void onStartup(final Set> c, final ServletContext ctx) throws ServletException { - ctx.addListener(new ServletContextListener() { - @Override - public void contextInitialized(final ServletContextEvent sce) { - //no -op - } - - @Override - public void contextDestroyed(final ServletContextEvent sce) { // ensure we cleanup our "eviction" processes - try { - org.apache.tomee.catalina.websocket.JavaEEDefaultServerEnpointConfigurator.unregisterProcesses(sce.getServletContext()); - } catch (final Throwable th) { - // no-op - } - } - }); - } - }, null); - } catch (final Throwable noWebSocket) { - // no-op: ok - } - // add myfaces auto-initializer if mojarra is not present try { classLoader.loadClass("com.sun.faces.context.SessionMap"); http://git-wip-us.apache.org/repos/asf/tomee/blob/fde16235/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/websocket/JavaEEDefaultServerEnpointConfigurator.java ---------------------------------------------------------------------- diff --git a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/websocket/JavaEEDefaultServerEnpointConfigurator.java b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/websocket/JavaEEDefaultServerEnpointConfigurator.java index f73b80f..34df1dc 100644 --- a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/websocket/JavaEEDefaultServerEnpointConfigurator.java +++ b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/websocket/JavaEEDefaultServerEnpointConfigurator.java @@ -16,51 +16,14 @@ */ package org.apache.tomee.catalina.websocket; -import org.apache.openejb.core.WebContext; import org.apache.openejb.loader.SystemInstance; import org.apache.tomcat.InstanceManager; -import org.apache.tomcat.websocket.BackgroundProcess; -import org.apache.tomcat.websocket.BackgroundProcessManager; -import org.apache.tomcat.websocket.WsWebSocketContainer; -import org.apache.tomcat.websocket.pojo.PojoEndpointBase; -import org.apache.tomcat.websocket.server.Constants; import org.apache.tomcat.websocket.server.DefaultServerEndpointConfigurator; -import org.apache.tomee.catalina.JavaeeInstanceManager; import org.apache.tomee.catalina.TomcatWebAppBuilder; -import javax.servlet.ServletContext; -import javax.websocket.Endpoint; -import javax.websocket.Session; -import javax.websocket.WebSocketContainer; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Collection; -import java.util.LinkedList; import java.util.Map; -import java.util.Set; public class JavaEEDefaultServerEnpointConfigurator extends DefaultServerEndpointConfigurator { - private static final String BG_PROCESSES_LIST = JavaEEDefaultServerEnpointConfigurator.class.getName() + ".bgProcesses"; - - // for websocket eviction - private static final Field END_POINT_SESSION_MAP_LOCK; - private static final Field ENDPOINT_SESSION_MAP; - private static final Method GET_POJO; - static { - try { - ENDPOINT_SESSION_MAP = WsWebSocketContainer.class.getDeclaredField("endpointSessionMap"); - ENDPOINT_SESSION_MAP.setAccessible(true); - END_POINT_SESSION_MAP_LOCK = WsWebSocketContainer.class.getDeclaredField("endPointSessionMapLock"); - END_POINT_SESSION_MAP_LOCK.setAccessible(true); - - GET_POJO = PojoEndpointBase.class.getDeclaredMethod("getPojo"); - GET_POJO.setAccessible(true); - } catch (final Exception e) { - throw new IllegalStateException("Toncat not compatible with tomee", e); - } - } - private final Map instanceManagers; public JavaEEDefaultServerEnpointConfigurator() { @@ -87,38 +50,7 @@ public class JavaEEDefaultServerEnpointConfigurator extends DefaultServerEndpoin } try { - final Object instance; - if (JavaeeInstanceManager.class.isInstance(instanceManager)) { - final JavaeeInstanceManager javaeeInstanceManager = JavaeeInstanceManager.class.cast(instanceManager); - final WebContext.Instance cdiInstance = javaeeInstanceManager.newWeakableInstance(clazz); - instance = cdiInstance.getValue(); - if (cdiInstance.getCreationalContext() != null) { // TODO: if we manage to have better listeners on tomcat we can use it rather than it - final ServletContext sc = javaeeInstanceManager.getServletContext(); - if (sc != null) { - Collection processes; - synchronized (sc) { - processes = (Collection) sc.getAttribute(BG_PROCESSES_LIST); - if (processes == null) { - processes = new LinkedList<>(); - sc.setAttribute(BG_PROCESSES_LIST, processes); - } - } - - final WebSocketContainer wsc = WebSocketContainer.class.cast(sc.getAttribute(Constants.SERVER_CONTAINER_SERVLET_CONTEXT_ATTRIBUTE)); - final Object lock = END_POINT_SESSION_MAP_LOCK.get(wsc); - if (wsc != null && WsWebSocketContainer.class.isInstance(wsc)) { - final CdiCleanUpBackgroundProcess process = new CdiCleanUpBackgroundProcess(wsc, cdiInstance, lock); - synchronized (processes) { - processes.add(process); - } - BackgroundProcessManager.getInstance().register(process); - } - } - } - } else { - instance = instanceManager.newInstance(clazz); - } - return clazz.cast(instance); + return clazz.cast(instanceManager.newInstance(clazz)); } catch (final Exception e) { if (InstantiationException.class.isInstance(e)) { throw InstantiationException.class.cast(e); @@ -126,100 +58,4 @@ public class JavaEEDefaultServerEnpointConfigurator extends DefaultServerEndpoin throw new InstantiationException(e.getMessage()); } } - - public static void unregisterProcesses(final ServletContext sc) { // no sync needed at this point - no more "runtime" - final Collection processes = (Collection) sc.getAttribute(BG_PROCESSES_LIST); - if (processes == null) { - return; - } - for (final CdiCleanUpBackgroundProcess p : processes) { - try { - p.stop(); - } catch (final RuntimeException e) { - // no-op - } - } - } - - private static final class CdiCleanUpBackgroundProcess implements BackgroundProcess { - private volatile int period = 1; // 1s by default - private volatile int acceptRetries = 3; // in case there is latency between this call and registerSession() - private volatile Set sessions; - private volatile boolean stopped; - - private final WebSocketContainer container; - private final Object lock; - private final WebContext.Instance cdiInstance; - - private CdiCleanUpBackgroundProcess(final WebSocketContainer wsc, final WebContext.Instance cdiInstance, final Object lock) { - this.container = wsc; - this.cdiInstance = cdiInstance; - this.lock = lock; - } - - @Override - public void backgroundProcess() { - if (!hasSession() && --acceptRetries > 0) { - stop(); - } - } - - @Override - public void setProcessPeriod(final int period) { - this.period = period; - } - - @Override - public int getProcessPeriod() { - return period; - } - - private boolean hasSession() { - try { - if (sessions == null) { // needs to be lazy cause tomcat register sessions after - final Map> sessionsByEndpoint = (Map>) ENDPOINT_SESSION_MAP.get(container); - if (sessionsByEndpoint != null) { // find sessions - synchronized (lock) { - for (final Map.Entry> e : sessionsByEndpoint.entrySet()) { - if (e.getKey() == cdiInstance.getValue()) { - sessions = e.getValue(); - break; - } - if (PojoEndpointBase.class.isInstance(e.getKey())) { - try { - final Object pojo = GET_POJO.invoke(e.getKey()); - if (pojo == cdiInstance.getValue()) { - sessions = e.getValue(); - break; - } - } catch (final InvocationTargetException e1) { - // no-op - } - } - } - } - } - } - - synchronized (lock) { - return sessions != null && !sessions.isEmpty(); - } - } catch (final IllegalAccessException e) { - // no-op - } - return false; - } - - public void stop() { - if (stopped) { - return; - } - stopped = true; - try { - cdiInstance.getCreationalContext().release(); - } finally { - BackgroundProcessManager.getInstance().unregister(this); - } - } - } }