Merge remote-tracking branch 'origin/jetty-10.0.x' into jetty-11.0.x

This commit is contained in:
Jan Bartel 2021-05-16 09:53:00 +10:00
commit e0b80abf4e
6 changed files with 125 additions and 34 deletions

View File

@ -469,10 +469,7 @@ public class Session implements SessionHandler.SessionIf
{
try (AutoLock l = _lock.lock())
{
if (isInvalid())
{
throw new IllegalStateException("Session not valid");
}
checkValidForRead();
return _sessionData.getLastAccessed();
}
}
@ -867,14 +864,18 @@ public class Session implements SessionHandler.SessionIf
// do the invalidation
_handler.callSessionDestroyedListeners(this);
}
catch (Exception e)
{
LOG.warn("Error during Session destroy listener", e);
}
finally
{
// call the attribute removed listeners and finally mark it
// as invalid
finishInvalidate();
// tell id mgr to remove sessions with same id from all contexts
_handler.getSessionIdManager().invalidateAll(_sessionData.getId());
}
// tell id mgr to remove sessions with same id from all contexts
_handler.getSessionIdManager().invalidateAll(_sessionData.getId());
}
}
catch (Exception e)

View File

@ -1972,7 +1972,9 @@ public class RequestTest
@Override
public HttpSession getSession()
{
return new Session(new SessionHandler(), new SessionData(TEST_SESSION_ID, "", "0.0.0.0", 0, 0, 0, 300));
Session session = new Session(new SessionHandler(), new SessionData(TEST_SESSION_ID, "", "0.0.0.0", 0, 0, 0, 300));
session.setResident(true); //necessary for session methods to not throw ISE
return session;
}
@Override

View File

@ -41,7 +41,6 @@ import org.eclipse.jetty.util.component.LifeCycle;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -100,13 +99,9 @@ public class QoSFilterTest
rethrowExceptions(futures);
if (TestServlet.__maxSleepers <= maxQos)
LOG.warn("TEST WAS NOT PARALLEL ENOUGH!");
else
assertThat(TestServlet.__maxSleepers, Matchers.lessThanOrEqualTo(numConnections));
assertThat(TestServlet.__maxSleepers, Matchers.lessThanOrEqualTo(numConnections));
}
@Disabled("Issue #2627")
@Test
public void testBlockingQosFilter() throws Exception
{
@ -126,10 +121,7 @@ public class QoSFilterTest
rethrowExceptions(futures);
if (TestServlet.__maxSleepers < maxQos)
LOG.warn("TEST WAS NOT PARALLEL ENOUGH!");
else
assertEquals(TestServlet.__maxSleepers, maxQos);
assertEquals(TestServlet.__maxSleepers, maxQos);
}
@Test
@ -151,10 +143,7 @@ public class QoSFilterTest
rethrowExceptions(futures);
if (TestServlet.__maxSleepers < maxQos)
LOG.warn("TEST WAS NOT PARALLEL ENOUGH!");
else
assertEquals(TestServlet.__maxSleepers, maxQos);
assertEquals(TestServlet.__maxSleepers, maxQos);
}
private void rethrowExceptions(List<Future<Void>> futures) throws Exception

View File

@ -27,16 +27,18 @@ public class TestHttpSessionListener implements HttpSessionListener
public List<String> createdSessions = new ArrayList<>();
public List<String> destroyedSessions = new ArrayList<>();
public boolean accessAttribute = false;
public Exception ex = null;
public boolean lastAccessTime = false;
public Exception attributeException = null;
public Exception accessTimeException = null;
public TestHttpSessionListener(boolean access)
public TestHttpSessionListener(boolean accessAttribute, boolean lastAccessTime)
{
accessAttribute = access;
this.accessAttribute = accessAttribute;
this.lastAccessTime = lastAccessTime;
}
public TestHttpSessionListener()
{
accessAttribute = false;
}
public void sessionDestroyed(HttpSessionEvent se)
@ -50,7 +52,19 @@ public class TestHttpSessionListener implements HttpSessionListener
}
catch (Exception e)
{
ex = e;
attributeException = e;
}
}
if (lastAccessTime)
{
try
{
se.getSession().getLastAccessedTime();
}
catch (Exception e)
{
accessTimeException = e;
}
}
}

View File

@ -30,9 +30,9 @@ public class TestHttpSessionListenerWithWebappClasses extends TestHttpSessionLis
super();
}
public TestHttpSessionListenerWithWebappClasses(boolean access)
public TestHttpSessionListenerWithWebappClasses(boolean attribute, boolean lastAccessTime)
{
super(access);
super(attribute, lastAccessTime);
}
@Override
@ -47,7 +47,7 @@ public class TestHttpSessionListenerWithWebappClasses extends TestHttpSessionLis
}
catch (Exception cnfe)
{
ex = cnfe;
attributeException = cnfe;
}
super.sessionDestroyed(se);
}

View File

@ -53,6 +53,7 @@ import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.in;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
@ -87,7 +88,7 @@ public class SessionListenerTest
TestServer server = new TestServer(0, inactivePeriod, scavengePeriod,
cacheFactory, storeFactory);
ServletContextHandler context = server.addContext(contextPath);
TestHttpSessionListener listener = new TestHttpSessionListener(true);
TestHttpSessionListener listener = new TestHttpSessionListener(true, true);
context.getSessionHandler().addEventListener(listener);
TestServlet servlet = new TestServlet();
ServletHolder holder = new ServletHolder(servlet);
@ -131,6 +132,72 @@ public class SessionListenerTest
LifeCycle.stop(server);
}
}
/**
* Test that if a session listener throws an exception during sessionDestroyed the session is still invalidated
*/
@Test
public void testListenerWithInvalidationException() throws Exception
{
String contextPath = "";
String servletMapping = "/server";
int inactivePeriod = 6;
int scavengePeriod = -1;
DefaultSessionCacheFactory cacheFactory = new DefaultSessionCacheFactory();
cacheFactory.setEvictionPolicy(SessionCache.NEVER_EVICT);
TestSessionDataStoreFactory storeFactory = new TestSessionDataStoreFactory();
storeFactory.setGracePeriodSec(scavengePeriod);
TestServer server = new TestServer(0, inactivePeriod, scavengePeriod,
cacheFactory, storeFactory);
ServletContextHandler context = server.addContext(contextPath);
ThrowingSessionListener listener = new ThrowingSessionListener();
context.getSessionHandler().addEventListener(listener);
TestServlet servlet = new TestServlet();
ServletHolder holder = new ServletHolder(servlet);
context.addServlet(holder, servletMapping);
try
{
server.start();
int port1 = server.getPort();
HttpClient client = new HttpClient();
client.start();
try
{
String url = "http://localhost:" + port1 + contextPath + servletMapping;
// Create the session
ContentResponse response1 = client.GET(url + "?action=init");
assertEquals(HttpServletResponse.SC_OK, response1.getStatus());
String sessionCookie = response1.getHeaders().get("Set-Cookie");
assertNotNull(sessionCookie);
assertTrue(TestServlet.bindingListener.bound);
String sessionId = TestServer.extractSessionId(sessionCookie);
// Make a request which will invalidate the existing session
Request request2 = client.newRequest(url + "?action=test");
ContentResponse response2 = request2.send();
assertEquals(HttpServletResponse.SC_OK, response2.getStatus());
assertTrue(TestServlet.bindingListener.unbound);
//check session no longer exists
assertFalse(context.getSessionHandler().getSessionCache().contains(sessionId));
assertFalse(context.getSessionHandler().getSessionCache().getSessionDataStore().exists(sessionId));
}
finally
{
LifeCycle.stop(client);
}
}
finally
{
LifeCycle.stop(server);
}
}
/**
* Test that listeners are called when a session expires
@ -172,7 +239,7 @@ public class SessionListenerTest
ServletContextHandler context = server1.addContext(contextPath);
context.setClassLoader(contextClassLoader);
context.addServlet(holder, servletMapping);
TestHttpSessionListener listener = new TestHttpSessionListenerWithWebappClasses(true);
TestHttpSessionListener listener = new TestHttpSessionListenerWithWebappClasses(true, true);
context.getSessionHandler().addEventListener(listener);
try
@ -201,7 +268,8 @@ public class SessionListenerTest
assertThat(sessionId, is(in(listener.destroyedSessions)));
assertNull(listener.ex);
assertNull(listener.attributeException);
assertNull(listener.accessTimeException);
}
finally
{
@ -236,7 +304,7 @@ public class SessionListenerTest
ServletHolder holder = new ServletHolder(servlet);
ServletContextHandler context = server1.addContext(contextPath);
context.addServlet(holder, servletMapping);
TestHttpSessionListener listener = new TestHttpSessionListener();
TestHttpSessionListener listener = new TestHttpSessionListener(true, true);
context.getSessionHandler().addEventListener(listener);
@ -271,7 +339,8 @@ public class SessionListenerTest
assertTrue(listener.destroyedSessions.contains("1234"));
assertNull(listener.ex);
assertNull(listener.attributeException);
assertNull(listener.accessTimeException);
}
finally
{
@ -296,6 +365,22 @@ public class SessionListenerTest
{
}
}
public static class ThrowingSessionListener implements HttpSessionListener
{
@Override
public void sessionCreated(HttpSessionEvent se)
{
}
@Override
public void sessionDestroyed(HttpSessionEvent se)
{
throw new IllegalStateException("Exception during sessionDestroyed");
}
}
@Test
public void testSessionListeners()