Merge branch 'master' into jetty-9.4.x-Feature
This commit is contained in:
commit
c5f0c80cd2
|
@ -31,6 +31,7 @@ import org.eclipse.jetty.client.api.Request;
|
||||||
import org.eclipse.jetty.client.api.Response;
|
import org.eclipse.jetty.client.api.Response;
|
||||||
import org.eclipse.jetty.client.api.Result;
|
import org.eclipse.jetty.client.api.Result;
|
||||||
import org.eclipse.jetty.client.util.BufferingResponseListener;
|
import org.eclipse.jetty.client.util.BufferingResponseListener;
|
||||||
|
import org.eclipse.jetty.http.HttpField;
|
||||||
import org.eclipse.jetty.http.HttpHeader;
|
import org.eclipse.jetty.http.HttpHeader;
|
||||||
import org.eclipse.jetty.util.log.Log;
|
import org.eclipse.jetty.util.log.Log;
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
|
@ -40,7 +41,6 @@ public abstract class AuthenticationProtocolHandler implements ProtocolHandler
|
||||||
public static final int DEFAULT_MAX_CONTENT_LENGTH = 16*1024;
|
public static final int DEFAULT_MAX_CONTENT_LENGTH = 16*1024;
|
||||||
public static final Logger LOG = Log.getLogger(AuthenticationProtocolHandler.class);
|
public static final Logger LOG = Log.getLogger(AuthenticationProtocolHandler.class);
|
||||||
private static final Pattern AUTHENTICATE_PATTERN = Pattern.compile("([^\\s]+)\\s+realm=\"([^\"]+)\"(.*)", Pattern.CASE_INSENSITIVE);
|
private static final Pattern AUTHENTICATE_PATTERN = Pattern.compile("([^\\s]+)\\s+realm=\"([^\"]+)\"(.*)", Pattern.CASE_INSENSITIVE);
|
||||||
private static final String AUTHENTICATION_ATTRIBUTE = AuthenticationProtocolHandler.class.getName() + ".authentication";
|
|
||||||
|
|
||||||
private final HttpClient client;
|
private final HttpClient client;
|
||||||
private final int maxContentLength;
|
private final int maxContentLength;
|
||||||
|
@ -64,6 +64,8 @@ public abstract class AuthenticationProtocolHandler implements ProtocolHandler
|
||||||
|
|
||||||
protected abstract URI getAuthenticationURI(Request request);
|
protected abstract URI getAuthenticationURI(Request request);
|
||||||
|
|
||||||
|
protected abstract String getAuthenticationAttribute();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Response.Listener getResponseListener()
|
public Response.Listener getResponseListener()
|
||||||
{
|
{
|
||||||
|
@ -92,8 +94,9 @@ public abstract class AuthenticationProtocolHandler implements ProtocolHandler
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String authenticationAttribute = getAuthenticationAttribute();
|
||||||
HttpConversation conversation = request.getConversation();
|
HttpConversation conversation = request.getConversation();
|
||||||
if (conversation.getAttribute(AUTHENTICATION_ATTRIBUTE) != null)
|
if (conversation.getAttribute(authenticationAttribute) != null)
|
||||||
{
|
{
|
||||||
// We have already tried to authenticate, but we failed again
|
// We have already tried to authenticate, but we failed again
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
|
@ -146,18 +149,16 @@ public abstract class AuthenticationProtocolHandler implements ProtocolHandler
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
conversation.setAttribute(AUTHENTICATION_ATTRIBUTE, true);
|
conversation.setAttribute(authenticationAttribute, true);
|
||||||
|
|
||||||
Request newRequest = client.copyRequest(request, request.getURI());
|
Request newRequest = client.copyRequest(request, request.getURI());
|
||||||
authnResult.apply(newRequest);
|
authnResult.apply(newRequest);
|
||||||
newRequest.onResponseSuccess(new Response.SuccessListener()
|
// Copy existing, explicitly set, authorization headers.
|
||||||
{
|
copyIfAbsent(request, newRequest, HttpHeader.AUTHORIZATION);
|
||||||
@Override
|
copyIfAbsent(request, newRequest, HttpHeader.PROXY_AUTHORIZATION);
|
||||||
public void onSuccess(Response response)
|
|
||||||
{
|
newRequest.onResponseSuccess(r -> client.getAuthenticationStore().addAuthenticationResult(authnResult))
|
||||||
client.getAuthenticationStore().addAuthenticationResult(authnResult);
|
.send(null);
|
||||||
}
|
|
||||||
}).send(null);
|
|
||||||
}
|
}
|
||||||
catch (Throwable x)
|
catch (Throwable x)
|
||||||
{
|
{
|
||||||
|
@ -167,6 +168,13 @@ public abstract class AuthenticationProtocolHandler implements ProtocolHandler
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void copyIfAbsent(HttpRequest oldRequest, Request newRequest, HttpHeader header)
|
||||||
|
{
|
||||||
|
HttpField field = oldRequest.getHeaders().getField(header);
|
||||||
|
if (field != null && !newRequest.getHeaders().contains(header))
|
||||||
|
newRequest.getHeaders().put(field);
|
||||||
|
}
|
||||||
|
|
||||||
private void forwardSuccessComplete(HttpRequest request, Response response)
|
private void forwardSuccessComplete(HttpRequest request, Response response)
|
||||||
{
|
{
|
||||||
HttpConversation conversation = request.getConversation();
|
HttpConversation conversation = request.getConversation();
|
||||||
|
|
|
@ -153,14 +153,9 @@ public abstract class HttpConnection implements Connection
|
||||||
request.header(HttpHeader.COOKIE.asString(), cookies.toString());
|
request.header(HttpHeader.COOKIE.asString(), cookies.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Authorization
|
// Authentication
|
||||||
URI authenticationURI = proxy != null ? proxy.getURI() : request.getURI();
|
applyAuthentication(request, proxy != null ? proxy.getURI() : null);
|
||||||
if (authenticationURI != null)
|
applyAuthentication(request, request.getURI());
|
||||||
{
|
|
||||||
Authentication.Result authnResult = getHttpClient().getAuthenticationStore().findAuthenticationResult(authenticationURI);
|
|
||||||
if (authnResult != null)
|
|
||||||
authnResult.apply(request);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private StringBuilder convertCookies(List<HttpCookie> cookies, StringBuilder builder)
|
private StringBuilder convertCookies(List<HttpCookie> cookies, StringBuilder builder)
|
||||||
|
@ -177,6 +172,16 @@ public abstract class HttpConnection implements Connection
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void applyAuthentication(Request request, URI uri)
|
||||||
|
{
|
||||||
|
if (uri != null)
|
||||||
|
{
|
||||||
|
Authentication.Result result = getHttpClient().getAuthenticationStore().findAuthenticationResult(uri);
|
||||||
|
if (result != null)
|
||||||
|
result.apply(request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected SendFailure send(HttpChannel channel, HttpExchange exchange)
|
protected SendFailure send(HttpChannel channel, HttpExchange exchange)
|
||||||
{
|
{
|
||||||
// Forbid idle timeouts for the time window where
|
// Forbid idle timeouts for the time window where
|
||||||
|
|
|
@ -34,6 +34,7 @@ import org.eclipse.jetty.http.HttpStatus;
|
||||||
public class ProxyAuthenticationProtocolHandler extends AuthenticationProtocolHandler
|
public class ProxyAuthenticationProtocolHandler extends AuthenticationProtocolHandler
|
||||||
{
|
{
|
||||||
public static final String NAME = "proxy-authenticate";
|
public static final String NAME = "proxy-authenticate";
|
||||||
|
private static final String ATTRIBUTE = ProxyAuthenticationProtocolHandler.class.getName() + ".attribute";
|
||||||
|
|
||||||
public ProxyAuthenticationProtocolHandler(HttpClient client)
|
public ProxyAuthenticationProtocolHandler(HttpClient client)
|
||||||
{
|
{
|
||||||
|
@ -76,4 +77,10 @@ public class ProxyAuthenticationProtocolHandler extends AuthenticationProtocolHa
|
||||||
ProxyConfiguration.Proxy proxy = destination.getProxy();
|
ProxyConfiguration.Proxy proxy = destination.getProxy();
|
||||||
return proxy != null ? proxy.getURI() : request.getURI();
|
return proxy != null ? proxy.getURI() : request.getURI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getAuthenticationAttribute()
|
||||||
|
{
|
||||||
|
return ATTRIBUTE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ import org.eclipse.jetty.http.HttpStatus;
|
||||||
public class WWWAuthenticationProtocolHandler extends AuthenticationProtocolHandler
|
public class WWWAuthenticationProtocolHandler extends AuthenticationProtocolHandler
|
||||||
{
|
{
|
||||||
public static final String NAME = "www-authenticate";
|
public static final String NAME = "www-authenticate";
|
||||||
|
private static final String ATTRIBUTE = WWWAuthenticationProtocolHandler.class.getName() + ".attribute";
|
||||||
|
|
||||||
public WWWAuthenticationProtocolHandler(HttpClient client)
|
public WWWAuthenticationProtocolHandler(HttpClient client)
|
||||||
{
|
{
|
||||||
|
@ -74,4 +75,10 @@ public class WWWAuthenticationProtocolHandler extends AuthenticationProtocolHand
|
||||||
{
|
{
|
||||||
return request.getURI();
|
return request.getURI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getAuthenticationAttribute()
|
||||||
|
{
|
||||||
|
return ATTRIBUTE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ public class HttpClientProxyTest extends AbstractHttpClientServerTest
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAuthenticatedProxiedRequest() throws Exception
|
public void testProxyAuthentication() throws Exception
|
||||||
{
|
{
|
||||||
final String user = "foo";
|
final String user = "foo";
|
||||||
final String password = "bar";
|
final String password = "bar";
|
||||||
|
@ -160,7 +160,7 @@ public class HttpClientProxyTest extends AbstractHttpClientServerTest
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAuthenticatedProxiedRequestWithRedirect() throws Exception
|
public void testProxyAuthenticationWithRedirect() throws Exception
|
||||||
{
|
{
|
||||||
String user = "foo";
|
String user = "foo";
|
||||||
String password = "bar";
|
String password = "bar";
|
||||||
|
@ -254,4 +254,148 @@ public class HttpClientProxyTest extends AbstractHttpClientServerTest
|
||||||
Assert.assertEquals(status, response3.getStatus());
|
Assert.assertEquals(status, response3.getStatus());
|
||||||
Assert.assertEquals(1, requests.get());
|
Assert.assertEquals(1, requests.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testProxyAuthenticationWithServerAuthentication() throws Exception
|
||||||
|
{
|
||||||
|
String proxyRealm = "proxyRealm";
|
||||||
|
String serverRealm = "serverRealm";
|
||||||
|
int status = HttpStatus.NO_CONTENT_204;
|
||||||
|
start(new AbstractHandler()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||||
|
{
|
||||||
|
baseRequest.setHandled(true);
|
||||||
|
String authorization = request.getHeader(HttpHeader.PROXY_AUTHORIZATION.asString());
|
||||||
|
if (authorization == null)
|
||||||
|
{
|
||||||
|
response.setStatus(HttpStatus.PROXY_AUTHENTICATION_REQUIRED_407);
|
||||||
|
response.setHeader(HttpHeader.PROXY_AUTHENTICATE.asString(), "Basic realm=\"" + proxyRealm + "\"");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
authorization = request.getHeader(HttpHeader.AUTHORIZATION.asString());
|
||||||
|
if (authorization == null)
|
||||||
|
{
|
||||||
|
response.setStatus(HttpStatus.UNAUTHORIZED_401);
|
||||||
|
response.setHeader(HttpHeader.WWW_AUTHENTICATE.asString(), "Basic realm=\"" + serverRealm + "\"");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response.setStatus(status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
String proxyHost = "localhost";
|
||||||
|
int proxyPort = connector.getLocalPort();
|
||||||
|
String serverHost = "server";
|
||||||
|
int serverPort = proxyPort + 1;
|
||||||
|
URI proxyURI = URI.create(scheme + "://" + proxyHost + ":" + proxyPort);
|
||||||
|
client.getAuthenticationStore().addAuthentication(new BasicAuthentication(proxyURI, proxyRealm, "proxyUser", "proxyPassword"));
|
||||||
|
URI serverURI = URI.create(scheme + "://" + serverHost + ":" + serverPort);
|
||||||
|
client.getAuthenticationStore().addAuthentication(new BasicAuthentication(serverURI, serverRealm, "serverUser", "serverPassword"));
|
||||||
|
client.getProxyConfiguration().getProxies().add(new HttpProxy(proxyHost, proxyPort));
|
||||||
|
final AtomicInteger requests = new AtomicInteger();
|
||||||
|
client.getRequestListeners().add(new Request.Listener.Adapter()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Request request)
|
||||||
|
{
|
||||||
|
requests.incrementAndGet();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Make a request, expect 407 + 401 + 204.
|
||||||
|
ContentResponse response1 = client.newRequest(serverHost, serverPort)
|
||||||
|
.scheme(scheme)
|
||||||
|
.timeout(5, TimeUnit.SECONDS)
|
||||||
|
.send();
|
||||||
|
|
||||||
|
Assert.assertEquals(status, response1.getStatus());
|
||||||
|
Assert.assertEquals(3, requests.get());
|
||||||
|
|
||||||
|
// Make again the request, authentication is cached, expect 204.
|
||||||
|
requests.set(0);
|
||||||
|
ContentResponse response2 = client.newRequest(serverHost, serverPort)
|
||||||
|
.scheme(scheme)
|
||||||
|
.timeout(5, TimeUnit.SECONDS)
|
||||||
|
.send();
|
||||||
|
|
||||||
|
Assert.assertEquals(status, response2.getStatus());
|
||||||
|
Assert.assertEquals(1, requests.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testProxyAuthenticationWithExplicitAuthorizationHeader() throws Exception
|
||||||
|
{
|
||||||
|
String proxyRealm = "proxyRealm";
|
||||||
|
String serverRealm = "serverRealm";
|
||||||
|
int status = HttpStatus.NO_CONTENT_204;
|
||||||
|
start(new AbstractHandler()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||||
|
{
|
||||||
|
baseRequest.setHandled(true);
|
||||||
|
String authorization = request.getHeader(HttpHeader.PROXY_AUTHORIZATION.asString());
|
||||||
|
if (authorization == null)
|
||||||
|
{
|
||||||
|
response.setStatus(HttpStatus.PROXY_AUTHENTICATION_REQUIRED_407);
|
||||||
|
response.setHeader(HttpHeader.PROXY_AUTHENTICATE.asString(), "Basic realm=\"" + proxyRealm + "\"");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
authorization = request.getHeader(HttpHeader.AUTHORIZATION.asString());
|
||||||
|
if (authorization == null)
|
||||||
|
{
|
||||||
|
response.setStatus(HttpStatus.UNAUTHORIZED_401);
|
||||||
|
response.setHeader(HttpHeader.WWW_AUTHENTICATE.asString(), "Basic realm=\"" + serverRealm + "\"");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response.setStatus(status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
String proxyHost = "localhost";
|
||||||
|
int proxyPort = connector.getLocalPort();
|
||||||
|
String serverHost = "server";
|
||||||
|
int serverPort = proxyPort + 1;
|
||||||
|
URI proxyURI = URI.create(scheme + "://" + proxyHost + ":" + proxyPort);
|
||||||
|
client.getAuthenticationStore().addAuthentication(new BasicAuthentication(proxyURI, proxyRealm, "proxyUser", "proxyPassword"));
|
||||||
|
client.getProxyConfiguration().getProxies().add(new HttpProxy(proxyHost, proxyPort));
|
||||||
|
final AtomicInteger requests = new AtomicInteger();
|
||||||
|
client.getRequestListeners().add(new Request.Listener.Adapter()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Request request)
|
||||||
|
{
|
||||||
|
requests.incrementAndGet();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Make a request, expect 407 + 204.
|
||||||
|
ContentResponse response1 = client.newRequest(serverHost, serverPort)
|
||||||
|
.scheme(scheme)
|
||||||
|
.header(HttpHeader.AUTHORIZATION, "Basic foobar")
|
||||||
|
.timeout(5, TimeUnit.SECONDS)
|
||||||
|
.send();
|
||||||
|
|
||||||
|
Assert.assertEquals(status, response1.getStatus());
|
||||||
|
Assert.assertEquals(2, requests.get());
|
||||||
|
|
||||||
|
// Make again the request, authentication is cached, expect 204.
|
||||||
|
requests.set(0);
|
||||||
|
ContentResponse response2 = client.newRequest(serverHost, serverPort)
|
||||||
|
.scheme(scheme)
|
||||||
|
.header(HttpHeader.AUTHORIZATION, "Basic foobar")
|
||||||
|
.timeout(5, TimeUnit.SECONDS)
|
||||||
|
.send();
|
||||||
|
|
||||||
|
Assert.assertEquals(status, response2.getStatus());
|
||||||
|
Assert.assertEquals(1, requests.get());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -208,7 +208,7 @@ public class InfinispanSessionDataStore extends AbstractSessionDataStore
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Class<?> remoteClass = Thread.currentThread().getContextClassLoader().loadClass("org.infinispan.client.hotrod.RemoteCache");
|
Class<?> remoteClass = Thread.currentThread().getContextClassLoader().loadClass("org.infinispan.client.hotrod.RemoteCache");
|
||||||
if (_cache.getClass().isAssignableFrom(remoteClass))
|
if (remoteClass.isAssignableFrom(_cache.getClass()))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,6 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
|
||||||
final static Logger LOG = Log.getLogger("org.eclipse.jetty.server.session");
|
final static Logger LOG = Log.getLogger("org.eclipse.jetty.server.session");
|
||||||
|
|
||||||
protected SessionDataStore _sessionDataStore;
|
protected SessionDataStore _sessionDataStore;
|
||||||
protected StalenessStrategy _staleStrategy;
|
|
||||||
protected SessionManager _manager;
|
protected SessionManager _manager;
|
||||||
protected SessionContext _context;
|
protected SessionContext _context;
|
||||||
protected int _idlePassivationTimeoutSec;
|
protected int _idlePassivationTimeoutSec;
|
||||||
|
@ -80,6 +79,16 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
|
||||||
public abstract Session doPutIfAbsent (String id, Session session);
|
public abstract Session doPutIfAbsent (String id, Session session);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace the mapping from id to oldValue with newValue
|
||||||
|
* @param id
|
||||||
|
* @param oldValue
|
||||||
|
* @param newValue
|
||||||
|
* @return true if replacement was done
|
||||||
|
*/
|
||||||
|
public abstract boolean doReplace (String id, Session oldValue, Session newValue);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check to see if the session exists in the store
|
* Check to see if the session exists in the store
|
||||||
|
@ -99,6 +108,24 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PlaceHolder
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected class PlaceHolderSession extends Session
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
public PlaceHolderSession(SessionData data)
|
||||||
|
{
|
||||||
|
super(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -185,21 +212,6 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
|
||||||
_sessionDataStore = sessionDataStore;
|
_sessionDataStore = sessionDataStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the strategy for detecting stale sessions or null if there isn't one
|
|
||||||
*/
|
|
||||||
public StalenessStrategy getStaleStrategy()
|
|
||||||
{
|
|
||||||
return _staleStrategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param staleStrategy
|
|
||||||
*/
|
|
||||||
public void setStaleStrategy(StalenessStrategy staleStrategy)
|
|
||||||
{
|
|
||||||
_staleStrategy = staleStrategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -238,53 +250,132 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
|
||||||
@Override
|
@Override
|
||||||
public Session get(String id, boolean staleCheck) throws Exception
|
public Session get(String id, boolean staleCheck) throws Exception
|
||||||
{
|
{
|
||||||
//look locally
|
Session session = null;
|
||||||
Session session = doGet(id);
|
Exception ex = null;
|
||||||
|
|
||||||
//TODO also check that session is only written out if only the access time changes infrequently
|
while (true)
|
||||||
|
|
||||||
//session is either not in session store, or it is stale, or its been passivated, load the data for the session if possible
|
|
||||||
if (session == null || (staleCheck && isStale(session)) || session.isPassivated() && _sessionDataStore != null)
|
|
||||||
{
|
{
|
||||||
SessionData data = _sessionDataStore.load(id);
|
session = doGet(id);
|
||||||
|
|
||||||
|
if (_sessionDataStore == null)
|
||||||
|
break; //can't load any session data so just return null or the session object
|
||||||
|
|
||||||
//session wasn't in session store
|
|
||||||
if (session == null)
|
if (session == null)
|
||||||
{
|
{
|
||||||
if (data != null)
|
if (LOG.isDebugEnabled())
|
||||||
|
LOG.debug("Session not found locally, attempting to load");
|
||||||
|
|
||||||
|
//didn't get a session, try and create one and put in a placeholder for it
|
||||||
|
PlaceHolderSession phs = new PlaceHolderSession (new SessionData(id, null, null,0,0,0,0));
|
||||||
|
Lock phsLock = phs.lock();
|
||||||
|
Session s = doPutIfAbsent(id, phs);
|
||||||
|
if (s == null)
|
||||||
{
|
{
|
||||||
session = newSession(data);
|
//My placeholder won, go ahead and load the full session data
|
||||||
session.setSessionManager(_manager);
|
try
|
||||||
Session existing = doPutIfAbsent(id, session);
|
|
||||||
if (existing != null)
|
|
||||||
{
|
{
|
||||||
//some other thread has got in first and added the session
|
session = loadSession(id);
|
||||||
//so use it
|
if (session == null)
|
||||||
session = existing;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//else session not in store and not in data store either, so doesn't exist
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
//session was already in session store, refresh it if its still stale/passivated
|
//session does not exist, remove the placeholder
|
||||||
|
doDelete(id);
|
||||||
|
phsLock.close();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
try (Lock lock = session.lock())
|
try (Lock lock = session.lock())
|
||||||
{
|
{
|
||||||
if (session.isPassivated() || staleCheck && isStale(session))
|
//swap it in instead of the placeholder
|
||||||
|
boolean success = doReplace(id, phs, session);
|
||||||
|
if (!success)
|
||||||
{
|
{
|
||||||
//if we were able to load it, then update our session object
|
//something has gone wrong, it should have been our placeholder
|
||||||
if (data != null)
|
doDelete(id);
|
||||||
|
session = null;
|
||||||
|
LOG.warn("Replacement of placeholder for session {} failed", id);
|
||||||
|
phsLock.close();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//successfully swapped in the session
|
||||||
|
phsLock.close();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
session.setPassivated(false);
|
ex = e; //remember a problem happened loading the session
|
||||||
session.getSessionData().copy(data);
|
LOG.warn(e);
|
||||||
session.didActivate();
|
doDelete(id); //remove the placeholder
|
||||||
|
phsLock.close();
|
||||||
|
session = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
session = null; //TODO rely on the expiry mechanism to get rid of it?
|
{
|
||||||
|
//my placeholder didn't win, check the session returned
|
||||||
|
phsLock.close();
|
||||||
|
try (Lock lock = s.lock())
|
||||||
|
{
|
||||||
|
//is it a placeholder? or is it passivated? In both cases, chuck it away and start again
|
||||||
|
if (s.isPassivated() || s instanceof PlaceHolderSession)
|
||||||
|
{
|
||||||
|
session = null;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
session = s;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//check the session returned
|
||||||
|
try (Lock lock = session.lock())
|
||||||
|
{
|
||||||
|
//is it a placeholder? or is it passivated? In both cases, chuck it away and start again
|
||||||
|
if (session.isPassivated() || session instanceof PlaceHolderSession)
|
||||||
|
{
|
||||||
|
session = null;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//got the session
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ex != null)
|
||||||
|
throw ex;
|
||||||
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the info for the session from the session data store
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* @return a Session object filled with data or null if the session doesn't exist
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private Session loadSession (String id)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
SessionData data = null;
|
||||||
|
Session session = null;
|
||||||
|
|
||||||
|
if (_sessionDataStore == null)
|
||||||
|
return null; //can't load it
|
||||||
|
|
||||||
|
data =_sessionDataStore.load(id);
|
||||||
|
|
||||||
|
if (data == null) //session doesn't exist
|
||||||
|
return null;
|
||||||
|
|
||||||
|
session = newSession(data);
|
||||||
|
session.setSessionManager(_manager);
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,12 +392,20 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
|
||||||
if (id == null || session == null)
|
if (id == null || session == null)
|
||||||
throw new IllegalArgumentException ("Put key="+id+" session="+(session==null?"null":session.getId()));
|
throw new IllegalArgumentException ("Put key="+id+" session="+(session==null?"null":session.getId()));
|
||||||
|
|
||||||
session.setSessionManager(_manager);
|
|
||||||
|
|
||||||
//if the session is new, the data has changed, or the cache is considered stale, write it to any backing store
|
//if the session is new, the data has changed, or the cache is considered stale, write it to any backing store
|
||||||
try (Lock lock = session.lock())
|
try (Lock lock = session.lock())
|
||||||
{
|
{
|
||||||
if ((session.isNew() || session.getSessionData().isDirty() || isStale(session)) && _sessionDataStore != null)
|
session.setSessionManager(_manager);
|
||||||
|
|
||||||
|
if (session.isPassivated())
|
||||||
|
throw new IllegalStateException ("Session "+id+" is passivated and cannot be saved");
|
||||||
|
|
||||||
|
if (!session.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((session.isNew() || session.getSessionData().isDirty()) && _sessionDataStore != null)
|
||||||
{
|
{
|
||||||
if (_sessionDataStore.isPassivating())
|
if (_sessionDataStore.isPassivating())
|
||||||
{
|
{
|
||||||
|
@ -322,12 +421,12 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
_sessionDataStore.store(id, session.getSessionData());
|
_sessionDataStore.store(id, session.getSessionData());
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
doPutIfAbsent(id,session);
|
doPutIfAbsent(id,session);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check to see if the session object exists in this store.
|
* Check to see if the session object exists in this store.
|
||||||
|
@ -344,60 +443,28 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
|
||||||
/**
|
/**
|
||||||
* Remove a session object from this store and from any backing store.
|
* Remove a session object from this store and from any backing store.
|
||||||
*
|
*
|
||||||
* If session has been passivated, may need to reload it before it can
|
|
||||||
* be properly deleted
|
|
||||||
*
|
*
|
||||||
* @see org.eclipse.jetty.server.session.SessionStore#delete(java.lang.String)
|
* @see org.eclipse.jetty.server.session.SessionStore#delete(java.lang.String)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Session delete(String id) throws Exception
|
public Session delete(String id) throws Exception
|
||||||
{
|
{
|
||||||
//Ensure that the session object is not passivated so that its attributes
|
//get the session, if its not in memory, this will load it
|
||||||
//are valid
|
Session session = get(id, false);
|
||||||
Session session = doGet(id);
|
|
||||||
|
|
||||||
//TODO if (session == null) do we want to load it to delete it?
|
//Always delete it from the backing data store
|
||||||
if (session != null)
|
|
||||||
{
|
|
||||||
try (Lock lock = session.lock())
|
|
||||||
{
|
|
||||||
//TODO don't check stale on deletion?
|
|
||||||
if (session.isPassivated() && _sessionDataStore != null)
|
|
||||||
{
|
|
||||||
session.setPassivated(false);
|
|
||||||
SessionData data = _sessionDataStore.load(id);
|
|
||||||
if (data != null)
|
|
||||||
{
|
|
||||||
session.getSessionData().copy(data);
|
|
||||||
session.didActivate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//Always delete it from the data store
|
|
||||||
if (_sessionDataStore != null)
|
if (_sessionDataStore != null)
|
||||||
{
|
{
|
||||||
boolean dsdel = _sessionDataStore.delete(id);
|
boolean dsdel = _sessionDataStore.delete(id);
|
||||||
if (LOG.isDebugEnabled()) LOG.debug("Session {} deleted in db {}",id, dsdel);
|
if (LOG.isDebugEnabled()) LOG.debug("Session {} deleted in db {}",id, dsdel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//delete it from the session object store
|
||||||
return doDelete(id);
|
return doDelete(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param session
|
|
||||||
* @return true or false according to the StaleStrategy
|
|
||||||
*/
|
|
||||||
public boolean isStale (Session session)
|
|
||||||
{
|
|
||||||
if (_staleStrategy != null)
|
|
||||||
return _staleStrategy.isStale(session);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -443,8 +510,8 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the SessionDataStore supports passivation, passivate any
|
* If the SessionDataStore supports passivation,
|
||||||
* sessions that have not be accessed for longer than x sec
|
* write the session to the backing data store.
|
||||||
*
|
*
|
||||||
* @param id identity of session to passivate
|
* @param id identity of session to passivate
|
||||||
*/
|
*/
|
||||||
|
@ -453,12 +520,8 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
|
||||||
if (!isStarted())
|
if (!isStarted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_sessionDataStore == null)
|
if (_sessionDataStore == null || !_sessionDataStore.isPassivating())
|
||||||
return; //no data store to passivate
|
return; //no data store to passivate or it doesn't passivate
|
||||||
|
|
||||||
if (!_sessionDataStore.isPassivating())
|
|
||||||
return; //doesn't support passivation
|
|
||||||
|
|
||||||
|
|
||||||
//get the session locally
|
//get the session locally
|
||||||
Session s = doGet(id);
|
Session s = doGet(id);
|
||||||
|
@ -470,23 +533,35 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//lock the session during passivation
|
||||||
try (Lock lock = s.lock())
|
try (Lock lock = s.lock())
|
||||||
{
|
{
|
||||||
//check the session is still idle first
|
//check the session is still idle and that it doesn't have requests using it
|
||||||
if (s.isValid() && s.isIdleLongerThan(_idlePassivationTimeoutSec))
|
if (s.isValid() && s.isIdleLongerThan(_idlePassivationTimeoutSec) && s.isActive() && (s.getRequests() <= 0))
|
||||||
{
|
{
|
||||||
|
//TODO - do we need to check that the session exists in the session data store
|
||||||
|
//before we passivate it? If it doesn't exist, we can assume another node
|
||||||
|
//invalidated it. If the session was new, it shouldn't have been idle passivated.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (LOG.isDebugEnabled())
|
||||||
|
LOG.debug("Passivating idle session {}", id);
|
||||||
s.willPassivate();
|
s.willPassivate();
|
||||||
_sessionDataStore.store(id, s.getSessionData());
|
_sessionDataStore.store(id, s.getSessionData());
|
||||||
s.getSessionData().clearAllAttributes();
|
|
||||||
s.getSessionData().setDirty(false);
|
s.getSessionData().setDirty(false);
|
||||||
}
|
s.setPassivated();
|
||||||
|
doDelete(id); //Take the session object of this session store
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
LOG.warn("Passivation of idle session {} failed", id, e);
|
LOG.warn("Passivation of idle session {} failed", id, e);
|
||||||
// TODO should do session.invalidate(); ???
|
s.setPassivated(); //set it as passivated so it can't be used
|
||||||
|
doDelete(id); //detach it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -27,13 +27,20 @@ package org.eclipse.jetty.server.session;
|
||||||
*/
|
*/
|
||||||
public class FileSessionManager extends SessionManager
|
public class FileSessionManager extends SessionManager
|
||||||
{
|
{
|
||||||
protected FileSessionDataStore _sessionDataStore = new FileSessionDataStore();
|
protected FileSessionDataStore _sessionDataStore;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public FileSessionManager ()
|
||||||
|
{
|
||||||
|
_sessionStore = new MemorySessionStore();
|
||||||
|
_sessionDataStore = new FileSessionDataStore();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doStart() throws Exception
|
public void doStart() throws Exception
|
||||||
{
|
{
|
||||||
_sessionStore = new MemorySessionStore();
|
|
||||||
((AbstractSessionStore)_sessionStore).setSessionDataStore(_sessionDataStore);
|
((AbstractSessionStore)_sessionStore).setSessionDataStore(_sessionDataStore);
|
||||||
|
|
||||||
super.doStart();
|
super.doStart();
|
||||||
|
|
|
@ -81,6 +81,8 @@ public class IdleInspector implements SessionInspector
|
||||||
public void preInspection()
|
public void preInspection()
|
||||||
{
|
{
|
||||||
_idleCandidates = new HashSet<String>();
|
_idleCandidates = new HashSet<String>();
|
||||||
|
if (LOG.isDebugEnabled())
|
||||||
|
LOG.debug("IdleInspector preinspection");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,6 +93,9 @@ public class IdleInspector implements SessionInspector
|
||||||
@Override
|
@Override
|
||||||
public void postInspection()
|
public void postInspection()
|
||||||
{
|
{
|
||||||
|
if (LOG.isDebugEnabled())
|
||||||
|
LOG.debug("IdleInspector postinspection");
|
||||||
|
|
||||||
for (String id:_idleCandidates)
|
for (String id:_idleCandidates)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
@ -717,7 +717,6 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
|
||||||
|
|
||||||
//ensure this runs with context classloader set
|
//ensure this runs with context classloader set
|
||||||
_context.run(r);
|
_context.run(r);
|
||||||
|
|
||||||
if (exception.get() != null)
|
if (exception.get() != null)
|
||||||
throw exception.get();
|
throw exception.get();
|
||||||
|
|
||||||
|
|
|
@ -124,7 +124,7 @@ public class MemorySessionStore extends AbstractSessionStore
|
||||||
public Session doPutIfAbsent(String id, Session session)
|
public Session doPutIfAbsent(String id, Session session)
|
||||||
{
|
{
|
||||||
Session s = _sessions.putIfAbsent(id, session);
|
Session s = _sessions.putIfAbsent(id, session);
|
||||||
if (s == null)
|
if (s == null && !(session instanceof PlaceHolderSession))
|
||||||
_stats.increment();
|
_stats.increment();
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
@ -145,32 +145,12 @@ public class MemorySessionStore extends AbstractSessionStore
|
||||||
public Session doDelete(String id)
|
public Session doDelete(String id)
|
||||||
{
|
{
|
||||||
Session s = _sessions.remove(id);
|
Session s = _sessions.remove(id);
|
||||||
if (s != null)
|
if (s != null && !(s instanceof PlaceHolderSession))
|
||||||
_stats.decrement();
|
_stats.decrement();
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> doGetExpiredCandidates()
|
|
||||||
{
|
|
||||||
Set<String> candidates = new HashSet<String>();
|
|
||||||
long now = System.currentTimeMillis();
|
|
||||||
|
|
||||||
for (Session s:_sessions.values())
|
|
||||||
{
|
|
||||||
if (s.isExpiredAt(now))
|
|
||||||
{
|
|
||||||
candidates.add(s.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return candidates;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -253,4 +233,17 @@ public class MemorySessionStore extends AbstractSessionStore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.eclipse.jetty.server.session.AbstractSessionStore#doReplace(java.lang.String, org.eclipse.jetty.server.session.Session, org.eclipse.jetty.server.session.Session)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean doReplace(String id, Session oldValue, Session newValue)
|
||||||
|
{
|
||||||
|
boolean result = _sessions.replace(id, oldValue, newValue);
|
||||||
|
if (result && (oldValue instanceof PlaceHolderSession))
|
||||||
|
_stats.increment();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,12 +51,28 @@ public class Session implements SessionManager.SessionIf
|
||||||
private final static Logger LOG = Log.getLogger("org.eclipse.jetty.server.session");
|
private final static Logger LOG = Log.getLogger("org.eclipse.jetty.server.session");
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
public final static String SESSION_CREATED_SECURE="org.eclipse.jetty.security.sessionCreatedSecure";
|
public final static String SESSION_CREATED_SECURE="org.eclipse.jetty.security.sessionCreatedSecure";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* State
|
||||||
|
*
|
||||||
|
* Validity states of a session
|
||||||
|
*/
|
||||||
public enum State {VALID, INVALID, INVALIDATING};
|
public enum State {VALID, INVALID, INVALIDATING};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PassivationState
|
||||||
|
*
|
||||||
|
* States of a session - either active in memory or passivated to persistent store
|
||||||
|
*/
|
||||||
|
public enum PassivationState {PASSIVATED, ACTIVE};
|
||||||
|
|
||||||
|
|
||||||
protected SessionData _sessionData;
|
protected SessionData _sessionData;
|
||||||
protected SessionManager _manager;
|
protected SessionManager _manager;
|
||||||
protected String _extendedId; //the _id plus the worker name
|
protected String _extendedId; //the _id plus the worker name
|
||||||
|
@ -66,24 +82,52 @@ public class Session implements SessionManager.SessionIf
|
||||||
private State _state = State.VALID; //state of the session:valid,invalid or being invalidated
|
private State _state = State.VALID; //state of the session:valid,invalid or being invalidated
|
||||||
private Locker _lock = new Locker();
|
private Locker _lock = new Locker();
|
||||||
|
|
||||||
|
private PassivationState _passivationState = PassivationState.ACTIVE;
|
||||||
|
|
||||||
private boolean _isPassivated;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new session
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
public Session (HttpServletRequest request, SessionData data)
|
public Session (HttpServletRequest request, SessionData data)
|
||||||
{
|
{
|
||||||
_sessionData = data;
|
_sessionData = data;
|
||||||
_newSession = true;
|
_newSession = true;
|
||||||
_requests = 1;
|
_requests = 1; //access will not be called on this new session, but we are obviously in a request
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Re-create an existing session
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
public Session (SessionData data)
|
public Session (SessionData data)
|
||||||
{
|
{
|
||||||
_sessionData = data;
|
_sessionData = data;
|
||||||
_requests = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should call this method with a lock held if you want to
|
||||||
|
* make decision on what to do with the session
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public long getRequests()
|
||||||
|
{
|
||||||
|
try (Lock lock = _lock.lockIfNotHeld())
|
||||||
|
{
|
||||||
|
return _requests;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void setSessionManager (SessionManager manager)
|
public void setSessionManager (SessionManager manager)
|
||||||
{
|
{
|
||||||
_manager = manager;
|
_manager = manager;
|
||||||
|
@ -98,7 +142,7 @@ public class Session implements SessionManager.SessionIf
|
||||||
/* ------------------------------------------------------------- */
|
/* ------------------------------------------------------------- */
|
||||||
protected void cookieSet()
|
protected void cookieSet()
|
||||||
{
|
{
|
||||||
try (Lock lock = lock())
|
try (Lock lock = _lock.lockIfNotHeld())
|
||||||
{
|
{
|
||||||
_sessionData.setCookieSet(_sessionData.getAccessed());
|
_sessionData.setCookieSet(_sessionData.getAccessed());
|
||||||
}
|
}
|
||||||
|
@ -106,7 +150,7 @@ public class Session implements SessionManager.SessionIf
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
protected boolean access(long time)
|
protected boolean access(long time)
|
||||||
{
|
{
|
||||||
try (Lock lock=lock())
|
try (Lock lock = _lock.lockIfNotHeld())
|
||||||
{
|
{
|
||||||
if (!isValid())
|
if (!isValid())
|
||||||
return false;
|
return false;
|
||||||
|
@ -129,7 +173,7 @@ public class Session implements SessionManager.SessionIf
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
protected void complete()
|
protected void complete()
|
||||||
{
|
{
|
||||||
try (Lock lock = lock())
|
try (Lock lock = _lock.lockIfNotHeld())
|
||||||
{
|
{
|
||||||
_requests--;
|
_requests--;
|
||||||
}
|
}
|
||||||
|
@ -363,7 +407,7 @@ public class Session implements SessionManager.SessionIf
|
||||||
@Override
|
@Override
|
||||||
public void setMaxInactiveInterval(int secs)
|
public void setMaxInactiveInterval(int secs)
|
||||||
{
|
{
|
||||||
try (Lock lock = lock())
|
try (Lock lock = _lock.lockIfNotHeld())
|
||||||
{
|
{
|
||||||
_sessionData.setMaxInactiveMs((long)secs*1000L);
|
_sessionData.setMaxInactiveMs((long)secs*1000L);
|
||||||
_sessionData.setExpiry(_sessionData.getMaxInactiveMs() <= 0 ? 0 : (System.currentTimeMillis() + _sessionData.getMaxInactiveMs()*1000L));
|
_sessionData.setExpiry(_sessionData.getMaxInactiveMs() <= 0 ? 0 : (System.currentTimeMillis() + _sessionData.getMaxInactiveMs()*1000L));
|
||||||
|
@ -407,11 +451,13 @@ public class Session implements SessionManager.SessionIf
|
||||||
*/
|
*/
|
||||||
protected void checkValidForWrite() throws IllegalStateException
|
protected void checkValidForWrite() throws IllegalStateException
|
||||||
{
|
{
|
||||||
if (!_lock.isLocked())
|
checkLocked();
|
||||||
throw new IllegalStateException();
|
|
||||||
|
|
||||||
if (_state != State.VALID)
|
if (_state != State.VALID)
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
|
|
||||||
|
if (_passivationState == PassivationState.PASSIVATED)
|
||||||
|
throw new IllegalStateException("Passivated");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -422,14 +468,26 @@ public class Session implements SessionManager.SessionIf
|
||||||
*/
|
*/
|
||||||
protected void checkValidForRead () throws IllegalStateException
|
protected void checkValidForRead () throws IllegalStateException
|
||||||
{
|
{
|
||||||
if (!_lock.isLocked())
|
checkLocked();
|
||||||
throw new IllegalStateException();
|
|
||||||
if (_state == State.INVALID)
|
if (_state == State.INVALID)
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException("Invalid");
|
||||||
|
|
||||||
|
if (_passivationState == PassivationState.PASSIVATED)
|
||||||
|
throw new IllegalStateException("Passivated");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------- */
|
||||||
|
/**
|
||||||
|
* @throws IllegalStateException
|
||||||
|
*/
|
||||||
|
protected void checkLocked ()
|
||||||
|
throws IllegalStateException
|
||||||
|
{
|
||||||
|
if (!_lock.isLocked())
|
||||||
|
throw new IllegalStateException("Session not locked");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see javax.servlet.http.HttpSession#getAttribute(java.lang.String)
|
* @see javax.servlet.http.HttpSession#getAttribute(java.lang.String)
|
||||||
|
@ -750,7 +808,7 @@ public class Session implements SessionManager.SessionIf
|
||||||
/* ------------------------------------------------------------- */
|
/* ------------------------------------------------------------- */
|
||||||
public void setIdChanged(boolean changed)
|
public void setIdChanged(boolean changed)
|
||||||
{
|
{
|
||||||
try (Lock lock = lock())
|
try (Lock lock = _lock.lockIfNotHeld())
|
||||||
{
|
{
|
||||||
_idChanged=changed;
|
_idChanged=changed;
|
||||||
}
|
}
|
||||||
|
@ -785,24 +843,45 @@ public class Session implements SessionManager.SessionIf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------- */
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void setPassivated ()
|
||||||
|
{
|
||||||
|
checkLocked();
|
||||||
|
_passivationState = PassivationState.PASSIVATED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void setActive ()
|
||||||
|
{
|
||||||
|
checkLocked();
|
||||||
|
_passivationState = PassivationState.ACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean isActive ()
|
||||||
|
{
|
||||||
|
checkLocked();
|
||||||
|
return _passivationState == PassivationState.ACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public boolean isPassivated ()
|
public boolean isPassivated ()
|
||||||
{
|
{
|
||||||
return _isPassivated;
|
checkLocked();
|
||||||
|
return _passivationState == PassivationState.PASSIVATED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------- */
|
|
||||||
/**
|
|
||||||
* @param isPassivated
|
|
||||||
*/
|
|
||||||
public void setPassivated(boolean isPassivated)
|
|
||||||
{
|
|
||||||
_isPassivated = isPassivated;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ import org.eclipse.jetty.util.log.Log;
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
import org.eclipse.jetty.util.statistic.CounterStatistic;
|
import org.eclipse.jetty.util.statistic.CounterStatistic;
|
||||||
import org.eclipse.jetty.util.statistic.SampleStatistic;
|
import org.eclipse.jetty.util.statistic.SampleStatistic;
|
||||||
|
import org.eclipse.jetty.util.thread.Locker.Lock;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -221,10 +222,10 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je
|
||||||
public void complete(HttpSession session)
|
public void complete(HttpSession session)
|
||||||
{
|
{
|
||||||
Session s = ((SessionIf)session).getSession();
|
Session s = ((SessionIf)session).getSession();
|
||||||
s.complete();
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (s.isValid())
|
s.complete();
|
||||||
_sessionStore.put(s.getId(), s);
|
_sessionStore.put(s.getId(), s);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
@ -574,6 +575,7 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je
|
||||||
@Override
|
@Override
|
||||||
public HttpSession newHttpSession(HttpServletRequest request)
|
public HttpSession newHttpSession(HttpServletRequest request)
|
||||||
{
|
{
|
||||||
|
|
||||||
long created=System.currentTimeMillis();
|
long created=System.currentTimeMillis();
|
||||||
String id =_sessionIdManager.newSessionId(request,created);
|
String id =_sessionIdManager.newSessionId(request,created);
|
||||||
Session session = _sessionStore.newSession(request, id, created, (_dftMaxIdleSecs>0?_dftMaxIdleSecs*1000L:-1));
|
Session session = _sessionStore.newSession(request, id, created, (_dftMaxIdleSecs>0?_dftMaxIdleSecs*1000L:-1));
|
||||||
|
@ -583,7 +585,6 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je
|
||||||
session.getSessionData().setExpiry(_dftMaxIdleSecs <= 0 ? 0 : (created + _dftMaxIdleSecs*1000L));
|
session.getSessionData().setExpiry(_dftMaxIdleSecs <= 0 ? 0 : (created + _dftMaxIdleSecs*1000L));
|
||||||
if (request.isSecure())
|
if (request.isSecure())
|
||||||
session.setAttribute(Session.SESSION_CREATED_SECURE, Boolean.TRUE);
|
session.setAttribute(Session.SESSION_CREATED_SECURE, Boolean.TRUE);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_sessionStore.put(id, session);
|
_sessionStore.put(id, session);
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.server.handler;
|
package org.eclipse.jetty.server.handler;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.is;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
@ -38,7 +36,9 @@ import org.junit.BeforeClass;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@Ignore("Unfixed range bug")
|
import static org.hamcrest.Matchers.is;
|
||||||
|
|
||||||
|
@Ignore("Unfixed range bug - Issue #107")
|
||||||
public class ResourceHandlerRangeTest
|
public class ResourceHandlerRangeTest
|
||||||
{
|
{
|
||||||
private static Server server;
|
private static Server server;
|
||||||
|
|
|
@ -123,6 +123,16 @@ public class SessionCookieTest
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.eclipse.jetty.server.session.AbstractSessionStore#doReplace(java.lang.String, org.eclipse.jetty.server.session.Session, org.eclipse.jetty.server.session.Session)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean doReplace(String id, Session oldValue, Session newValue)
|
||||||
|
{
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1113,6 +1113,8 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
|
||||||
code=Integer.valueOf(error);
|
code=Integer.valueOf(error);
|
||||||
|
|
||||||
String location = node.getString("location", false, true);
|
String location = node.getString("location", false, true);
|
||||||
|
if (!location.startsWith("/"))
|
||||||
|
throw new IllegalStateException("Missing leading '/' for location: " + location);
|
||||||
ErrorPageErrorHandler handler = (ErrorPageErrorHandler)context.getErrorHandler();
|
ErrorPageErrorHandler handler = (ErrorPageErrorHandler)context.getErrorHandler();
|
||||||
String originName = "error."+error;
|
String originName = "error."+error;
|
||||||
switch (context.getMetaData().getOrigin(originName))
|
switch (context.getMetaData().getOrigin(originName))
|
||||||
|
|
|
@ -18,6 +18,11 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.server.session;
|
package org.eclipse.jetty.server.session;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
import org.eclipse.jetty.server.SessionIdManager;
|
import org.eclipse.jetty.server.SessionIdManager;
|
||||||
|
@ -50,6 +55,70 @@ public class FileTestServer extends AbstractTestServer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void assertStoreDirEmpty (boolean isEmpty)
|
||||||
|
{
|
||||||
|
assertNotNull(_tmpDir);
|
||||||
|
assertTrue(_tmpDir.exists());
|
||||||
|
String[] files = _tmpDir.list();
|
||||||
|
if (isEmpty)
|
||||||
|
{
|
||||||
|
if (files != null)
|
||||||
|
assertEquals(0, files.length);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assertNotNull(files);
|
||||||
|
assertFalse(files.length==0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void assertFileExists (String sessionId, boolean exists)
|
||||||
|
{
|
||||||
|
assertNotNull(_tmpDir);
|
||||||
|
assertTrue(_tmpDir.exists());
|
||||||
|
String[] files = _tmpDir.list();
|
||||||
|
assertNotNull(files);
|
||||||
|
assertFalse(files.length == 0);
|
||||||
|
boolean found = false;
|
||||||
|
for (String name:files)
|
||||||
|
{
|
||||||
|
if (name.contains(sessionId))
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (exists)
|
||||||
|
assertTrue(found);
|
||||||
|
else
|
||||||
|
assertFalse(found);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void deleteFile (String sessionId)
|
||||||
|
{
|
||||||
|
assertNotNull(_tmpDir);
|
||||||
|
assertTrue(_tmpDir.exists());
|
||||||
|
String[] files = _tmpDir.list();
|
||||||
|
assertNotNull(files);
|
||||||
|
assertFalse(files.length == 0);
|
||||||
|
String filename = null;
|
||||||
|
for (String name:files)
|
||||||
|
{
|
||||||
|
if (name.contains(sessionId))
|
||||||
|
{
|
||||||
|
filename = name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (filename != null)
|
||||||
|
{
|
||||||
|
File f = new File (_tmpDir, filename);
|
||||||
|
assertTrue(f.delete());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public FileTestServer(int port)
|
public FileTestServer(int port)
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2016 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.server.session;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.server.SessionManager;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IdleSessionTest
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class IdleSessionTest extends AbstractIdleSessionTest
|
||||||
|
{
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void before() throws Exception
|
||||||
|
{
|
||||||
|
FileTestServer.setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void after()
|
||||||
|
{
|
||||||
|
FileTestServer.teardown();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.eclipse.jetty.server.session.AbstractIdleSessionTest#createServer(int, int, int, int)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public AbstractTestServer createServer(final int port, final int max, final int scavenge, final int idleSec)
|
||||||
|
{
|
||||||
|
FileTestServer server = new FileTestServer(port,max,scavenge)
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.eclipse.jetty.server.session.FileTestServer#newSessionManager()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public SessionManager newSessionManager()
|
||||||
|
{
|
||||||
|
FileSessionManager manager = (FileSessionManager)super.newSessionManager();
|
||||||
|
manager.getSessionStore().setIdlePassivationTimeoutSec(idleSec);
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.eclipse.jetty.server.session.AbstractIdleSessionTest#checkSessionIdled(java.lang.String)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void checkSessionIdled(String sessionId)
|
||||||
|
{
|
||||||
|
FileTestServer.assertStoreDirEmpty(false);
|
||||||
|
FileTestServer.assertFileExists(sessionId, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.eclipse.jetty.server.session.AbstractIdleSessionTest#checkSessionDeIdled(java.lang.String)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void checkSessionDeIdled(String sessionId)
|
||||||
|
{
|
||||||
|
//Can't check absence of file to indicate session is de-idled
|
||||||
|
//because the FileSessionStore writes out the session to a file if anything changes.
|
||||||
|
//The test changes an attribute so the file will probably exist.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.eclipse.jetty.server.session.AbstractIdleSessionTest#deleteSessionData(java.lang.String)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void deleteSessionData(String sessionId)
|
||||||
|
{
|
||||||
|
FileTestServer.deleteFile(sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -37,7 +37,6 @@ import com.google.gcloud.datastore.DatastoreFactory;
|
||||||
public class GCloudTestServer extends AbstractTestServer
|
public class GCloudTestServer extends AbstractTestServer
|
||||||
{
|
{
|
||||||
static int __workers=0;
|
static int __workers=0;
|
||||||
public static int STALE_INTERVAL_SEC = 1;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -82,9 +81,6 @@ public class GCloudTestServer extends AbstractTestServer
|
||||||
GCloudSessionManager sessionManager = new GCloudSessionManager();
|
GCloudSessionManager sessionManager = new GCloudSessionManager();
|
||||||
sessionManager.setSessionIdManager((GCloudSessionIdManager)_sessionIdManager);
|
sessionManager.setSessionIdManager((GCloudSessionIdManager)_sessionIdManager);
|
||||||
sessionManager.getSessionDataStore().setGCloudConfiguration(((GCloudSessionIdManager)_sessionIdManager).getConfig());
|
sessionManager.getSessionDataStore().setGCloudConfiguration(((GCloudSessionIdManager)_sessionIdManager).getConfig());
|
||||||
StalePeriodStrategy staleStrategy = new StalePeriodStrategy();
|
|
||||||
staleStrategy.setStaleSec(STALE_INTERVAL_SEC);
|
|
||||||
((AbstractSessionStore)sessionManager.getSessionStore()).setStaleStrategy(staleStrategy);
|
|
||||||
return sessionManager;
|
return sessionManager;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,12 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.gcloud.session;
|
package org.eclipse.jetty.gcloud.session;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.server.SessionManager;
|
||||||
import org.eclipse.jetty.server.session.AbstractInvalidationSessionTest;
|
import org.eclipse.jetty.server.session.AbstractInvalidationSessionTest;
|
||||||
import org.eclipse.jetty.server.session.AbstractTestServer;
|
import org.eclipse.jetty.server.session.AbstractTestServer;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Ignore;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* InvalidationSessionTest
|
* InvalidationSessionTest
|
||||||
|
@ -32,6 +34,7 @@ import org.junit.BeforeClass;
|
||||||
public class InvalidationSessionTest extends AbstractInvalidationSessionTest
|
public class InvalidationSessionTest extends AbstractInvalidationSessionTest
|
||||||
{
|
{
|
||||||
static GCloudSessionTestSupport _testSupport;
|
static GCloudSessionTestSupport _testSupport;
|
||||||
|
public static final int IDLE_PASSIVATE_SEC = 3;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void setup () throws Exception
|
public static void setup () throws Exception
|
||||||
|
@ -50,9 +53,23 @@ public class InvalidationSessionTest extends AbstractInvalidationSessionTest
|
||||||
* @see org.eclipse.jetty.server.session.AbstractInvalidationSessionTest#createServer(int)
|
* @see org.eclipse.jetty.server.session.AbstractInvalidationSessionTest#createServer(int)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public AbstractTestServer createServer(int port)
|
public AbstractTestServer createServer(int port, int maxInactive, int inspectInterval)
|
||||||
{
|
{
|
||||||
return new GCloudTestServer(port, _testSupport.getConfiguration());
|
GCloudTestServer server = new GCloudTestServer(port, maxInactive, inspectInterval, _testSupport.getConfiguration())
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @see org.eclipse.jetty.gcloud.session.GCloudTestServer#newSessionManager()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public SessionManager newSessionManager()
|
||||||
|
{
|
||||||
|
GCloudSessionManager manager = (GCloudSessionManager)super.newSessionManager();
|
||||||
|
manager.getSessionStore().setIdlePassivationTimeoutSec(IDLE_PASSIVATE_SEC);
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
return server;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -66,7 +83,7 @@ public class InvalidationSessionTest extends AbstractInvalidationSessionTest
|
||||||
//has expired on node2 for it to reload the session and discover it has been deleted.
|
//has expired on node2 for it to reload the session and discover it has been deleted.
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Thread.currentThread().sleep((2*GCloudTestServer.STALE_INTERVAL_SEC)*1000);
|
Thread.currentThread().sleep((2*IDLE_PASSIVATE_SEC)*1000);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -75,4 +92,17 @@ public class InvalidationSessionTest extends AbstractInvalidationSessionTest
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.eclipse.jetty.server.session.AbstractInvalidationSessionTest#testInvalidation()
|
||||||
|
*/
|
||||||
|
@Ignore
|
||||||
|
@Override
|
||||||
|
public void testInvalidation() throws Exception
|
||||||
|
{
|
||||||
|
// Ignore
|
||||||
|
//super.testInvalidation();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,8 @@ import org.junit.AfterClass;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.junit.Assert;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SessionExpiryTest
|
* SessionExpiryTest
|
||||||
|
@ -76,21 +78,21 @@ public class SessionExpiryTest extends AbstractSessionExpiryTest
|
||||||
public void testSessionExpiry() throws Exception
|
public void testSessionExpiry() throws Exception
|
||||||
{
|
{
|
||||||
super.testSessionExpiry();
|
super.testSessionExpiry();
|
||||||
_testSupport.assertSessions(0);
|
try{_testSupport.assertSessions(0);}catch(Exception e){ Assert.fail(e.getMessage());}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void verifySessionCreated(TestHttpSessionListener listener, String sessionId)
|
public void verifySessionCreated(TestHttpSessionListener listener, String sessionId)
|
||||||
{
|
{
|
||||||
super.verifySessionCreated(listener, sessionId);
|
super.verifySessionCreated(listener, sessionId);
|
||||||
try{ _testSupport.listSessions(); _testSupport.assertSessions(1);}catch(Exception e) {e.printStackTrace();}
|
try {_testSupport.assertSessions(1);}catch(Exception e){ Assert.fail(e.getMessage());}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void verifySessionDestroyed(TestHttpSessionListener listener, String sessionId)
|
public void verifySessionDestroyed(TestHttpSessionListener listener, String sessionId)
|
||||||
{
|
{
|
||||||
super.verifySessionDestroyed(listener, sessionId);
|
super.verifySessionDestroyed(listener, sessionId);
|
||||||
try{ _testSupport.listSessions(); _testSupport.assertSessions(0);}catch(Exception e) {e.printStackTrace();}
|
try{_testSupport.assertSessions(0);}catch(Exception e){ Assert.fail(e.getMessage());}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@ -40,6 +41,7 @@ import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
import org.eclipse.jetty.util.IO;
|
import org.eclipse.jetty.util.IO;
|
||||||
import org.eclipse.jetty.util.log.Log;
|
import org.eclipse.jetty.util.log.Log;
|
||||||
import org.eclipse.jetty.util.log.StdErrLog;
|
import org.eclipse.jetty.util.log.StdErrLog;
|
||||||
|
import org.eclipse.jetty.util.thread.Locker.Lock;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,7 +50,7 @@ import org.junit.Test;
|
||||||
*
|
*
|
||||||
* Checks that a session can be idled and de-idled on the next request if it hasn't expired.
|
* Checks that a session can be idled and de-idled on the next request if it hasn't expired.
|
||||||
*
|
*
|
||||||
* TODO support session idling in FileSessionDataStore?
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class IdleSessionTest
|
public class IdleSessionTest
|
||||||
|
@ -69,9 +71,9 @@ public class IdleSessionTest
|
||||||
@Override
|
@Override
|
||||||
public SessionManager newSessionManager()
|
public SessionManager newSessionManager()
|
||||||
{
|
{
|
||||||
HashSessionManager manager = (HashSessionManager)super.newSessionManager();
|
FileSessionManager manager = new FileSessionManager();
|
||||||
//manager.getSessionDataStore().setStoreDir(_storeDir);
|
manager.getSessionStore().setIdlePassivationTimeoutSec(_idlePeriod);
|
||||||
//manager.setIdleSavePeriod(_idlePeriod);
|
manager.getSessionDataStore().setStoreDir(_storeDir);
|
||||||
return manager;
|
return manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,6 +100,7 @@ public class IdleSessionTest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testSessionIdle() throws Exception
|
public void testSessionIdle() throws Exception
|
||||||
{
|
{
|
||||||
String contextPath = "";
|
String contextPath = "";
|
||||||
|
@ -136,7 +139,7 @@ public class IdleSessionTest
|
||||||
pause(idlePeriod * 2);
|
pause(idlePeriod * 2);
|
||||||
|
|
||||||
//check that the file exists
|
//check that the file exists
|
||||||
checkSessionIdled(storeDir, getSessionId(sessionCookie));
|
checkSessionIdled(storeDir, HashTestServer.extractSessionId(sessionCookie));
|
||||||
|
|
||||||
//make another request to de-idle the session
|
//make another request to de-idle the session
|
||||||
Request request = client.newRequest(url + "?action=test");
|
Request request = client.newRequest(url + "?action=test");
|
||||||
|
@ -151,11 +154,11 @@ public class IdleSessionTest
|
||||||
pause(idlePeriod * 2);
|
pause(idlePeriod * 2);
|
||||||
|
|
||||||
//check that it is
|
//check that it is
|
||||||
checkSessionIdled(storeDir, getSessionId(sessionCookie));
|
checkSessionIdled(storeDir, HashTestServer.extractSessionId(sessionCookie));
|
||||||
|
|
||||||
|
|
||||||
//delete the file
|
//delete the file
|
||||||
File idleFile = getIdleFile(storeDir, getSessionId(sessionCookie));
|
File idleFile = getIdleFile(storeDir, HashTestServer.extractSessionId(sessionCookie));
|
||||||
assertTrue(idleFile.exists());
|
assertTrue(idleFile.exists());
|
||||||
assertTrue(idleFile.delete());
|
assertTrue(idleFile.delete());
|
||||||
|
|
||||||
|
@ -173,6 +176,10 @@ public class IdleSessionTest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param sessionDir
|
||||||
|
* @param sessionId
|
||||||
|
*/
|
||||||
public void checkSessionIdled (File sessionDir, String sessionId)
|
public void checkSessionIdled (File sessionDir, String sessionId)
|
||||||
{
|
{
|
||||||
assertNotNull(sessionDir);
|
assertNotNull(sessionDir);
|
||||||
|
@ -180,10 +187,13 @@ public class IdleSessionTest
|
||||||
String[] files = sessionDir.list();
|
String[] files = sessionDir.list();
|
||||||
assertNotNull(files);
|
assertNotNull(files);
|
||||||
assertEquals(1, files.length);
|
assertEquals(1, files.length);
|
||||||
assertEquals(sessionId, files[0]);
|
assertTrue(files[0].contains(sessionId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param sessionDir
|
||||||
|
*/
|
||||||
public void checkSessionDeIdled (File sessionDir)
|
public void checkSessionDeIdled (File sessionDir)
|
||||||
{
|
{
|
||||||
assertNotNull(sessionDir);
|
assertNotNull(sessionDir);
|
||||||
|
@ -193,6 +203,11 @@ public class IdleSessionTest
|
||||||
assertEquals(0, files.length);
|
assertEquals(0, files.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param sessionDir
|
||||||
|
* @param sessionId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public File getIdleFile (File sessionDir, String sessionId)
|
public File getIdleFile (File sessionDir, String sessionId)
|
||||||
{
|
{
|
||||||
assertNotNull(sessionDir);
|
assertNotNull(sessionDir);
|
||||||
|
@ -202,13 +217,6 @@ public class IdleSessionTest
|
||||||
return new File(sessionDir, files[0]);
|
return new File(sessionDir, files[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSessionId (String sessionCookie)
|
|
||||||
{
|
|
||||||
assertNotNull(sessionCookie);
|
|
||||||
String sessionId = sessionCookie.substring(11);
|
|
||||||
sessionId = sessionId.substring(0, sessionId.indexOf(';'));
|
|
||||||
return sessionId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class TestServlet extends HttpServlet
|
public static class TestServlet extends HttpServlet
|
||||||
{
|
{
|
||||||
|
@ -223,7 +231,11 @@ public class IdleSessionTest
|
||||||
HttpSession session = request.getSession(true);
|
HttpSession session = request.getSession(true);
|
||||||
session.setAttribute("test", "test");
|
session.setAttribute("test", "test");
|
||||||
originalId = session.getId();
|
originalId = session.getId();
|
||||||
// assertTrue(!((HashedSession)session).isIdled());
|
Session s = (Session)session;
|
||||||
|
try (Lock lock = s.lock())
|
||||||
|
{
|
||||||
|
assertTrue(!s.isPassivated());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if ("test".equals(action))
|
else if ("test".equals(action))
|
||||||
{
|
{
|
||||||
|
@ -231,7 +243,6 @@ public class IdleSessionTest
|
||||||
assertTrue(session != null);
|
assertTrue(session != null);
|
||||||
assertTrue(originalId.equals(session.getId()));
|
assertTrue(originalId.equals(session.getId()));
|
||||||
assertEquals("test", session.getAttribute("test"));
|
assertEquals("test", session.getAttribute("test"));
|
||||||
// assertTrue(!((HashedSession)session).isIdled());
|
|
||||||
}
|
}
|
||||||
else if ("testfail".equals(action))
|
else if ("testfail".equals(action))
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2016 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.server.session;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* OrphanedSessionTest
|
|
||||||
*/
|
|
||||||
public class OrphanedSessionTest extends AbstractOrphanedSessionTest
|
|
||||||
{
|
|
||||||
public AbstractTestServer createServer(int port, int max, int scavenge)
|
|
||||||
{
|
|
||||||
return new HashTestServer(port,max,scavenge);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOrphanedSession() throws Exception
|
|
||||||
{
|
|
||||||
super.testOrphanedSession();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -65,9 +65,6 @@ public class InfinispanTestSessionServer extends AbstractTestServer
|
||||||
InfinispanSessionManager sessionManager = new InfinispanSessionManager();
|
InfinispanSessionManager sessionManager = new InfinispanSessionManager();
|
||||||
sessionManager.setSessionIdManager((InfinispanSessionIdManager)_sessionIdManager);
|
sessionManager.setSessionIdManager((InfinispanSessionIdManager)_sessionIdManager);
|
||||||
sessionManager.getSessionDataStore().setCache(((InfinispanSessionIdManager)_sessionIdManager).getCache());
|
sessionManager.getSessionDataStore().setCache(((InfinispanSessionIdManager)_sessionIdManager).getCache());
|
||||||
StalePeriodStrategy staleStrategy = new StalePeriodStrategy();
|
|
||||||
staleStrategy.setStaleSec(1);
|
|
||||||
((AbstractSessionStore)sessionManager.getSessionStore()).setStaleStrategy(staleStrategy);
|
|
||||||
return sessionManager;
|
return sessionManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,91 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2016 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.server.session;
|
|
||||||
|
|
||||||
import org.junit.AfterClass;
|
|
||||||
import org.junit.BeforeClass;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* InvalidationSessionTest
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class InvalidationSessionTest extends AbstractInvalidationSessionTest
|
|
||||||
{
|
|
||||||
|
|
||||||
public static InfinispanTestSupport __testSupport;
|
|
||||||
public static long __staleSec = 3L;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@BeforeClass
|
|
||||||
public static void setup () throws Exception
|
|
||||||
{
|
|
||||||
__testSupport = new InfinispanTestSupport();
|
|
||||||
__testSupport.setup();
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterClass
|
|
||||||
public static void teardown () throws Exception
|
|
||||||
{
|
|
||||||
__testSupport.teardown();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see org.eclipse.jetty.server.session.AbstractInvalidationSessionTest#createServer(int)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public AbstractTestServer createServer(int port)
|
|
||||||
{
|
|
||||||
return new InfinispanTestSessionServer(port, __testSupport.getCache());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void testInvalidation() throws Exception
|
|
||||||
{
|
|
||||||
super.testInvalidation();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see org.eclipse.jetty.server.session.AbstractInvalidationSessionTest#pause()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void pause()
|
|
||||||
{
|
|
||||||
//This test moves a session from node 1 to node 2, then invalidates the session back on node1. This
|
|
||||||
//should never happen with a decent load balancer.
|
|
||||||
//The infinispan session manager on node 2 will hold the session in local memory for a specific (configurable)
|
|
||||||
//amount of time. We've set the stale session time to 3 sec, so we need to pause for at least this long before making
|
|
||||||
//another request to node2
|
|
||||||
|
|
||||||
//that the node will re-load the session from the database and discover that it has gone.
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Thread.sleep(2 * __staleSec * 1000);
|
|
||||||
}
|
|
||||||
catch (InterruptedException e)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -19,11 +19,14 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.server.session.remote;
|
package org.eclipse.jetty.server.session.remote;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.server.SessionManager;
|
||||||
import org.eclipse.jetty.server.session.AbstractInvalidationSessionTest;
|
import org.eclipse.jetty.server.session.AbstractInvalidationSessionTest;
|
||||||
import org.eclipse.jetty.server.session.AbstractTestServer;
|
import org.eclipse.jetty.server.session.AbstractTestServer;
|
||||||
import org.eclipse.jetty.server.session.InfinispanTestSessionServer;
|
import org.eclipse.jetty.server.session.InfinispanTestSessionServer;
|
||||||
|
import org.eclipse.jetty.session.infinispan.InfinispanSessionManager;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Ignore;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* InvalidationSessionTest
|
* InvalidationSessionTest
|
||||||
|
@ -34,7 +37,7 @@ public class RemoteInvalidationSessionTest extends AbstractInvalidationSessionTe
|
||||||
{
|
{
|
||||||
|
|
||||||
public static RemoteInfinispanTestSupport __testSupport;
|
public static RemoteInfinispanTestSupport __testSupport;
|
||||||
public static long __staleSec = 3L;
|
public static final int IDLE_PASSIVATE_SEC = 3;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -55,18 +58,34 @@ public class RemoteInvalidationSessionTest extends AbstractInvalidationSessionTe
|
||||||
* @see org.eclipse.jetty.server.session.AbstractInvalidationSessionTest#createServer(int)
|
* @see org.eclipse.jetty.server.session.AbstractInvalidationSessionTest#createServer(int)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public AbstractTestServer createServer(int port)
|
public AbstractTestServer createServer(int port, int maxInterval, int inspectInterval)
|
||||||
{
|
{
|
||||||
return new InfinispanTestSessionServer(port, __testSupport.getCache());
|
InfinispanTestSessionServer server = new InfinispanTestSessionServer(port, maxInterval, inspectInterval, __testSupport.getCache())
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.eclipse.jetty.server.session.InfinispanTestSessionServer#newSessionManager()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public SessionManager newSessionManager()
|
||||||
|
{
|
||||||
|
InfinispanSessionManager mgr = (InfinispanSessionManager)super.newSessionManager();
|
||||||
|
mgr.getSessionStore().setIdlePassivationTimeoutSec(IDLE_PASSIVATE_SEC);
|
||||||
|
return mgr;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
return server;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Ignore
|
||||||
@Override
|
@Override
|
||||||
public void testInvalidation() throws Exception
|
public void testInvalidation() throws Exception
|
||||||
{
|
{
|
||||||
super.testInvalidation();
|
//Ignore
|
||||||
|
//super.testInvalidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -83,7 +102,7 @@ public class RemoteInvalidationSessionTest extends AbstractInvalidationSessionTe
|
||||||
//that the node will re-load the session from the database and discover that it has gone.
|
//that the node will re-load the session from the database and discover that it has gone.
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Thread.sleep(2 * __staleSec * 1000);
|
Thread.sleep(2 * IDLE_PASSIVATE_SEC * 1000);
|
||||||
}
|
}
|
||||||
catch (InterruptedException e)
|
catch (InterruptedException e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.server.session;
|
package org.eclipse.jetty.server.session;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.server.SessionManager;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -26,9 +27,26 @@ import org.junit.Test;
|
||||||
*/
|
*/
|
||||||
public class InvalidationSessionTest extends AbstractInvalidationSessionTest
|
public class InvalidationSessionTest extends AbstractInvalidationSessionTest
|
||||||
{
|
{
|
||||||
public AbstractTestServer createServer(int port)
|
public static final int IDLE_PASSIVATE_SEC = 3;
|
||||||
|
|
||||||
|
public AbstractTestServer createServer(int port, int maxInactive, int inspectInterval)
|
||||||
{
|
{
|
||||||
return new JdbcTestServer(port);
|
JdbcTestServer server = new JdbcTestServer(port, maxInactive, inspectInterval)
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.eclipse.jetty.server.session.JdbcTestServer#newSessionManager()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public SessionManager newSessionManager()
|
||||||
|
{
|
||||||
|
JDBCSessionManager manager = (JDBCSessionManager)super.newSessionManager();
|
||||||
|
manager.getSessionStore().setIdlePassivationTimeoutSec(IDLE_PASSIVATE_SEC);
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
return server;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pause()
|
public void pause()
|
||||||
|
@ -40,7 +58,7 @@ public class InvalidationSessionTest extends AbstractInvalidationSessionTest
|
||||||
//that the node will re-load the session from the database and discover that it has gone.
|
//that the node will re-load the session from the database and discover that it has gone.
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Thread.sleep(2 * JdbcTestServer.STALE_INTERVAL * 1000);
|
Thread.sleep(2 * IDLE_PASSIVATE_SEC * 1000);
|
||||||
}
|
}
|
||||||
catch (InterruptedException e)
|
catch (InterruptedException e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -137,7 +137,7 @@ public class JdbcTestServer extends AbstractTestServer
|
||||||
JDBCSessionManager manager = new JDBCSessionManager();
|
JDBCSessionManager manager = new JDBCSessionManager();
|
||||||
manager.setSessionIdManager((JDBCSessionIdManager)_sessionIdManager);
|
manager.setSessionIdManager((JDBCSessionIdManager)_sessionIdManager);
|
||||||
JDBCSessionDataStore ds = manager.getSessionDataStore();
|
JDBCSessionDataStore ds = manager.getSessionDataStore();
|
||||||
ds.setGracePeriodSec(_scavengePeriod);
|
ds.setGracePeriodSec(_inspectionPeriod);
|
||||||
manager.getDatabaseAdaptor().setDriverInfo(DRIVER_CLASS, DEFAULT_CONNECTION_URL);
|
manager.getDatabaseAdaptor().setDriverInfo(DRIVER_CLASS, DEFAULT_CONNECTION_URL);
|
||||||
JDBCSessionDataStore.SessionTableSchema sessionTableSchema = new JDBCSessionDataStore.SessionTableSchema();
|
JDBCSessionDataStore.SessionTableSchema sessionTableSchema = new JDBCSessionDataStore.SessionTableSchema();
|
||||||
sessionTableSchema.setTableName(TABLE);
|
sessionTableSchema.setTableName(TABLE);
|
||||||
|
@ -153,9 +153,6 @@ public class JdbcTestServer extends AbstractTestServer
|
||||||
sessionTableSchema.setMapColumn(MAP_COL);
|
sessionTableSchema.setMapColumn(MAP_COL);
|
||||||
sessionTableSchema.setMaxIntervalColumn(MAX_IDLE_COL);
|
sessionTableSchema.setMaxIntervalColumn(MAX_IDLE_COL);
|
||||||
ds.setSessionTableSchema(sessionTableSchema);
|
ds.setSessionTableSchema(sessionTableSchema);
|
||||||
StalePeriodStrategy staleStrategy = new StalePeriodStrategy();
|
|
||||||
staleStrategy.setStaleSec(STALE_INTERVAL);
|
|
||||||
((AbstractSessionStore)manager.getSessionStore()).setStaleStrategy(staleStrategy);
|
|
||||||
return manager;
|
return manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ package org.eclipse.jetty.server.session;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
|
@ -125,8 +126,10 @@ public class ReloadedSessionMissingClassTest
|
||||||
response = request.send();
|
response = request.send();
|
||||||
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||||
String afterStopSessionId = (String)webApp.getServletContext().getAttribute("foo.session");
|
String afterStopSessionId = (String)webApp.getServletContext().getAttribute("foo.session");
|
||||||
|
Boolean fooPresent = (Boolean)webApp.getServletContext().getAttribute("foo.present");
|
||||||
|
assertFalse(fooPresent);
|
||||||
assertNotNull(afterStopSessionId);
|
assertNotNull(afterStopSessionId);
|
||||||
|
assertFalse(fooPresent);
|
||||||
assertTrue(!afterStopSessionId.equals(sessionId));
|
assertTrue(!afterStopSessionId.equals(sessionId));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,9 +67,9 @@ public class SaveIntervalTest
|
||||||
holder.setServlet(servlet);
|
holder.setServlet(servlet);
|
||||||
ctxA.addServlet(holder, "/test");
|
ctxA.addServlet(holder, "/test");
|
||||||
|
|
||||||
StalePeriodStrategy strategy = new StalePeriodStrategy();
|
|
||||||
strategy.setStaleSec(SAVE);
|
//TODO set up the intermittent save
|
||||||
((AbstractSessionStore)((JDBCSessionManager)ctxA.getSessionHandler().getSessionManager()).getSessionStore()).setStaleStrategy(strategy);
|
|
||||||
server.start();
|
server.start();
|
||||||
int port=server.getPort();
|
int port=server.getPort();
|
||||||
try
|
try
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2016 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.nosql.mongodb;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
|
||||||
|
import org.eclipse.jetty.server.SessionManager;
|
||||||
|
import org.eclipse.jetty.server.session.AbstractIdleSessionTest;
|
||||||
|
import org.eclipse.jetty.server.session.AbstractTestServer;
|
||||||
|
import org.eclipse.jetty.server.session.Session;
|
||||||
|
import org.eclipse.jetty.util.thread.Locker.Lock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IdleSessionTest
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class IdleSessionTest extends AbstractIdleSessionTest
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.eclipse.jetty.server.session.AbstractIdleSessionTest#createServer(int, int, int, int)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public AbstractTestServer createServer(final int port, final int max, final int scavenge, final int idleSec)
|
||||||
|
{
|
||||||
|
MongoTestServer server = new MongoTestServer(port,max,scavenge)
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.eclipse.jetty.nosql.mongodb.MongoTestServer#newSessionManager()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public SessionManager newSessionManager()
|
||||||
|
{
|
||||||
|
MongoSessionManager manager = (MongoSessionManager)super.newSessionManager();
|
||||||
|
manager.getSessionStore().setIdlePassivationTimeoutSec(idleSec);
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.eclipse.jetty.server.session.AbstractIdleSessionTest#checkSessionIdled(java.lang.String)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void checkSessionIdled(String sessionId)
|
||||||
|
{
|
||||||
|
assertNotNull(_servlet);
|
||||||
|
assertNotNull(_servlet._session);
|
||||||
|
try (Lock lock = ((Session)_servlet._session).lock())
|
||||||
|
{
|
||||||
|
assertTrue(((Session)_servlet._session).isPassivated());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.eclipse.jetty.server.session.AbstractIdleSessionTest#checkSessionDeIdled(java.lang.String)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void checkSessionDeIdled(String sessionId)
|
||||||
|
{
|
||||||
|
assertNotNull(_servlet);
|
||||||
|
assertNotNull(_servlet._session);
|
||||||
|
try (Lock lock = ((Session)_servlet._session).lock())
|
||||||
|
{
|
||||||
|
assertTrue(((Session)_servlet._session).isActive());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.eclipse.jetty.server.session.AbstractIdleSessionTest#deleteSessionData(java.lang.String)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void deleteSessionData(String sessionId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
MongoTestServer.dropCollection();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
fail(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -19,6 +19,7 @@
|
||||||
package org.eclipse.jetty.nosql.mongodb;
|
package org.eclipse.jetty.nosql.mongodb;
|
||||||
|
|
||||||
|
|
||||||
|
import org.eclipse.jetty.server.SessionManager;
|
||||||
import org.eclipse.jetty.server.session.AbstractInvalidationSessionTest;
|
import org.eclipse.jetty.server.session.AbstractInvalidationSessionTest;
|
||||||
import org.eclipse.jetty.server.session.AbstractTestServer;
|
import org.eclipse.jetty.server.session.AbstractTestServer;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
|
@ -27,7 +28,7 @@ import org.junit.Test;
|
||||||
|
|
||||||
public class InvalidateSessionTest extends AbstractInvalidationSessionTest
|
public class InvalidateSessionTest extends AbstractInvalidationSessionTest
|
||||||
{
|
{
|
||||||
|
public final static int IDLE_PASSIVATE_SEC = 1;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void beforeClass() throws Exception
|
public static void beforeClass() throws Exception
|
||||||
|
@ -43,9 +44,24 @@ public class InvalidateSessionTest extends AbstractInvalidationSessionTest
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractTestServer createServer(int port)
|
public AbstractTestServer createServer(int port, int maxInterval, int inspectInterval)
|
||||||
{
|
{
|
||||||
return new MongoTestServer(port);
|
MongoTestServer server = new MongoTestServer(port, maxInterval, inspectInterval)
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.eclipse.jetty.nosql.mongodb.MongoTestServer#newSessionManager()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public SessionManager newSessionManager()
|
||||||
|
{
|
||||||
|
MongoSessionManager manager = (MongoSessionManager)super.newSessionManager();
|
||||||
|
manager.getSessionStore().setIdlePassivationTimeoutSec(IDLE_PASSIVATE_SEC);
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
return server;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -53,7 +69,7 @@ public class InvalidateSessionTest extends AbstractInvalidationSessionTest
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Thread.sleep(2 * MongoTestServer.STALE_INTERVAL * 1000);
|
Thread.sleep(2 * IDLE_PASSIVATE_SEC * 1000);
|
||||||
}
|
}
|
||||||
catch (InterruptedException e)
|
catch (InterruptedException e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,10 +22,8 @@ import java.net.UnknownHostException;
|
||||||
|
|
||||||
import org.eclipse.jetty.server.SessionIdManager;
|
import org.eclipse.jetty.server.SessionIdManager;
|
||||||
import org.eclipse.jetty.server.SessionManager;
|
import org.eclipse.jetty.server.SessionManager;
|
||||||
import org.eclipse.jetty.server.session.AbstractSessionStore;
|
|
||||||
import org.eclipse.jetty.server.session.AbstractTestServer;
|
import org.eclipse.jetty.server.session.AbstractTestServer;
|
||||||
import org.eclipse.jetty.server.session.SessionHandler;
|
import org.eclipse.jetty.server.session.SessionHandler;
|
||||||
import org.eclipse.jetty.server.session.StalePeriodStrategy;
|
|
||||||
|
|
||||||
import com.mongodb.DBCollection;
|
import com.mongodb.DBCollection;
|
||||||
import com.mongodb.Mongo;
|
import com.mongodb.Mongo;
|
||||||
|
@ -37,7 +35,6 @@ import com.mongodb.MongoException;
|
||||||
*/
|
*/
|
||||||
public class MongoTestServer extends AbstractTestServer
|
public class MongoTestServer extends AbstractTestServer
|
||||||
{
|
{
|
||||||
public static final int STALE_INTERVAL = 1;
|
|
||||||
static int __workers=0;
|
static int __workers=0;
|
||||||
|
|
||||||
|
|
||||||
|
@ -98,10 +95,7 @@ public class MongoTestServer extends AbstractTestServer
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
manager = new MongoSessionManager();
|
manager = new MongoSessionManager();
|
||||||
manager.getSessionDataStore().setGracePeriodSec(_scavengePeriod);
|
manager.getSessionDataStore().setGracePeriodSec(_inspectionPeriod);
|
||||||
StalePeriodStrategy staleStrategy = new StalePeriodStrategy();
|
|
||||||
staleStrategy.setStaleSec(STALE_INTERVAL);
|
|
||||||
((AbstractSessionStore)manager.getSessionStore()).setStaleStrategy(staleStrategy);
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,261 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2016 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.server.session;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.client.HttpClient;
|
||||||
|
import org.eclipse.jetty.client.api.ContentResponse;
|
||||||
|
import org.eclipse.jetty.client.api.Request;
|
||||||
|
import org.eclipse.jetty.server.SessionManager;
|
||||||
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
import org.eclipse.jetty.util.IO;
|
||||||
|
import org.eclipse.jetty.util.log.Log;
|
||||||
|
import org.eclipse.jetty.util.log.StdErrLog;
|
||||||
|
import org.eclipse.jetty.util.thread.Locker.Lock;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IdleSessionTest
|
||||||
|
*
|
||||||
|
* Checks that a session can be idled and de-idled on the next request if it hasn't expired.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public abstract class AbstractIdleSessionTest
|
||||||
|
{
|
||||||
|
|
||||||
|
protected TestServlet _servlet = new TestServlet();
|
||||||
|
protected AbstractTestServer _server1 = null;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param port
|
||||||
|
* @param max
|
||||||
|
* @param scavenge
|
||||||
|
* @param idleSec
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public abstract AbstractTestServer createServer (int port, int max, int scavenge, int idleSec);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param sessionDir
|
||||||
|
* @param sessionId
|
||||||
|
*/
|
||||||
|
public abstract void checkSessionIdled (String sessionId);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param sessionId
|
||||||
|
*/
|
||||||
|
public abstract void checkSessionDeIdled (String sessionId);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param sessionId
|
||||||
|
*/
|
||||||
|
public abstract void deleteSessionData (String sessionId);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param sec
|
||||||
|
*/
|
||||||
|
public void pause (int sec)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Thread.sleep(sec * 1000L);
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSessionIdle() throws Exception
|
||||||
|
{
|
||||||
|
String contextPath = "";
|
||||||
|
String servletMapping = "/server";
|
||||||
|
int inactivePeriod = 20;
|
||||||
|
int scavengePeriod = 3;
|
||||||
|
int idlePeriod = 5;
|
||||||
|
((StdErrLog)Log.getLogger("org.eclipse.jetty.server.session")).setHideStacks(true);
|
||||||
|
System.setProperty("org.eclipse.jetty.STACKS", "false");
|
||||||
|
|
||||||
|
|
||||||
|
_server1 = createServer(0, inactivePeriod, scavengePeriod, idlePeriod);
|
||||||
|
ServletHolder holder = new ServletHolder(_servlet);
|
||||||
|
ServletContextHandler contextHandler = _server1.addContext(contextPath);
|
||||||
|
contextHandler.addServlet(holder, servletMapping);
|
||||||
|
_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 response = client.GET(url + "?action=init");
|
||||||
|
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||||
|
String sessionCookie = response.getHeaders().get("Set-Cookie");
|
||||||
|
assertTrue(sessionCookie != null);
|
||||||
|
// Mangle the cookie, replacing Path with $Path, etc.
|
||||||
|
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||||
|
|
||||||
|
//and wait until the session should be idled out
|
||||||
|
pause(idlePeriod * 2);
|
||||||
|
|
||||||
|
|
||||||
|
//check that the session has been idled
|
||||||
|
checkSessionIdled(AbstractTestServer.extractSessionId(sessionCookie));
|
||||||
|
|
||||||
|
//make another request to de-idle the session
|
||||||
|
Request request = client.newRequest(url + "?action=test");
|
||||||
|
request.getHeaders().add("Cookie", sessionCookie);
|
||||||
|
ContentResponse response2 = request.send();
|
||||||
|
assertEquals(HttpServletResponse.SC_OK,response2.getStatus());
|
||||||
|
|
||||||
|
//check session de-idled
|
||||||
|
checkSessionDeIdled(AbstractTestServer.extractSessionId(sessionCookie));
|
||||||
|
|
||||||
|
//wait again for the session to be idled
|
||||||
|
pause(idlePeriod * 2);
|
||||||
|
|
||||||
|
//check that it is
|
||||||
|
checkSessionIdled(AbstractTestServer.extractSessionId(sessionCookie));
|
||||||
|
|
||||||
|
//While idle, take some action to ensure that a deidle won't work, like
|
||||||
|
//deleting all sessions in mongo
|
||||||
|
deleteSessionData(AbstractTestServer.extractSessionId(sessionCookie));
|
||||||
|
|
||||||
|
//make a request
|
||||||
|
request = client.newRequest(url + "?action=testfail");
|
||||||
|
request.getHeaders().add("Cookie", sessionCookie);
|
||||||
|
response2 = request.send();
|
||||||
|
assertEquals(HttpServletResponse.SC_OK,response2.getStatus());
|
||||||
|
|
||||||
|
//Test trying to de-idle an expired session (ie before the scavenger can get to it)
|
||||||
|
|
||||||
|
//make a request to set up a session on the server
|
||||||
|
response = client.GET(url + "?action=init");
|
||||||
|
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||||
|
sessionCookie = response.getHeaders().get("Set-Cookie");
|
||||||
|
assertTrue(sessionCookie != null);
|
||||||
|
// Mangle the cookie, replacing Path with $Path, etc.
|
||||||
|
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||||
|
|
||||||
|
//and wait until the session should be idled out
|
||||||
|
pause(idlePeriod * 2);
|
||||||
|
|
||||||
|
//stop the scavenger
|
||||||
|
if (_server1.getInspector() != null)
|
||||||
|
_server1.getInspector().stop();
|
||||||
|
|
||||||
|
//check that the session is idle
|
||||||
|
checkSessionIdled(AbstractTestServer.extractSessionId(sessionCookie));
|
||||||
|
|
||||||
|
//wait until the session should be expired
|
||||||
|
pause (inactivePeriod + (inactivePeriod/2));
|
||||||
|
|
||||||
|
//make another request to de-idle the session
|
||||||
|
request = client.newRequest(url + "?action=testfail");
|
||||||
|
request.getHeaders().add("Cookie", sessionCookie);
|
||||||
|
response2 = request.send();
|
||||||
|
assertEquals(HttpServletResponse.SC_OK,response2.getStatus());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_server1.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static class TestServlet extends HttpServlet
|
||||||
|
{
|
||||||
|
public String originalId = null;
|
||||||
|
public HttpSession _session = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse httpServletResponse) throws ServletException, IOException
|
||||||
|
{
|
||||||
|
String action = request.getParameter("action");
|
||||||
|
if ("init".equals(action))
|
||||||
|
{
|
||||||
|
HttpSession session = request.getSession(true);
|
||||||
|
session.setAttribute("value", new Integer(1));
|
||||||
|
originalId = session.getId();
|
||||||
|
Session s = (Session)session;
|
||||||
|
try (Lock lock = s.lock())
|
||||||
|
{
|
||||||
|
assertTrue(!s.isPassivated());
|
||||||
|
}
|
||||||
|
_session = s;
|
||||||
|
}
|
||||||
|
else if ("test".equals(action))
|
||||||
|
{
|
||||||
|
HttpSession session = request.getSession(false);
|
||||||
|
assertTrue(session != null);
|
||||||
|
assertTrue(originalId.equals(session.getId()));
|
||||||
|
Session s = (Session)session;
|
||||||
|
try (Lock lock = s.lock();)
|
||||||
|
{
|
||||||
|
assertTrue(s.isActive());
|
||||||
|
assertFalse(s.isPassivated());
|
||||||
|
}
|
||||||
|
Integer v = (Integer)session.getAttribute("value");
|
||||||
|
session.setAttribute("value", new Integer(v.intValue()+1));
|
||||||
|
_session = session;
|
||||||
|
}
|
||||||
|
else if ("testfail".equals(action))
|
||||||
|
{
|
||||||
|
HttpSession session = request.getSession(false);
|
||||||
|
assertTrue(session == null);
|
||||||
|
_session = session;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -43,7 +43,7 @@ import org.junit.Test;
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractInvalidationSessionTest
|
public abstract class AbstractInvalidationSessionTest
|
||||||
{
|
{
|
||||||
public abstract AbstractTestServer createServer(int port);
|
public abstract AbstractTestServer createServer(int port, int maxInactive, int inspectInterval);
|
||||||
public abstract void pause();
|
public abstract void pause();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -51,7 +51,7 @@ public abstract class AbstractInvalidationSessionTest
|
||||||
{
|
{
|
||||||
String contextPath = "";
|
String contextPath = "";
|
||||||
String servletMapping = "/server";
|
String servletMapping = "/server";
|
||||||
AbstractTestServer server1 = createServer(0);
|
AbstractTestServer server1 = createServer(0, 30, 1);
|
||||||
server1.addContext(contextPath).addServlet(TestServlet.class, servletMapping);
|
server1.addContext(contextPath).addServlet(TestServlet.class, servletMapping);
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ public abstract class AbstractInvalidationSessionTest
|
||||||
{
|
{
|
||||||
server1.start();
|
server1.start();
|
||||||
int port1 = server1.getPort();
|
int port1 = server1.getPort();
|
||||||
AbstractTestServer server2 = createServer(0);
|
AbstractTestServer server2 = createServer(0, 30, 1);
|
||||||
server2.addContext(contextPath).addServlet(TestServlet.class, servletMapping);
|
server2.addContext(contextPath).addServlet(TestServlet.class, servletMapping);
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
|
@ -35,14 +35,14 @@ import org.eclipse.jetty.webapp.WebAppContext;
|
||||||
public abstract class AbstractTestServer
|
public abstract class AbstractTestServer
|
||||||
{
|
{
|
||||||
public static int DEFAULT_MAX_INACTIVE = 30;
|
public static int DEFAULT_MAX_INACTIVE = 30;
|
||||||
public static int DEFAULT_SCAVENGE = 10;
|
public static int DEFAULT_INSPECTION_SEC = 10;
|
||||||
|
|
||||||
protected final Server _server;
|
protected final Server _server;
|
||||||
protected final int _maxInactivePeriod;
|
protected final int _maxInactivePeriod;
|
||||||
protected final int _scavengePeriod;
|
protected final int _inspectionPeriod;
|
||||||
protected final ContextHandlerCollection _contexts;
|
protected final ContextHandlerCollection _contexts;
|
||||||
protected SessionIdManager _sessionIdManager;
|
protected SessionIdManager _sessionIdManager;
|
||||||
private PeriodicSessionInspector _scavenger;
|
private PeriodicSessionInspector _inspector;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ public abstract class AbstractTestServer
|
||||||
|
|
||||||
public AbstractTestServer(int port)
|
public AbstractTestServer(int port)
|
||||||
{
|
{
|
||||||
this(port, DEFAULT_MAX_INACTIVE, DEFAULT_SCAVENGE);
|
this(port, DEFAULT_MAX_INACTIVE, DEFAULT_INSPECTION_SEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractTestServer(int port, int maxInactivePeriod, int scavengePeriod)
|
public AbstractTestServer(int port, int maxInactivePeriod, int scavengePeriod)
|
||||||
|
@ -78,14 +78,14 @@ public abstract class AbstractTestServer
|
||||||
{
|
{
|
||||||
_server = new Server(port);
|
_server = new Server(port);
|
||||||
_maxInactivePeriod = maxInactivePeriod;
|
_maxInactivePeriod = maxInactivePeriod;
|
||||||
_scavengePeriod = scavengePeriod;
|
_inspectionPeriod = scavengePeriod;
|
||||||
_contexts = new ContextHandlerCollection();
|
_contexts = new ContextHandlerCollection();
|
||||||
_sessionIdManager = newSessionIdManager(sessionIdMgrConfig);
|
_sessionIdManager = newSessionIdManager(sessionIdMgrConfig);
|
||||||
_server.setSessionIdManager(_sessionIdManager);
|
_server.setSessionIdManager(_sessionIdManager);
|
||||||
((AbstractSessionIdManager) _sessionIdManager).setServer(_server);
|
((AbstractSessionIdManager) _sessionIdManager).setServer(_server);
|
||||||
_scavenger = new PeriodicSessionInspector();
|
_inspector = new PeriodicSessionInspector();
|
||||||
_scavenger.setIntervalSec(scavengePeriod);
|
_inspector.setIntervalSec(scavengePeriod);
|
||||||
((AbstractSessionIdManager)_sessionIdManager).setSessionScavenger(_scavenger);
|
((AbstractSessionIdManager)_sessionIdManager).setSessionScavenger(_inspector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -102,6 +102,11 @@ public abstract class AbstractTestServer
|
||||||
_server.start();
|
_server.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PeriodicSessionInspector getInspector()
|
||||||
|
{
|
||||||
|
return _inspector;
|
||||||
|
}
|
||||||
|
|
||||||
public int getPort()
|
public int getPort()
|
||||||
{
|
{
|
||||||
return ((NetworkConnector)getServer().getConnectors()[0]).getLocalPort();
|
return ((NetworkConnector)getServer().getConnectors()[0]).getLocalPort();
|
||||||
|
|
Loading…
Reference in New Issue