You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by rm...@apache.org on 2016/01/18 19:50:25 UTC

tomee git commit: TOMEE-1694 use tomcat destroy hook

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 <rm...@gmail.com>
Authored: Mon Jan 18 19:50:16 2016 +0100
Committer: Romain Manni-Bucau <rm...@gmail.com>
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<Class<?>> 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<ClassLoader, InstanceManager> 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<CdiCleanUpBackgroundProcess> processes;
-                        synchronized (sc) {
-                            processes = (Collection<CdiCleanUpBackgroundProcess>) 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<CdiCleanUpBackgroundProcess> processes = (Collection<CdiCleanUpBackgroundProcess>) 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<Session> 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<Endpoint, Set<Session>> sessionsByEndpoint = (Map<Endpoint, Set<Session>>) ENDPOINT_SESSION_MAP.get(container);
-                    if (sessionsByEndpoint != null) { // find sessions
-                        synchronized (lock) {
-                            for (final Map.Entry<Endpoint, Set<Session>> 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);
-            }
-        }
-    }
 }