This commit is contained in:
Jan Bartel 2017-02-08 13:05:48 +11:00
parent c48b471caa
commit f76dafebc3
5 changed files with 148 additions and 57 deletions

View File

@ -844,36 +844,14 @@ public class Session implements SessionHandler.SessionIf
if (_handler == null)
throw new IllegalStateException ("No session manager for session "+ _sessionData.getId());
boolean result = false;
try (Lock lock = _lock.lockIfNotHeld())
{
switch (_state)
{
case INVALID:
{
throw new IllegalStateException(); //spec does not allow invalidate of already invalid session
}
case VALID:
{
//only first change from valid to invalidating should be actionable
result = true;
_state = State.INVALIDATING;
break;
}
default:
{
LOG.info("Session {} already being invalidated", _sessionData.getId());
}
}
}
boolean result = beginInvalidate();
try
{
//if the session was not already invalid, or in process of being invalidated, do invalidate
if (result)
{
//tell id mgr to remove session from all other contexts
//tell id mgr to remove session from all contexts
_handler.getSessionIdManager().invalidateAll(_sessionData.getId());
}
}
@ -901,6 +879,39 @@ public class Session implements SessionHandler.SessionIf
{
return _lock.lockIfNotHeld();
}
/* ------------------------------------------------------------- */
/**
* @return true if the session is not already invalid or being invalidated.
*/
protected boolean beginInvalidate()
{
boolean result = false;
try (Lock lock = _lock.lockIfNotHeld())
{
switch (_state)
{
case INVALID:
{
throw new IllegalStateException(); //spec does not allow invalidate of already invalid session
}
case VALID:
{
//only first change from valid to invalidating should be actionable
result = true;
_state = State.INVALIDATING;
break;
}
default:
{
LOG.info("Session {} already being invalidated", _sessionData.getId());
}
}
}
return result;
}
/* ------------------------------------------------------------- */
/** Call HttpSessionAttributeListeners as part of invalidating
@ -908,7 +919,20 @@ public class Session implements SessionHandler.SessionIf
*
* @throws IllegalStateException
*/
@Deprecated
protected void doInvalidate() throws IllegalStateException
{
finishInvalidate();
}
/* ------------------------------------------------------------- */
/** Call HttpSessionAttributeListeners as part of invalidating
* a Session.
*
* @throws IllegalStateException
*/
protected void finishInvalidate() throws IllegalStateException
{
try (Lock lock = _lock.lockIfNotHeld())
{

View File

@ -1048,6 +1048,8 @@ public class SessionHandler extends ScopedHandler
{
if (invalidate)
{
session.beginInvalidate();
if (_sessionListeners!=null)
{
HttpSessionEvent event=new HttpSessionEvent(session);
@ -1214,8 +1216,7 @@ public class SessionHandler extends ScopedHandler
/* ------------------------------------------------------------ */
/**
* Called either when a session has expired, or the app has
* invalidated it.
* Called when a session has expired.
*
* @param id the id to invalidate
*/
@ -1232,7 +1233,7 @@ public class SessionHandler extends ScopedHandler
if (session != null)
{
_sessionTimeStats.set(round((System.currentTimeMillis() - session.getSessionData().getCreated())/1000.0));
session.doInvalidate();
session.finishInvalidate();
}
}
catch (Exception e)
@ -1242,7 +1243,11 @@ public class SessionHandler extends ScopedHandler
}
/* ------------------------------------------------------------ */
/**
* Called periodically by the HouseKeeper to handle the list of
* sessions that have expired since the last call to scavenge.
*/
public void scavenge ()
{
//don't attempt to scavenge if we are shutting down
@ -1279,7 +1284,7 @@ public class SessionHandler extends ScopedHandler
}
}
/* ------------------------------------------------------------ */
/**
* Each session has a timer that is configured to go off
* when either the session has not been accessed for a

View File

@ -22,11 +22,8 @@ package org.eclipse.jetty.gcloud.session;
import org.eclipse.jetty.server.session.AbstractSessionExpiryTest;
import org.eclipse.jetty.server.session.AbstractTestServer;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.Assert;
import org.junit.Test;
/**
@ -37,10 +34,11 @@ import org.junit.Assert;
public class SessionExpiryTest extends AbstractSessionExpiryTest
{
@AfterClass
public static void teardown () throws Exception
@After
public void teardown () throws Exception
{
GCloudTestSuite.__testSupport.deleteSessions();
System.err.println("Deleted sessions");
}
@ -53,25 +51,7 @@ public class SessionExpiryTest extends AbstractSessionExpiryTest
return new GCloudTestServer(port, max, scavenge, evictionPolicy);
}
@Test
@Override
public void testSessionNotExpired() throws Exception
{
super.testSessionNotExpired();
GCloudTestSuite.__testSupport.deleteSessions();
}
/**
* @see org.eclipse.jetty.server.session.AbstractSessionExpiryTest#testSessionExpiry()
*/
@Test
@Override
public void testSessionExpiry() throws Exception
{
super.testSessionExpiry();
GCloudTestSuite.__testSupport.deleteSessions();
}
@Override
public void verifySessionCreated(TestHttpSessionListener listener, String sessionId)
@ -80,6 +60,9 @@ public class SessionExpiryTest extends AbstractSessionExpiryTest
try {GCloudTestSuite.__testSupport.assertSessions(1);}catch(Exception e){ Assert.fail(e.getMessage());}
}
@Override
public void verifySessionDestroyed(TestHttpSessionListener listener, String sessionId)
{

View File

@ -49,9 +49,16 @@ public class SessionExpiryTest extends AbstractSessionExpiryTest
super.testSessionExpiry();
}
}
/**
* @see org.eclipse.jetty.server.session.AbstractSessionExpiryTest#testSessionExpiresWithListener()
*/
@Test
public void testSessionExpiresWithListener() throws Exception
{
super.testSessionExpiresWithListener();
}
@Test

View File

@ -68,18 +68,90 @@ public abstract class AbstractSessionExpiryTest extends AbstractTestBase
{
public List<String> createdSessions = new ArrayList<String>();
public List<String> destroyedSessions = new ArrayList<String>();
public boolean accessAttribute = false;
public Exception ex = null;
public TestHttpSessionListener(boolean access)
{
accessAttribute = access;
}
public TestHttpSessionListener()
{
accessAttribute = false;
}
public void sessionDestroyed(HttpSessionEvent se)
{
destroyedSessions.add(se.getSession().getId());
if (accessAttribute)
{
try
{
se.getSession().getAttribute("anything");
}
catch (Exception e)
{
ex = e;
}
}
}
public void sessionCreated(HttpSessionEvent se)
{
createdSessions.add(se.getSession().getId());
}
};
@Test
public void testSessionExpiresWithListener() throws Exception
{
String contextPath = "";
String servletMapping = "/server";
int inactivePeriod = 3;
int scavengePeriod = 1;
AbstractTestServer server1 = createServer(0, inactivePeriod, scavengePeriod, SessionCache.NEVER_EVICT);
TestServlet servlet = new TestServlet();
ServletHolder holder = new ServletHolder(servlet);
ServletContextHandler context = server1.addContext(contextPath);
context.addServlet(holder, servletMapping);
TestHttpSessionListener listener = new TestHttpSessionListener(true);
context.getSessionHandler().addEventListener(listener);
server1.start();
int port1 = server1.getPort();
try
{
HttpClient client = new HttpClient();
client.start();
String url = "http://localhost:" + port1 + contextPath + servletMapping;
//make a request to set up a session on the server
ContentResponse response1 = client.GET(url + "?action=init");
assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
String sessionCookie = response1.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
String sessionId = AbstractTestServer.extractSessionId(sessionCookie);
verifySessionCreated(listener,sessionId);
//and wait until the session should have expired
pause(inactivePeriod+(scavengePeriod*2));
verifySessionDestroyed (listener, sessionId);
assertNull(listener.ex);
}
finally
{
server1.stop();
}
}
/**
* Check session is preserved over stop/start