From 9da6520831f29d05fa69de20d6c3b4a2d1a7a605 Mon Sep 17 00:00:00 2001 From: Jan Bartel Date: Mon, 23 Mar 2020 18:03:57 +0100 Subject: [PATCH] Issue #4700 ServletContext.createXXX methods should throw UnsupportedOperationException Signed-off-by: Jan Bartel --- .../jetty/servlet/ServletContextHandler.java | 36 +++++ .../servlet/ServletContextHandlerTest.java | 132 +++++++++++++++++- 2 files changed, 167 insertions(+), 1 deletion(-) diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java index 9d2206412875..b061eceb0a85 100644 --- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java +++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java @@ -1418,6 +1418,42 @@ public void setSessionTimeout(int sessionTimeout) _sessionHandler.setMaxInactiveInterval((int)tmp); } } + + @Override + public T createServlet(Class clazz) throws ServletException + { + if (!_enabled) + throw new UnsupportedOperationException(); + return super.createServlet(clazz); + } + + @Override + public T createFilter(Class clazz) throws ServletException + { + if (!_enabled) + throw new UnsupportedOperationException(); + return super.createFilter(clazz); + } + + @Override + public T createListener(Class clazz) throws ServletException + { + if (!_enabled) + throw new UnsupportedOperationException(); + try + { + checkListener(clazz); + } + catch (IllegalArgumentException e) + { + //Bizarrely, according to the spec, it is NOT an error to create an instance of + //a ServletContextListener from inside a ServletContextListener, but it IS an error + //to call addListener with one! + if (!ServletContextListener.class.isAssignableFrom(clazz)) + throw e; + } + return super.createListener(clazz); + } @Override public void addListener(String className) diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java index fdd6fab34cd5..70e92c3b4d08 100644 --- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java +++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java @@ -397,6 +397,66 @@ public void sessionIdChanged(HttpSessionEvent event, String oldSessionId) } } + /** + * ServletContextListener that is designed to be added programmatically, + * which should make all of the createListener, createServlet, createFilter + * methods fail with UnsupportedOperationException + * + */ + public class CreatingSCL implements ServletContextListener + { + @Override + public void contextInitialized(ServletContextEvent sce) + { + try + { + sce.getServletContext().createFilter(MyFilter.class); + sce.getServletContext().setAttribute("CreatingSCL.filter", Boolean.FALSE); + } + catch (UnsupportedOperationException e) + { + sce.getServletContext().setAttribute("CreatingSCL.filter", Boolean.TRUE); + } + catch (Exception e) + { + fail(e); + } + + try + { + sce.getServletContext().createServlet(HelloServlet.class); + sce.getServletContext().setAttribute("CreatingSCL.servlet", Boolean.FALSE); + } + catch (UnsupportedOperationException e) + { + sce.getServletContext().setAttribute("CreatingSCL.servlet", Boolean.TRUE); + } + catch (Exception e) + { + fail(e); + } + + try + { + sce.getServletContext().createListener(MyContextListener.class); + sce.getServletContext().setAttribute("CreatingSCL.listener", Boolean.FALSE); + } + catch (UnsupportedOperationException e) + { + sce.getServletContext().setAttribute("CreatingSCL.listener", Boolean.TRUE); + } + catch (Exception e) + { + fail(e); + } + } + + @Override + public void contextDestroyed(ServletContextEvent sce) + { + } + } + public class InitialListener implements ServletContextListener { @Override @@ -432,7 +492,7 @@ public void contextInitialized(ServletContextEvent sce) { MyContextListener contextListener = sce.getServletContext().createListener(MyContextListener.class); sce.getServletContext().addListener(contextListener); - fail("Adding SCI from an SCI!"); + fail("Adding SCL from an SCL!"); } catch (IllegalArgumentException e) { @@ -748,6 +808,76 @@ public void testAddServletFromServlet() throws Exception fail(e); } } + + @Test + public void testCreateMethodsFromSCI() throws Exception + { + //A filter can be created by an SCI + ContextHandlerCollection contexts = new ContextHandlerCollection(); + _server.setHandler(contexts); + + ServletContextHandler root = new ServletContextHandler(contexts, "/"); + class FilterCreatingSCI implements ServletContainerInitializer + { + @Override + public void onStartup(Set> c, ServletContext ctx) throws ServletException + { + try + { + ctx.createFilter(MyFilter.class); + } + catch (Exception e) + { + fail(e); + } + + try + { + ctx.createServlet(HelloServlet.class); + } + catch (Exception e) + { + fail(e); + } + + try + { + ctx.createListener(MyContextListener.class); + } + catch (Exception e) + { + fail(e); + } + } + } + + root.addBean(new MySCIStarter(root.getServletContext(), new FilterCreatingSCI()), true); + _server.start(); + } + + @Test + public void testCreateMethodsFromSCL() throws Exception + { + //A filter can be created by an SCI + ContextHandlerCollection contexts = new ContextHandlerCollection(); + _server.setHandler(contexts); + + ServletContextHandler root = new ServletContextHandler(contexts, "/"); + class ListenerCreatingSCI implements ServletContainerInitializer + { + @Override + public void onStartup(Set> c, ServletContext ctx) throws ServletException + { + ctx.addListener(new CreatingSCL()); + } + } + + root.addBean(new MySCIStarter(root.getServletContext(), new ListenerCreatingSCI()), true); + _server.start(); + assertTrue((Boolean)root.getServletContext().getAttribute("CreatingSCL.filter")); + assertTrue((Boolean)root.getServletContext().getAttribute("CreatingSCL.servlet")); + assertTrue((Boolean)root.getServletContext().getAttribute("CreatingSCL.listener")); + } @Test public void testAddFilterFromServlet() throws Exception