* Issue #3799 Programmatic listeners from ServletContextListeners. Ensure programmatic listeners added from ServletContextListeners are called. Signed-off-by: Jan Bartel <janb@webtide.com> * Issue #3799 add distribution test Signed-off-by: olivier lamy <oliver.lamy@gmail.com>
This commit is contained in:
parent
154e036b1d
commit
e26179e8e9
|
@ -62,6 +62,9 @@ import javax.servlet.SessionTrackingMode;
|
|||
import javax.servlet.descriptor.JspConfigDescriptor;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSessionAttributeListener;
|
||||
import javax.servlet.http.HttpSessionIdListener;
|
||||
import javax.servlet.http.HttpSessionListener;
|
||||
|
||||
import org.eclipse.jetty.http.HttpURI;
|
||||
import org.eclipse.jetty.http.MimeTypes;
|
||||
|
@ -110,12 +113,15 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
|||
public static final int SERVLET_MAJOR_VERSION = 3;
|
||||
public static final int SERVLET_MINOR_VERSION = 1;
|
||||
public static final Class<?>[] SERVLET_LISTENER_TYPES =
|
||||
{
|
||||
ServletContextListener.class,
|
||||
ServletContextAttributeListener.class,
|
||||
ServletRequestListener.class,
|
||||
ServletRequestAttributeListener.class
|
||||
};
|
||||
{
|
||||
ServletContextListener.class,
|
||||
ServletContextAttributeListener.class,
|
||||
ServletRequestListener.class,
|
||||
ServletRequestAttributeListener.class,
|
||||
HttpSessionIdListener.class,
|
||||
HttpSessionListener.class,
|
||||
HttpSessionAttributeListener.class
|
||||
};
|
||||
|
||||
public static final int DEFAULT_LISTENER_TYPE_INDEX = 1;
|
||||
public static final int EXTENDED_LISTENER_TYPE_INDEX = 0;
|
||||
|
@ -643,7 +649,9 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
|||
_eventListeners.add(listener);
|
||||
|
||||
if (!(isStarted() || isStarting()))
|
||||
{
|
||||
_durableListeners.add(listener);
|
||||
}
|
||||
|
||||
if (listener instanceof ContextScopeListener)
|
||||
{
|
||||
|
@ -704,10 +712,15 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
|||
_programmaticListeners.add(listener);
|
||||
}
|
||||
|
||||
protected boolean isProgrammaticListener(EventListener listener)
|
||||
public boolean isProgrammaticListener(EventListener listener)
|
||||
{
|
||||
return _programmaticListeners.contains(listener);
|
||||
}
|
||||
|
||||
public boolean isDurableListener(EventListener listener)
|
||||
{
|
||||
return _durableListeners.contains(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this context is shutting down
|
||||
|
|
|
@ -22,6 +22,8 @@ import java.util.EventListener;
|
|||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
|
||||
/**
|
||||
* ListenerHolder
|
||||
*
|
||||
|
@ -32,7 +34,6 @@ import javax.servlet.ServletException;
|
|||
public class ListenerHolder extends BaseHolder<EventListener>
|
||||
{
|
||||
private EventListener _listener;
|
||||
private boolean _initialized = false;
|
||||
|
||||
public ListenerHolder()
|
||||
{
|
||||
|
@ -68,35 +69,6 @@ public class ListenerHolder extends BaseHolder<EventListener>
|
|||
setHeldClass(_listener.getClass());
|
||||
}
|
||||
|
||||
public void initialize(ServletContext context) throws Exception
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
initialize();
|
||||
|
||||
if (_listener == null)
|
||||
{
|
||||
//create an instance of the listener and decorate it
|
||||
try
|
||||
{
|
||||
_listener = (context instanceof ServletContextHandler.Context)
|
||||
? context.createListener(getHeldClass())
|
||||
: getHeldClass().getDeclaredConstructor().newInstance();
|
||||
}
|
||||
catch (ServletException ex)
|
||||
{
|
||||
Throwable cause = ex.getRootCause();
|
||||
if (cause instanceof InstantiationException)
|
||||
throw (InstantiationException)cause;
|
||||
if (cause instanceof IllegalAccessException)
|
||||
throw (IllegalAccessException)cause;
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doStart() throws Exception
|
||||
{
|
||||
|
@ -107,6 +79,29 @@ public class ListenerHolder extends BaseHolder<EventListener>
|
|||
super.stop();
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
|
||||
ContextHandler contextHandler = ContextHandler.getCurrentContext().getContextHandler();
|
||||
if (_listener == null)
|
||||
{
|
||||
//create an instance of the listener and decorate it
|
||||
try
|
||||
{
|
||||
ServletContext scontext = contextHandler.getServletContext();
|
||||
_listener = (scontext instanceof ServletContextHandler.Context)
|
||||
? scontext.createListener(getHeldClass())
|
||||
: getHeldClass().getDeclaredConstructor().newInstance();
|
||||
}
|
||||
catch (ServletException ex)
|
||||
{
|
||||
Throwable cause = ex.getRootCause();
|
||||
if (cause instanceof InstantiationException)
|
||||
throw (InstantiationException)cause;
|
||||
if (cause instanceof IllegalAccessException)
|
||||
throw (IllegalAccessException)cause;
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
contextHandler.addEventListener(_listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -115,7 +110,6 @@ public class ListenerHolder extends BaseHolder<EventListener>
|
|||
super.doStop();
|
||||
if (!_extInstance)
|
||||
_listener = null;
|
||||
_initialized = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -107,6 +107,8 @@ public class ServletContextHandler extends ContextHandler
|
|||
protected int _options;
|
||||
protected JspConfigDescriptor _jspConfig;
|
||||
|
||||
private boolean _startListeners;
|
||||
|
||||
public ServletContextHandler()
|
||||
{
|
||||
this(null, null, null, null, null);
|
||||
|
@ -347,14 +349,11 @@ public class ServletContextHandler extends ContextHandler
|
|||
for (ListenerHolder holder : _servletHandler.getListeners())
|
||||
{
|
||||
holder.start();
|
||||
//we need to pass in the context because the ServletHandler has not
|
||||
//yet got a reference to the ServletContext (happens in super.startContext)
|
||||
holder.initialize(_scontext);
|
||||
addEventListener(holder.getListener());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_startListeners = true;
|
||||
super.startContext();
|
||||
|
||||
// OK to Initialize servlet handler now that all relevant object trees have been started
|
||||
|
@ -365,6 +364,7 @@ public class ServletContextHandler extends ContextHandler
|
|||
@Override
|
||||
protected void stopContext() throws Exception
|
||||
{
|
||||
_startListeners = false;
|
||||
super.stopContext();
|
||||
}
|
||||
|
||||
|
@ -1417,8 +1417,19 @@ public class ServletContextHandler extends ContextHandler
|
|||
|
||||
ListenerHolder holder = getServletHandler().newListenerHolder(Source.JAVAX_API);
|
||||
holder.setListener(t);
|
||||
getServletHandler().addListener(holder);
|
||||
addProgrammaticListener(t);
|
||||
getServletHandler().addListener(holder);
|
||||
if (_startListeners)
|
||||
{
|
||||
try
|
||||
{
|
||||
holder.start();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -18,25 +18,48 @@
|
|||
|
||||
package org.eclipse.jetty.servlet;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EventListener;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletContainerInitializer;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletContextAttributeEvent;
|
||||
import javax.servlet.ServletContextAttributeListener;
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequestAttributeEvent;
|
||||
import javax.servlet.ServletRequestAttributeListener;
|
||||
import javax.servlet.ServletRequestEvent;
|
||||
import javax.servlet.ServletRequestListener;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import javax.servlet.http.HttpSessionAttributeListener;
|
||||
import javax.servlet.http.HttpSessionBindingEvent;
|
||||
import javax.servlet.http.HttpSessionEvent;
|
||||
import javax.servlet.http.HttpSessionIdListener;
|
||||
import javax.servlet.http.HttpSessionListener;
|
||||
|
||||
import org.eclipse.jetty.security.ConstraintSecurityHandler;
|
||||
|
@ -61,15 +84,6 @@ import org.junit.jupiter.api.AfterEach;
|
|||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class ServletContextHandlerTest
|
||||
{
|
||||
private Server _server;
|
||||
|
@ -157,8 +171,7 @@ public class ServletContextHandlerTest
|
|||
}
|
||||
|
||||
public static class MyTestSessionListener implements HttpSessionAttributeListener, HttpSessionListener
|
||||
{
|
||||
|
||||
{
|
||||
@Override
|
||||
public void sessionCreated(HttpSessionEvent se)
|
||||
{
|
||||
|
@ -184,6 +197,187 @@ public class ServletContextHandlerTest
|
|||
{
|
||||
}
|
||||
}
|
||||
|
||||
public static class MySCAListener implements ServletContextAttributeListener
|
||||
{
|
||||
public static int adds = 0;
|
||||
public static int removes = 0;
|
||||
public static int replaces = 0;
|
||||
|
||||
@Override
|
||||
public void attributeAdded(ServletContextAttributeEvent event)
|
||||
{
|
||||
++adds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeRemoved(ServletContextAttributeEvent event)
|
||||
{
|
||||
++removes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeReplaced(ServletContextAttributeEvent event)
|
||||
{
|
||||
++replaces;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MyRequestListener implements ServletRequestListener
|
||||
{
|
||||
public static int destroys = 0;
|
||||
public static int inits = 0;
|
||||
|
||||
@Override
|
||||
public void requestDestroyed(ServletRequestEvent sre)
|
||||
{
|
||||
++destroys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestInitialized(ServletRequestEvent sre)
|
||||
{
|
||||
++inits;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MyRAListener implements ServletRequestAttributeListener
|
||||
{
|
||||
public static int adds = 0;
|
||||
public static int removes = 0;
|
||||
public static int replaces = 0;
|
||||
|
||||
@Override
|
||||
public void attributeAdded(ServletRequestAttributeEvent srae)
|
||||
{
|
||||
++adds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeRemoved(ServletRequestAttributeEvent srae)
|
||||
{
|
||||
++removes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeReplaced(ServletRequestAttributeEvent srae)
|
||||
{
|
||||
++replaces;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MySListener implements HttpSessionListener
|
||||
{
|
||||
public static int creates = 0;
|
||||
public static int destroys = 0;
|
||||
|
||||
@Override
|
||||
public void sessionCreated(HttpSessionEvent se)
|
||||
{
|
||||
++creates;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionDestroyed(HttpSessionEvent se)
|
||||
{
|
||||
++destroys;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class MySAListener implements HttpSessionAttributeListener
|
||||
{
|
||||
public static int adds = 0;
|
||||
public static int removes = 0;
|
||||
public static int replaces = 0;
|
||||
|
||||
@Override
|
||||
public void attributeAdded(HttpSessionBindingEvent event)
|
||||
{
|
||||
++adds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeRemoved(HttpSessionBindingEvent event)
|
||||
{
|
||||
++removes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeReplaced(HttpSessionBindingEvent event)
|
||||
{
|
||||
++replaces;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class MySIListener implements HttpSessionIdListener
|
||||
{
|
||||
public static int changes = 0;
|
||||
|
||||
@Override
|
||||
public void sessionIdChanged(HttpSessionEvent event, String oldSessionId)
|
||||
{
|
||||
++changes;
|
||||
}
|
||||
}
|
||||
|
||||
public class InitialListener implements ServletContextListener
|
||||
{
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent sce)
|
||||
{
|
||||
//Add all of the sorts of listeners that are allowed
|
||||
try
|
||||
{
|
||||
MySCAListener mySCAListener = sce.getServletContext().createListener(MySCAListener.class);
|
||||
sce.getServletContext().addListener(mySCAListener);
|
||||
|
||||
MyRequestListener myRequestListener = sce.getServletContext().createListener(MyRequestListener.class);
|
||||
sce.getServletContext().addListener(myRequestListener);
|
||||
|
||||
MyRAListener myRAListener = sce.getServletContext().createListener(MyRAListener.class);
|
||||
sce.getServletContext().addListener(myRAListener);
|
||||
|
||||
MySListener mySListener = sce.getServletContext().createListener(MySListener.class);
|
||||
sce.getServletContext().addListener(mySListener);
|
||||
|
||||
MySAListener mySAListener = sce.getServletContext().createListener(MySAListener.class);
|
||||
sce.getServletContext().addListener(mySAListener);
|
||||
|
||||
MySIListener mySIListener = sce.getServletContext().createListener(MySIListener.class);
|
||||
sce.getServletContext().addListener(mySIListener);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
fail(e);
|
||||
}
|
||||
//And also test you can't add a ServletContextListener from a ServletContextListener
|
||||
try
|
||||
{
|
||||
MyContextListener contextListener = sce.getServletContext().createListener(MyContextListener.class);
|
||||
sce.getServletContext().addListener(contextListener);
|
||||
fail("Adding SCI from an SCI!");
|
||||
}
|
||||
catch (IllegalArgumentException e)
|
||||
{
|
||||
//expected
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
fail(x);
|
||||
}
|
||||
|
||||
sce.getServletContext().setAttribute("foo", "bar");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent sce)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void createServer()
|
||||
|
@ -232,6 +426,114 @@ public class ServletContextHandlerTest
|
|||
assertTrue((Boolean)root.getServletContext().getAttribute("MySCI.startup"));
|
||||
assertTrue((Boolean)root.getServletContext().getAttribute("MyContextListener.contextInitialized"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListenersFromContextListener() throws Exception
|
||||
{
|
||||
ContextHandlerCollection contexts = new ContextHandlerCollection();
|
||||
_server.setHandler(contexts);
|
||||
|
||||
ServletContextHandler root = new ServletContextHandler(contexts, "/", ServletContextHandler.SESSIONS);
|
||||
ListenerHolder initialListener = new ListenerHolder();
|
||||
initialListener.setListener(new InitialListener());
|
||||
root.getServletHandler().addListener(initialListener);
|
||||
ServletHolder holder0 = root.addServlet(TestServlet.class, "/test");
|
||||
_server.start();
|
||||
|
||||
ListenerHolder[] listenerHolders = root.getServletHandler().getListeners();
|
||||
assertNotNull(listenerHolders);
|
||||
for (ListenerHolder l : listenerHolders)
|
||||
{
|
||||
assertTrue(l.isStarted());
|
||||
assertNotNull(l.getListener());
|
||||
//all listeners except the first should be programmatic
|
||||
if (!"org.eclipse.jetty.servlet.ServletContextHandlerTest$InitialListener".equals(l.getClassName()))
|
||||
{
|
||||
assertFalse(root.isDurableListener(l.getListener()));
|
||||
assertTrue(root.isProgrammaticListener(l.getListener()));
|
||||
}
|
||||
}
|
||||
|
||||
EventListener[] listeners = root.getEventListeners();
|
||||
assertNotNull(listeners);
|
||||
List<String> listenerClassNames = new ArrayList<>();
|
||||
for (EventListener l : listeners)
|
||||
listenerClassNames.add(l.getClass().getName());
|
||||
|
||||
assertTrue(listenerClassNames.contains("org.eclipse.jetty.servlet.ServletContextHandlerTest$MySCAListener"));
|
||||
assertTrue(listenerClassNames.contains("org.eclipse.jetty.servlet.ServletContextHandlerTest$MyRequestListener"));
|
||||
assertTrue(listenerClassNames.contains("org.eclipse.jetty.servlet.ServletContextHandlerTest$MyRAListener"));
|
||||
assertTrue(listenerClassNames.contains("org.eclipse.jetty.servlet.ServletContextHandlerTest$MySListener"));
|
||||
assertTrue(listenerClassNames.contains("org.eclipse.jetty.servlet.ServletContextHandlerTest$MySAListener"));
|
||||
assertTrue(listenerClassNames.contains("org.eclipse.jetty.servlet.ServletContextHandlerTest$MySIListener"));
|
||||
|
||||
//test ServletRequestAttributeListener
|
||||
String response = _connector.getResponse("GET /test?req=all HTTP/1.0\r\n\r\n");
|
||||
assertThat(response, Matchers.containsString("200 OK"));
|
||||
assertEquals(1, MyRAListener.adds);
|
||||
assertEquals(1, MyRAListener.replaces);
|
||||
assertEquals(1, MyRAListener.removes);
|
||||
|
||||
//test HttpSessionAttributeListener
|
||||
response = _connector.getResponse("GET /test?session=create HTTP/1.0\r\n\r\n");
|
||||
String sessionid = response.substring(response.indexOf("JSESSIONID"), response.indexOf(";"));
|
||||
assertThat(response, Matchers.containsString("200 OK"));
|
||||
assertEquals(1, MySListener.creates);
|
||||
assertEquals(1, MySAListener.adds);
|
||||
assertEquals(0, MySAListener.replaces);
|
||||
assertEquals(0, MySAListener.removes);
|
||||
StringBuffer request = new StringBuffer();
|
||||
request.append("GET /test?session=replace HTTP/1.0\n");
|
||||
request.append("Host: localhost\n");
|
||||
request.append("Cookie: "+sessionid+"\n");
|
||||
request.append("\n");
|
||||
response = _connector.getResponse(request.toString());
|
||||
assertThat(response, Matchers.containsString("200 OK"));
|
||||
assertEquals(1, MySListener.creates);
|
||||
assertEquals(1, MySAListener.adds);
|
||||
assertEquals(1, MySAListener.replaces);
|
||||
assertEquals(0, MySAListener.removes);
|
||||
request = new StringBuffer();
|
||||
request.append("GET /test?session=remove HTTP/1.0\n");
|
||||
request.append("Host: localhost\n");
|
||||
request.append("Cookie: "+sessionid+"\n");
|
||||
request.append("\n");
|
||||
response = _connector.getResponse(request.toString());
|
||||
assertThat(response, Matchers.containsString("200 OK"));
|
||||
assertEquals(1, MySListener.creates);
|
||||
assertEquals(1, MySAListener.adds);
|
||||
assertEquals(1, MySAListener.replaces);
|
||||
assertEquals(1, MySAListener.removes);
|
||||
|
||||
//test HttpSessionIdListener.sessionIdChanged
|
||||
request = new StringBuffer();
|
||||
request.append("GET /test?session=change HTTP/1.0\n");
|
||||
request.append("Host: localhost\n");
|
||||
request.append("Cookie: "+sessionid+"\n");
|
||||
request.append("\n");
|
||||
response = _connector.getResponse(request.toString());
|
||||
assertThat(response, Matchers.containsString("200 OK"));
|
||||
assertEquals(1, MySIListener.changes);
|
||||
sessionid = response.substring(response.indexOf("JSESSIONID"), response.indexOf(";"));
|
||||
|
||||
//test HttpServletListener.sessionDestroyed
|
||||
request = new StringBuffer();
|
||||
request.append("GET /test?session=delete HTTP/1.0\n");
|
||||
request.append("Host: localhost\n");
|
||||
request.append("Cookie: "+sessionid+"\n");
|
||||
request.append("\n");
|
||||
response = _connector.getResponse(request.toString());
|
||||
assertThat(response, Matchers.containsString("200 OK"));
|
||||
assertEquals(1, MySListener.destroys);
|
||||
|
||||
//test ServletContextAttributeListener
|
||||
//attribute was set when context listener registered
|
||||
assertEquals(1, MySCAListener.adds);
|
||||
response = _connector.getResponse("GET /test?ctx=all HTTP/1.0\r\n\r\n");
|
||||
assertThat(response, Matchers.containsString("200 OK"));
|
||||
assertEquals(1, MySCAListener.replaces);
|
||||
assertEquals(1, MySCAListener.removes);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindContainer() throws Exception
|
||||
|
@ -670,6 +972,62 @@ public class ServletContextHandlerTest
|
|||
resp.setStatus(HttpServletResponse.SC_OK);
|
||||
PrintWriter writer = resp.getWriter();
|
||||
writer.write("Test");
|
||||
|
||||
String action = req.getParameter("session");
|
||||
if (!Objects.isNull(action))
|
||||
{
|
||||
if ("create".equalsIgnoreCase(action))
|
||||
{
|
||||
//Make a session
|
||||
HttpSession session = req.getSession(true);
|
||||
session.setAttribute("some", "thing");
|
||||
}
|
||||
else if ("change".equalsIgnoreCase(action))
|
||||
{
|
||||
HttpSession session = req.getSession(true);
|
||||
req.changeSessionId();
|
||||
}
|
||||
else if ("replace".equalsIgnoreCase(action))
|
||||
{
|
||||
HttpSession session = req.getSession(false);
|
||||
session.setAttribute("some", "other");
|
||||
}
|
||||
else if ("remove".equalsIgnoreCase(action))
|
||||
{
|
||||
HttpSession session = req.getSession(false);
|
||||
session.removeAttribute("some");
|
||||
}
|
||||
else if ("delete".equalsIgnoreCase(action))
|
||||
{
|
||||
HttpSession session = req.getSession(false);
|
||||
session.invalidate();
|
||||
}
|
||||
else
|
||||
resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
action = req.getParameter("req");
|
||||
if (!Objects.isNull(action))
|
||||
{
|
||||
//test all attribute ops
|
||||
req.setAttribute("some", "value");
|
||||
req.setAttribute("some", "other");
|
||||
req.removeAttribute("some");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
action = req.getParameter("ctx");
|
||||
if (!Objects.isNull(action))
|
||||
{
|
||||
//change and remove context attribute
|
||||
req.getServletContext().setAttribute("foo", "foo");
|
||||
req.getServletContext().removeAttribute("foo");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,6 +81,13 @@
|
|||
<type>war</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>test-jetty-webapp</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>war</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-test-helper</artifactId>
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.tests.distribution;
|
||||
|
||||
import org.eclipse.jetty.client.api.ContentResponse;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class DynamicListenerTests
|
||||
extends AbstractDistributionTest
|
||||
{
|
||||
@Test
|
||||
public void testSimpleWebAppWithJSP() throws Exception
|
||||
{
|
||||
Path jettyBase = Files.createTempDirectory( "jetty_base");
|
||||
String jettyVersion = System.getProperty("jettyVersion");
|
||||
DistributionTester distribution = DistributionTester.Builder.newInstance()
|
||||
.jettyBase(jettyBase)
|
||||
.jettyVersion(jettyVersion)
|
||||
.mavenLocalRepository(System.getProperty("mavenRepoPath"))
|
||||
.build();
|
||||
|
||||
String[] args1 = {
|
||||
"--create-startd",
|
||||
"--approve-all-licenses",
|
||||
"--add-to-start=resources,server,http,webapp,deploy,jsp,jmx,servlet,servlets,security,websocket"
|
||||
};
|
||||
try (DistributionTester.Run run1 = distribution.start(args1))
|
||||
{
|
||||
assertTrue(run1.awaitFor(5, TimeUnit.SECONDS));
|
||||
assertEquals(0, run1.getExitValue());
|
||||
|
||||
File war = distribution.resolveArtifact( "org.eclipse.jetty:test-jetty-webapp:war:" + jettyVersion);
|
||||
distribution.installWarFile(war, "test");
|
||||
|
||||
Path etc = Paths.get(jettyBase.toString(),"etc");
|
||||
if(!Files.exists(etc))
|
||||
{
|
||||
Files.createDirectory(etc);
|
||||
}
|
||||
|
||||
Files.copy(Paths.get("src/test/resources/realm.ini"),
|
||||
Paths.get(jettyBase.toString(),"start.d").resolve("realm.ini"));
|
||||
Files.copy(Paths.get("src/test/resources/realm.properties"),
|
||||
etc.resolve("realm.properties"));
|
||||
Files.copy(Paths.get("src/test/resources/test-realm.xml"),
|
||||
etc.resolve("test-realm.xml"));
|
||||
|
||||
int port = distribution.freePort();
|
||||
try (DistributionTester.Run run2 = distribution.start("jetty.http.port=" + port))
|
||||
{
|
||||
assertTrue(run2.awaitConsoleLogsFor("Started @", 10, TimeUnit.SECONDS));
|
||||
|
||||
startHttpClient();
|
||||
ContentResponse response = client.GET("http://localhost:" + port + "/test/testservlet/foo");
|
||||
assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||
String content = response.getContentAsString();
|
||||
System.out.println(content);
|
||||
assertThat(content, containsString("All Good"));
|
||||
assertThat(content, containsString("requestInitialized"));
|
||||
assertThat(content, containsString("requestInitialized"));
|
||||
assertThat(content, not(containsString("<%")));
|
||||
}
|
||||
} finally
|
||||
{
|
||||
IO.delete(jettyBase.toFile());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
# Example of providing a demo configuration, using a ${jetty.base}
|
||||
#
|
||||
# Additional ini files are in demo-base/start.d
|
||||
#
|
||||
# Create and configure the test realm
|
||||
etc/test-realm.xml
|
||||
jetty.demo.realm=etc/realm.properties
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#
|
||||
# This file defines users passwords and roles for a HashUserRealm
|
||||
#
|
||||
# The format is
|
||||
# <username>: <password>[,<rolename> ...]
|
||||
#
|
||||
# Passwords may be clear text, obfuscated or checksummed. The class
|
||||
# org.eclipse.util.Password should be used to generate obfuscated
|
||||
# passwords or password checksums
|
||||
#
|
||||
# If DIGEST Authentication is used, the password must be in a recoverable
|
||||
# format, either plain text or OBF:.
|
||||
#
|
||||
jetty: MD5:164c88b302622e17050af52c89945d44,user
|
||||
admin: CRYPT:adpexzg3FUZAk,server-administrator,content-administrator,admin,user
|
||||
other: OBF:1xmk1w261u9r1w1c1xmq,user
|
||||
plain: plain,user
|
||||
user: password,user
|
||||
|
||||
# This entry is for digest auth. The credential is a MD5 hash of username:realmname:password
|
||||
digest: MD5:6e120743ad67abfbc385bc2bb754e297,user
|
||||
|
||||
j2ee: j2ee,Administrator,Employee
|
||||
javajoe: javajoe,VP,Manager
|
||||
CN\=CTS,\ OU\=Java\ Software,\ O\=Sun\ Microsystems\ Inc.,\ L\=Burlington,\ ST\=MA,\ C\=,US=,Administrator
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE Configure PUBLIC "-" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
<!-- =========================================================== -->
|
||||
<!-- Configure Authentication Login Service -->
|
||||
<!-- Realms may be configured for the entire server here, or -->
|
||||
<!-- they can be configured for a specific web app in a context -->
|
||||
<!-- configuration (see $(jetty.home)/webapps/test.xml for an -->
|
||||
<!-- example). -->
|
||||
<!-- =========================================================== -->
|
||||
<Call name="addBean">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.security.HashLoginService">
|
||||
<Set name="name">Test Realm</Set>
|
||||
<Set name="config"><Property name="jetty.demo.realm" default="etc/realm.properties"/></Set>
|
||||
<Set name="hotReload">false</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
|
||||
<Get class="org.eclipse.jetty.util.log.Log" name="rootLogger">
|
||||
<Call name="warn"><Arg>demo test-realm is deployed. DO NOT USE IN PRODUCTION!</Arg></Call>
|
||||
</Get>
|
||||
</Configure>
|
|
@ -0,0 +1,50 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package com.acme;
|
||||
|
||||
import javax.servlet.ServletRequestEvent;
|
||||
import javax.servlet.ServletRequestListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public final class AddListServletRequestListener
|
||||
implements ServletRequestListener
|
||||
{
|
||||
|
||||
public void requestDestroyed( ServletRequestEvent event )
|
||||
{
|
||||
List al = (List) event.getServletContext().getAttribute( "arraylist" );
|
||||
if ( al != null )
|
||||
{
|
||||
event.getServletContext().removeAttribute( "arraylist" );
|
||||
}
|
||||
}
|
||||
|
||||
public void requestInitialized( ServletRequestEvent event )
|
||||
{
|
||||
List al = (List) event.getServletContext().getAttribute( "arraylist" );
|
||||
if ( al == null )
|
||||
{
|
||||
al = new ArrayList();
|
||||
}
|
||||
al.add( "in requestInitialized method of "+ getClass().getName() );
|
||||
event.getServletContext().setAttribute( "arraylist", al );
|
||||
}
|
||||
|
||||
}
|
|
@ -31,6 +31,7 @@ import javax.servlet.ServletContextAttributeEvent;
|
|||
import javax.servlet.ServletContextAttributeListener;
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRegistration;
|
||||
import javax.servlet.ServletRequestAttributeEvent;
|
||||
import javax.servlet.ServletRequestAttributeListener;
|
||||
|
@ -139,6 +140,18 @@ public class TestListener implements HttpSessionListener, HttpSessionAttributeLi
|
|||
EnumSet.of(DispatcherType.ERROR, DispatcherType.ASYNC, DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.REQUEST),
|
||||
true,
|
||||
"/*");
|
||||
|
||||
try
|
||||
{
|
||||
AddListServletRequestListener listenerClass =
|
||||
sce.getServletContext().createListener( AddListServletRequestListener.class );
|
||||
sce.getServletContext().addListener( listenerClass );
|
||||
}
|
||||
catch ( ServletException e )
|
||||
{
|
||||
throw new RuntimeException( e.getMessage(), e );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package com.acme;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
public class TestServlet extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
protected void doGet( HttpServletRequest req, HttpServletResponse resp )
|
||||
throws ServletException, IOException
|
||||
{
|
||||
List l = (List) getServletContext().getAttribute( "arraylist" );
|
||||
|
||||
resp.getOutputStream().println( "All Good " + l.toString() );
|
||||
}
|
||||
}
|
|
@ -188,6 +188,18 @@
|
|||
<url-pattern>/jsp/foo/</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
|
||||
<servlet>
|
||||
<servlet-name>TestServlet</servlet-name>
|
||||
<servlet-class>com.acme.TestServlet</servlet-class>
|
||||
<load-on-startup>10</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>TestServlet</servlet-name>
|
||||
<url-pattern>/testservlet/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<error-page>
|
||||
<error-code>404</error-code>
|
||||
<location>/error404.html</location>
|
||||
|
|
Loading…
Reference in New Issue