From 6a1bcea0da78feef4067a1c7c6c2cc01b97a550d Mon Sep 17 00:00:00 2001 From: gregw Date: Tue, 22 Dec 2020 14:33:30 +0100 Subject: [PATCH 1/7] Fix #5835 Durable Filters, Servlets and Listeners Filters, Servlets and Listeners are only durable if added prior to starting. --- .../eclipse/jetty/servlet/ServletHandler.java | 63 +++++++++---------- .../jetty/servlet/ServletHandlerTest.java | 62 ++++++++++++++++++ 2 files changed, 92 insertions(+), 33 deletions(-) diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java index 4f29e4e76d83..bbf872bbdc1e 100644 --- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java +++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java @@ -26,7 +26,6 @@ import java.util.EventListener; import java.util.HashMap; import java.util.List; -import java.util.ListIterator; import java.util.Map; import java.util.Objects; import java.util.Set; @@ -111,6 +110,7 @@ public class ServletHandler extends ScopedHandler private List _filterPathMappings; private MultiMap _filterNameMappings; private List _wildFilterNameMappings; + private final List> _durable = new ArrayList<>(); private final Map _servletNameMap = new HashMap<>(); private PathMappings _servletPathMap; @@ -160,6 +160,11 @@ protected synchronized void doStart() _identityService = securityHandler.getIdentityService(); } + _durable.clear(); + _durable.addAll(Arrays.asList(getFilters())); + _durable.addAll(Arrays.asList(getServlets())); + _durable.addAll(Arrays.asList(getListeners())); + updateNameMappings(); updateMappings(); @@ -234,35 +239,31 @@ protected synchronized void doStop() List filterMappings = ArrayUtil.asMutableList(_filterMappings); if (_filters != null) { - for (int i = _filters.length; i-- > 0; ) + for (FilterHolder f : _filters) { try { - _filters[i].stop(); + f.stop(); } catch (Exception e) { LOG.warn(Log.EXCEPTION, e); } - if (_filters[i].getSource() != Source.EMBEDDED) + if (_durable.contains(f)) + { + filterHolders.add(f); //only retain embedded + } + else { //remove all of the mappings that were for non-embedded filters - _filterNameMap.remove(_filters[i].getName()); + _filterNameMap.remove(f.getName()); //remove any mappings associated with this filter - ListIterator fmitor = filterMappings.listIterator(); - while (fmitor.hasNext()) - { - FilterMapping fm = fmitor.next(); - if (fm.getFilterName().equals(_filters[i].getName())) - fmitor.remove(); - } + filterMappings.removeIf(fm -> fm.getFilterName().equals(f.getName())); } - else - filterHolders.add(_filters[i]); //only retain embedded } } - //Retain only filters and mappings that were added using jetty api (ie Source.EMBEDDED) + //Retain only filters and mappings that were added using jetty api prior to starting FilterHolder[] fhs = filterHolders.toArray(new FilterHolder[0]); updateBeans(_filters, fhs); _filters = fhs; @@ -278,36 +279,32 @@ protected synchronized void doStop() List servletMappings = ArrayUtil.asMutableList(_servletMappings); //will be remaining mappings if (_servlets != null) { - for (int i = _servlets.length; i-- > 0; ) + for (ServletHolder s : _servlets) { try { - _servlets[i].stop(); + s.stop(); } catch (Exception e) { LOG.warn(Log.EXCEPTION, e); } - if (_servlets[i].getSource() != Source.EMBEDDED) + if (_durable.contains(s)) + { + servletHolders.add(s); //only retain embedded + } + else { //remove from servlet name map - _servletNameMap.remove(_servlets[i].getName()); + _servletNameMap.remove(s.getName()); //remove any mappings associated with this servlet - ListIterator smitor = servletMappings.listIterator(); - while (smitor.hasNext()) - { - ServletMapping sm = smitor.next(); - if (sm.getServletName().equals(_servlets[i].getName())) - smitor.remove(); - } + servletMappings.removeIf(sm -> sm.getServletName().equals(s.getName())); } - else - servletHolders.add(_servlets[i]); //only retain embedded } } - //Retain only Servlets and mappings added via jetty apis (ie Source.EMBEDDED) + // Retain only Servlets and mappings added via jetty apis prior to starting ServletHolder[] shs = servletHolders.toArray(new ServletHolder[0]); updateBeans(_servlets, shs); _servlets = shs; @@ -322,18 +319,18 @@ protected synchronized void doStop() List listenerHolders = new ArrayList<>(); if (_listeners != null) { - for (int i = _listeners.length; i-- > 0; ) + for (ListenerHolder l : _listeners) { try { - _listeners[i].stop(); + l.stop(); } catch (Exception e) { LOG.warn(Log.EXCEPTION, e); } - if (_listeners[i].getSource() == Source.EMBEDDED) - listenerHolders.add(_listeners[i]); + if (_durable.contains(l)) + listenerHolders.add(l); } } ListenerHolder[] listeners = listenerHolders.toArray(new ListenerHolder[0]); diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletHandlerTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletHandlerTest.java index 5bddd101f309..5638e625b6e7 100644 --- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletHandlerTest.java +++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletHandlerTest.java @@ -20,11 +20,14 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.EnumSet; import java.util.List; import javax.servlet.DispatcherType; import javax.servlet.Filter; import javax.servlet.FilterConfig; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; @@ -35,11 +38,13 @@ import org.eclipse.jetty.http.pathmap.MappedResource; import org.eclipse.jetty.server.LocalConnector; import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.component.Container; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsString; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -836,6 +841,63 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Se assertThat(connector.getResponse("GET /other.bob HTTP/1.0\r\n\r\n"), containsString("path-/*-path-*.bob-default")); } + @Test + public void testDurableEmbedded() throws Exception + { + Server server = new Server(); + ServletContextHandler context = new ServletContextHandler(); + server.setHandler(context); + ServletHandler handler = context.getServletHandler(); + + FilterHolder durableFilter = new FilterHolder((TestFilter)(req,res,c) -> c.doFilter(req, res)); + ServletHolder durableServlet = new ServletHolder(new HttpServlet(){}); + ListenerHolder durableListener = new ListenerHolder(MyServletListener.class); + + FilterHolder transientFilter = new FilterHolder((TestFilter)(req,res,c) -> c.doFilter(req, res)); + ServletHolder transientServlet = new ServletHolder(new HttpServlet(){}); + ListenerHolder transientListener = new ListenerHolder(MyServletListener.class); + + handler.addFilter(durableFilter); + handler.addServletWithMapping(durableServlet, "/"); + handler.addListener(durableListener); + + context.addBean(new AbstractLifeCycle() + { + @Override + protected void doStart() throws Exception + { + handler.addFilter(transientFilter); + handler.addServlet(transientServlet); + handler.addListener(transientListener); + } + }); + + server.start(); + + assertThat(Arrays.asList(handler.getFilters()), containsInAnyOrder(durableFilter, transientFilter)); + assertThat(Arrays.asList(handler.getServlets()), containsInAnyOrder(durableServlet, transientServlet)); + assertThat(Arrays.asList(handler.getListeners()), containsInAnyOrder(durableListener, transientListener)); + + server.stop(); + + assertThat(Arrays.asList(handler.getFilters()), containsInAnyOrder(durableFilter)); + assertThat(Arrays.asList(handler.getServlets()), containsInAnyOrder(durableServlet)); + assertThat(Arrays.asList(handler.getListeners()), containsInAnyOrder(durableListener)); + } + + public static class MyServletListener implements ServletContextListener + { + @Override + public void contextInitialized(ServletContextEvent sce) + { + } + + @Override + public void contextDestroyed(ServletContextEvent sce) + { + } + } + private interface TestFilter extends Filter { default void init(FilterConfig filterConfig) throws ServletException From 1fd8caf100fc87a4c94d1db830fb9c17000597c9 Mon Sep 17 00:00:00 2001 From: gregw Date: Tue, 22 Dec 2020 15:08:57 +0100 Subject: [PATCH 2/7] Fix #5835 Durable Filters, Servlets and Listeners For non durable ServletContextListeners ensure that initialized is called if they are added during starting and that destroyed is called. --- .../jetty/server/handler/ContextHandler.java | 41 ++++++------ .../server/handler/ContextHandlerTest.java | 64 +++++++++++++++++++ 2 files changed, 83 insertions(+), 22 deletions(-) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index f917aad6c960..8078658b1554 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -689,7 +689,7 @@ public void addEventListener(EventListener listener) { _eventListeners.add(listener); - if (!(isStarted() || isStarting())) + if (!isRunning()) { _durableListeners.add(listener); } @@ -702,7 +702,16 @@ public void addEventListener(EventListener listener) } if (listener instanceof ServletContextListener) - _servletContextListeners.add((ServletContextListener)listener); + { + ServletContextListener scl = (ServletContextListener)listener; + _servletContextListeners.add(scl); + if (_contextStatus == ContextStatus.INITIALIZED) + { + if (isStarting()) + scl.contextInitialized(new ServletContextEvent(_scontext)); + _destroyServletContextListeners.add(scl); + } + } if (listener instanceof ServletContextAttributeListener) _servletContextAttributeListeners.add((ServletContextAttributeListener)listener); @@ -982,31 +991,19 @@ protected void startContext() throws Exception public void contextInitialized() throws Exception { // Call context listeners - switch (_contextStatus) + if (_contextStatus == ContextStatus.NOTSET) { - case NOTSET: + _contextStatus = ContextStatus.INITIALIZED; + _destroyServletContextListeners.clear(); + if (!_servletContextListeners.isEmpty()) { - try - { - _destroyServletContextListeners.clear(); - if (!_servletContextListeners.isEmpty()) - { - ServletContextEvent event = new ServletContextEvent(_scontext); - for (ServletContextListener listener : _servletContextListeners) - { - callContextInitialized(listener, event); - _destroyServletContextListeners.add(listener); - } - } - } - finally + ServletContextEvent event = new ServletContextEvent(_scontext); + for (ServletContextListener listener : _servletContextListeners) { - _contextStatus = ContextStatus.INITIALIZED; + callContextInitialized(listener, event); + _destroyServletContextListeners.add(listener); } - break; } - default: - break; } } diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java index 24e1f7d40e91..105b47c422bd 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java @@ -27,6 +27,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.http.HttpServletRequest; @@ -482,6 +483,69 @@ public void testContextInitializationDestruction() throws Exception assertEquals(1, listener.destroyed); } + @Test + public void testNonDurableContextListener() throws Exception + { + Server server = new Server(); + ContextHandler context = new ContextHandler(); + server.setHandler(context); + AtomicInteger initialized = new AtomicInteger(); + AtomicInteger destroyed = new AtomicInteger(); + + context.addEventListener(new ServletContextListener() + { + @Override + public void contextInitialized(ServletContextEvent sce) + { + initialized.incrementAndGet(); + context.addEventListener(new ServletContextListener() + { + @Override + public void contextInitialized(ServletContextEvent sce) + { + initialized.incrementAndGet(); + } + + @Override + public void contextDestroyed(ServletContextEvent sce) + { + destroyed.incrementAndGet(); + } + }); + } + + @Override + public void contextDestroyed(ServletContextEvent sce) + { + destroyed.incrementAndGet(); + } + }); + + server.start(); + assertThat(initialized.get(), is(2)); + + context.addEventListener(new ServletContextListener() + { + @Override + public void contextInitialized(ServletContextEvent sce) + { + // This should not get called because added after started + initialized.incrementAndGet(); + } + + @Override + public void contextDestroyed(ServletContextEvent sce) + { + destroyed.incrementAndGet(); + } + }); + + assertThat(initialized.get(), is(2)); + + server.stop(); + assertThat(destroyed.get(), is(3)); + } + @Test public void testContextVirtualGetContext() throws Exception { From d72046c0585250998761ae7617058b24b2d1eee4 Mon Sep 17 00:00:00 2001 From: gregw Date: Tue, 22 Dec 2020 15:24:04 +0100 Subject: [PATCH 3/7] Fix #5835 Durable Filters, Servlets and Listeners Fixed destroy order. --- .../eclipse/jetty/servlet/ServletHandler.java | 103 +++++++++--------- .../jetty/servlet/DefaultServletTest.java | 2 + 2 files changed, 51 insertions(+), 54 deletions(-) diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java index bbf872bbdc1e..5a1732e3207e 100644 --- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java +++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java @@ -237,29 +237,27 @@ protected synchronized void doStop() // Stop filters List filterHolders = new ArrayList<>(); List filterMappings = ArrayUtil.asMutableList(_filterMappings); - if (_filters != null) + for (int i = _filters == null ? 0 : _filters.length; i-- > 0;) { - for (FilterHolder f : _filters) + FilterHolder f = _filters[i]; + try { - try - { - f.stop(); - } - catch (Exception e) - { - LOG.warn(Log.EXCEPTION, e); - } - if (_durable.contains(f)) - { - filterHolders.add(f); //only retain embedded - } - else - { - //remove all of the mappings that were for non-embedded filters - _filterNameMap.remove(f.getName()); - //remove any mappings associated with this filter - filterMappings.removeIf(fm -> fm.getFilterName().equals(f.getName())); - } + f.stop(); + } + catch (Exception e) + { + LOG.warn(Log.EXCEPTION, e); + } + if (_durable.contains(f)) + { + filterHolders.add(f); //only retain embedded + } + else + { + //remove all of the mappings that were for non-embedded filters + _filterNameMap.remove(f.getName()); + //remove any mappings associated with this filter + filterMappings.removeIf(fm -> fm.getFilterName().equals(f.getName())); } } @@ -277,30 +275,28 @@ protected synchronized void doStop() // Stop servlets List servletHolders = new ArrayList<>(); //will be remaining servlets List servletMappings = ArrayUtil.asMutableList(_servletMappings); //will be remaining mappings - if (_servlets != null) + for (int i = _servlets == null ? 0 : _servlets.length; i-- > 0;) { - for (ServletHolder s : _servlets) + ServletHolder s = _servlets[i]; + try { - try - { - s.stop(); - } - catch (Exception e) - { - LOG.warn(Log.EXCEPTION, e); - } + s.stop(); + } + catch (Exception e) + { + LOG.warn(Log.EXCEPTION, e); + } - if (_durable.contains(s)) - { - servletHolders.add(s); //only retain embedded - } - else - { - //remove from servlet name map - _servletNameMap.remove(s.getName()); - //remove any mappings associated with this servlet - servletMappings.removeIf(sm -> sm.getServletName().equals(s.getName())); - } + if (_durable.contains(s)) + { + servletHolders.add(s); //only retain embedded + } + else + { + //remove from servlet name map + _servletNameMap.remove(s.getName()); + //remove any mappings associated with this servlet + servletMappings.removeIf(sm -> sm.getServletName().equals(s.getName())); } } @@ -317,22 +313,21 @@ protected synchronized void doStop() //Retain only Listeners added via jetty apis (is Source.EMBEDDED) List listenerHolders = new ArrayList<>(); - if (_listeners != null) + for (int i = _listeners == null ? 0 : _listeners.length; i-- > 0;) { - for (ListenerHolder l : _listeners) + ListenerHolder l = _listeners[i]; + try { - try - { - l.stop(); - } - catch (Exception e) - { - LOG.warn(Log.EXCEPTION, e); - } - if (_durable.contains(l)) - listenerHolders.add(l); + l.stop(); } + catch (Exception e) + { + LOG.warn(Log.EXCEPTION, e); + } + if (_durable.contains(l)) + listenerHolders.add(l); } + ListenerHolder[] listeners = listenerHolders.toArray(new ListenerHolder[0]); updateBeans(_listeners, listeners); _listeners = listeners; diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java index b3165a2970c9..b664de51e603 100644 --- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java +++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java @@ -1457,11 +1457,13 @@ public void testFiltered() throws Exception Path image = docRoot.resolve("image.jpg"); createFile(image, "not an image"); + server.stop(); ServletHolder defholder = context.addServlet(DefaultServlet.class, "/"); defholder.setInitParameter("dirAllowed", "false"); defholder.setInitParameter("redirectWelcome", "false"); defholder.setInitParameter("welcomeServlets", "false"); defholder.setInitParameter("gzip", "false"); + server.start(); String rawResponse; HttpTester.Response response; From 4b6930f8e65faf0408ad9e58b9d5a87da6089778 Mon Sep 17 00:00:00 2001 From: Lachlan Roberts Date: Wed, 23 Dec 2020 18:49:19 +1100 Subject: [PATCH 4/7] Issue #5835 - fix tests for restarting webapp with websocket enabled Signed-off-by: Lachlan Roberts --- .../WebSocketServerContainerInitializer.java | 5 ++++- ...eWebSocketServletContainerInitializer.java | 20 ++++++++++++++++++- .../server/WebSocketUpgradeFilter.java | 11 ++++++---- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/deploy/WebSocketServerContainerInitializer.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/deploy/WebSocketServerContainerInitializer.java index bcbab91fb5a2..652ccc7acdbe 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/deploy/WebSocketServerContainerInitializer.java +++ b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/deploy/WebSocketServerContainerInitializer.java @@ -81,10 +81,13 @@ public void contextDestroyed(ServletContextEvent sce) ServerContainer bean = handler.getBean(ServerContainer.class); if (bean != null) handler.removeBean(bean); + + // Remove reference in ServletContextHandler. + handler.removeAttribute(ATTR_JAVAX_SERVER_CONTAINER); } //remove reference in attributes - sce.getServletContext().removeAttribute(javax.websocket.server.ServerContainer.class.getName()); + sce.getServletContext().removeAttribute(ATTR_JAVAX_SERVER_CONTAINER); } } diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/NativeWebSocketServletContainerInitializer.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/NativeWebSocketServletContainerInitializer.java index bec4995129f5..d04f67fdf233 100644 --- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/NativeWebSocketServletContainerInitializer.java +++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/NativeWebSocketServletContainerInitializer.java @@ -24,6 +24,8 @@ import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.listener.ContainerInitializer; +import org.eclipse.jetty.util.component.AbstractLifeCycle; +import org.eclipse.jetty.util.component.LifeCycle; public class NativeWebSocketServletContainerInitializer implements ServletContainerInitializer { @@ -63,8 +65,24 @@ public static NativeWebSocketConfiguration initialize(ServletContextHandler cont configuration = new NativeWebSocketConfiguration(context.getServletContext()); context.setAttribute(ATTR_KEY, configuration); - // Attach default configuration to context lifecycle + // Attach default configuration to context lifecycle. context.addManaged(configuration); + + // We want to remove the NativeWebSocketConfiguration only if it was added after starting. + if (context.isStarted() || context.isStarting()) + { + NativeWebSocketConfiguration finalConfiguration = configuration; + context.addLifeCycleListener(new AbstractLifeCycle.AbstractLifeCycleListener() + { + @Override + public void lifeCycleStopping(LifeCycle event) + { + context.removeAttribute(ATTR_KEY); + context.removeBean(finalConfiguration); + context.removeLifeCycleListener(this); + } + }); + } } return configuration; } diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilter.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilter.java index 6138423f1adf..b691ab313e14 100644 --- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilter.java +++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilter.java @@ -182,11 +182,14 @@ public void destroy() { try { + // We must clear out the configuration as the configuration is cleared on restart. + NativeWebSocketConfiguration config = configuration; + boolean localConfig = localConfiguration; + configuration = null; + localConfiguration = false; alreadySetToAttribute = false; - if (localConfiguration) - { - configuration.stop(); - } + if (localConfig) + config.stop(); } catch (Exception e) { From 176e58d0c4e7e3d23c583093aed1a45de81ea405 Mon Sep 17 00:00:00 2001 From: gregw Date: Wed, 23 Dec 2020 12:34:27 +0100 Subject: [PATCH 5/7] Fix #5835 Durable Filters, Servlets and Listeners Update WebSocketUpgradeFilter to have durable configuration. --- .../server/WebSocketUpgradeFilter.java | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilter.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilter.java index b691ab313e14..9d25582b02a1 100644 --- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilter.java +++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilter.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.util.EnumSet; +import java.util.Objects; import javax.servlet.DispatcherType; import javax.servlet.Filter; import javax.servlet.FilterChain; @@ -131,12 +132,12 @@ public static WebSocketUpgradeFilter configureContext(ServletContext context) th private NativeWebSocketConfiguration configuration; private String instanceKey; - private boolean localConfiguration = false; + private boolean durableConfiguration = false; + private boolean managedConfiguration = false; private boolean alreadySetToAttribute = false; public WebSocketUpgradeFilter() { - // do nothing } public WebSocketUpgradeFilter(WebSocketServerFactory factory) @@ -146,6 +147,7 @@ public WebSocketUpgradeFilter(WebSocketServerFactory factory) public WebSocketUpgradeFilter(NativeWebSocketConfiguration configuration) { + durableConfiguration = configuration != null; this.configuration = configuration; } @@ -182,14 +184,17 @@ public void destroy() { try { - // We must clear out the configuration as the configuration is cleared on restart. NativeWebSocketConfiguration config = configuration; - boolean localConfig = localConfiguration; - configuration = null; - localConfiguration = false; - alreadySetToAttribute = false; - if (localConfig) + if (!durableConfiguration) + configuration = null; + + boolean managed = managedConfiguration; + managedConfiguration = false; + if (managed) + { config.stop(); + } + alreadySetToAttribute = false; } catch (Exception e) { @@ -332,7 +337,14 @@ public void init(FilterConfig config) throws ServletException configurationKey = NativeWebSocketConfiguration.class.getName(); } - if (configuration == null) + if (durableConfiguration) + { + Objects.requireNonNull(this.configuration); + // We have a NativeWebSocketConfiguration already present, make sure it exists on the ServletContext + config.getServletContext().setAttribute(configurationKey, this.configuration); + + } + else { this.configuration = (NativeWebSocketConfiguration)config.getServletContext().getAttribute(configurationKey); if (this.configuration == null) @@ -342,18 +354,10 @@ public void init(FilterConfig config) throws ServletException NativeWebSocketConfiguration.class.getName() + " at ServletContext attribute '" + configurationKey + "'"); } } - else - { - // We have a NativeWebSocketConfiguration already present, make sure it exists on the ServletContext - if (config.getServletContext().getAttribute(configurationKey) == null) - { - config.getServletContext().setAttribute(configurationKey, this.configuration); - } - } if (!this.configuration.isRunning()) { - localConfiguration = true; + managedConfiguration = true; this.configuration.start(); } From ba34eb74b217c7ac8c99db87fa82a28d050f23c2 Mon Sep 17 00:00:00 2001 From: gregw Date: Tue, 29 Dec 2020 18:02:06 +0100 Subject: [PATCH 6/7] Fix #5835 Durable Filters, Servlets and Listeners throw ISE for SCL added after init --- .../org/eclipse/jetty/server/handler/ContextHandler.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index 8078658b1554..2db66f6089a6 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -707,9 +707,9 @@ public void addEventListener(EventListener listener) _servletContextListeners.add(scl); if (_contextStatus == ContextStatus.INITIALIZED) { - if (isStarting()) - scl.contextInitialized(new ServletContextEvent(_scontext)); - _destroyServletContextListeners.add(scl); + throw new IllegalStateException("Context is initialized"); +// scl.contextInitialized(new ServletContextEvent(_scontext)); +// _destroyServletContextListeners.add(scl); } } From cc75e4ea0f39a14d40202582405bb0bf13c9d650 Mon Sep 17 00:00:00 2001 From: gregw Date: Tue, 9 Feb 2021 09:33:23 +0100 Subject: [PATCH 7/7] minor cleanup --- .../org/eclipse/jetty/server/handler/ContextHandler.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index d96fc9c78eec..b5bb0e2d1d76 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -703,14 +703,9 @@ public void addEventListener(EventListener listener) if (listener instanceof ServletContextListener) { - ServletContextListener scl = (ServletContextListener)listener; - _servletContextListeners.add(scl); if (_contextStatus == ContextStatus.INITIALIZED) - { throw new IllegalStateException("Context is initialized"); -// scl.contextInitialized(new ServletContextEvent(_scontext)); -// _destroyServletContextListeners.add(scl); - } + _servletContextListeners.add((ServletContextListener)listener); } if (listener instanceof ServletContextAttributeListener)