Merge remote-tracking branch 'eclipse/jetty-9.4.x' into jetty-9.4.x-1027-Multipart
This commit is contained in:
commit
be2d6ebb29
|
@ -89,7 +89,7 @@ def getFullBuild(jdk, os) {
|
|||
globalMavenSettingsConfig: 'oss-settings.xml',
|
||||
mavenLocalRepo: "${env.JENKINS_HOME}/${env.EXECUTOR_NUMBER}") {
|
||||
//
|
||||
sh "mvn -V -B install -Dmaven.test.failure.ignore=true -Prun-its -T3 -e -Dmaven.repo.local=${env.JENKINS_HOME}/${env.EXECUTOR_NUMBER}"
|
||||
sh "mvn -V -B install -Dmaven.test.failure.ignore=true -Prun-its -T3 -e -Dmaven.repo.local=${env.JENKINS_HOME}/${env.EXECUTOR_NUMBER} -Pmongodb"
|
||||
}
|
||||
// withMaven doesn't label..
|
||||
// Report failures in the jenkins UI
|
||||
|
|
|
@ -127,7 +127,7 @@ public abstract class AbstractConnectionPool implements ConnectionPool, Dumpable
|
|||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Connection {}/{} creation succeeded {}", total+1, maxConnections, connection);
|
||||
connections.update(-1,0);
|
||||
connections.add(-1,0);
|
||||
onCreated(connection);
|
||||
proceed();
|
||||
}
|
||||
|
@ -137,7 +137,7 @@ public abstract class AbstractConnectionPool implements ConnectionPool, Dumpable
|
|||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Connection " + (total+1) + "/" + maxConnections + " creation failed", x);
|
||||
connections.update(-1,-1);
|
||||
connections.add(-1,-1);
|
||||
requester.failed(x);
|
||||
}
|
||||
});
|
||||
|
@ -190,7 +190,7 @@ public abstract class AbstractConnectionPool implements ConnectionPool, Dumpable
|
|||
|
||||
protected void removed(Connection connection)
|
||||
{
|
||||
int pooled = connections.updateLo(-1);
|
||||
int pooled = connections.addAndGetLo(-1);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Connection removed {} - pooled: {}", connection, pooled);
|
||||
}
|
||||
|
|
|
@ -31,8 +31,8 @@ jetty-plus.jar
|
|||
If you are using transactions, you will also need the `javax.transaction` api.
|
||||
You can obtain this jar link:{MVNCENTRAL}/org/eclipse/jetty/orbit/javax.transaction/1.1.1.v201105210645/javax.transaction-1.1.1.v201105210645.jar[here.]
|
||||
|
||||
If you wish to use mail, you will also need the `javax.mail` api and implementation which link:{MVNCENTRAL/org/eclipse/jetty/orbit/javax.mail.glassfish/1.4.1.v201005082020/javax.mail.glassfish-1.4.1.v201005082020.jar[you can download here.]
|
||||
Note that this jar also requires the `javax.activation` classes, which is available link:{MVCENTRAL}/org/eclipse/jetty/orbit/javax.activation/1.1.0.v201105071233/javax.activation-1.1.0.v201105071233.jar[at this link.]
|
||||
If you wish to use mail, you will also need the `javax.mail` api and implementation which link:{MVNCENTRAL}/org/eclipse/jetty/orbit/javax.mail.glassfish/1.4.1.v201005082020/javax.mail.glassfish-1.4.1.v201005082020.jar[you can download here.]
|
||||
Note that this jar also requires the `javax.activation` classes, which is available link:{MVNCENTRAL}/org/eclipse/jetty/orbit/javax.activation/1.1.0.v201105071233/javax.activation-1.1.0.v201105071233.jar[at this link.]
|
||||
|
||||
==== Example Code
|
||||
|
||||
|
|
|
@ -492,7 +492,7 @@ public void start(BundleContext context) throws Exception
|
|||
Dictionary props = new Hashtable();
|
||||
props.put("Jetty-WarResourcePath",".");
|
||||
props.put("contextPath","/acme");
|
||||
context.registerService(ContextHandler.class.getName(),webapp,props);
|
||||
context.registerService(WebAppContext.class.getName(),webapp,props);
|
||||
}
|
||||
----
|
||||
|
||||
|
|
|
@ -510,16 +510,22 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
|
|||
{
|
||||
if (LOG.isDebugEnabled()) LOG.debug("Loading session {} from DataStore", id);
|
||||
|
||||
Entity entity = _datastore.get(makeKey(id, _context));
|
||||
if (entity == null)
|
||||
try
|
||||
{
|
||||
if (LOG.isDebugEnabled()) LOG.debug("No session {} in DataStore ", id);
|
||||
return null;
|
||||
Entity entity = _datastore.get(makeKey(id, _context));
|
||||
if (entity == null)
|
||||
{
|
||||
if (LOG.isDebugEnabled()) LOG.debug("No session {} in DataStore ", id);
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return sessionFromEntity(entity);
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (Exception e)
|
||||
{
|
||||
SessionData data = sessionFromEntity(entity);
|
||||
return data;
|
||||
throw new UnreadableSessionDataException(id, _context, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -706,7 +712,10 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
|
|||
Query<ProjectionEntity> query = Query.newProjectionEntityQueryBuilder()
|
||||
.setKind(_model.getKind())
|
||||
.setProjection(_model.getExpiry())
|
||||
.setFilter(PropertyFilter.eq(_model.getId(), id))
|
||||
.setFilter(CompositeFilter.and(PropertyFilter.eq(_model.getId(), id),
|
||||
PropertyFilter.eq(_model.getContextPath(), _context.getCanonicalContextPath()),
|
||||
PropertyFilter.eq(_model.getVhost(), _context.getVhost())))
|
||||
//.setFilter(PropertyFilter.eq(_model.getId(), id))
|
||||
.build();
|
||||
|
||||
QueryResults<ProjectionEntity> presults;
|
||||
|
@ -731,7 +740,10 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
|
|||
{
|
||||
Query<Entity> query = Query.newEntityQueryBuilder()
|
||||
.setKind(_model.getKind())
|
||||
.setFilter(PropertyFilter.eq(_model.getId(), id))
|
||||
.setFilter(CompositeFilter.and(PropertyFilter.eq(_model.getId(), id),
|
||||
PropertyFilter.eq(_model.getContextPath(), _context.getCanonicalContextPath()),
|
||||
PropertyFilter.eq(_model.getVhost(), _context.getVhost())))
|
||||
//.setFilter(PropertyFilter.eq(_model.getId(), id))
|
||||
.build();
|
||||
|
||||
QueryResults<Entity> results;
|
||||
|
@ -912,8 +924,8 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
|
|||
if (entity == null)
|
||||
return null;
|
||||
|
||||
final AtomicReference<SessionData> reference = new AtomicReference<SessionData>();
|
||||
final AtomicReference<Exception> exception = new AtomicReference<Exception>();
|
||||
final AtomicReference<SessionData> reference = new AtomicReference<>();
|
||||
final AtomicReference<Exception> exception = new AtomicReference<>();
|
||||
Runnable load = new Runnable()
|
||||
{
|
||||
@Override
|
||||
|
@ -975,7 +987,9 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
|
|||
_context.run(load);
|
||||
|
||||
if (exception.get() != null)
|
||||
{
|
||||
throw exception.get();
|
||||
}
|
||||
|
||||
return reference.get();
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.eclipse.jetty.server.session.AbstractSessionDataStore;
|
|||
import org.eclipse.jetty.server.session.SessionContext;
|
||||
import org.eclipse.jetty.server.session.SessionData;
|
||||
import org.eclipse.jetty.server.session.SessionDataStore;
|
||||
import org.eclipse.jetty.server.session.UnreadableSessionDataException;
|
||||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
@ -55,23 +56,22 @@ public class HazelcastSessionDataStore
|
|||
throws Exception
|
||||
{
|
||||
|
||||
final AtomicReference<SessionData> reference = new AtomicReference<SessionData>();
|
||||
final AtomicReference<Exception> exception = new AtomicReference<Exception>();
|
||||
final AtomicReference<SessionData> reference = new AtomicReference<>();
|
||||
final AtomicReference<Exception> exception = new AtomicReference<>();
|
||||
|
||||
//ensure the load runs in the context classloader scope
|
||||
_context.run( () -> {
|
||||
try
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug( "Loading session {} from hazelcast", id );
|
||||
}
|
||||
|
||||
SessionData sd = sessionDataMap.get( getCacheKey( id ) );
|
||||
reference.set(sd);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
exception.set(e);
|
||||
exception.set(new UnreadableSessionDataException(id, _context, e));
|
||||
}
|
||||
} );
|
||||
|
||||
|
@ -126,12 +126,13 @@ public class HazelcastSessionDataStore
|
|||
{
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
return candidates.stream().filter( candidate -> {
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug( "Checking expiry for candidate {}", candidate );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
SessionData sd = load(candidate);
|
||||
|
@ -193,9 +194,17 @@ public class HazelcastSessionDataStore
|
|||
|
||||
@Override
|
||||
public boolean exists( String id )
|
||||
throws Exception
|
||||
throws Exception
|
||||
{
|
||||
return this.sessionDataMap.containsKey( getCacheKey( id ) );
|
||||
//TODO find way to do query without pulling in whole session data
|
||||
SessionData sd = load(id);
|
||||
if (sd == null)
|
||||
return false;
|
||||
|
||||
if (sd.getExpiry() <= 0)
|
||||
return true; //never expires
|
||||
else
|
||||
return (Boolean.valueOf(sd.getExpiry() > System.currentTimeMillis())); //not expired yet
|
||||
}
|
||||
|
||||
public String getCacheKey( String id )
|
||||
|
|
|
@ -33,7 +33,6 @@ import java.util.concurrent.atomic.AtomicLong;
|
|||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.servlet.AsyncContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.WriteListener;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
|
@ -244,12 +243,13 @@ public class StreamResetTest extends AbstractTest
|
|||
@Test
|
||||
public void testBlockingWriteAfterStreamReceivingReset() throws Exception
|
||||
{
|
||||
final CountDownLatch resetLatch = new CountDownLatch(1);
|
||||
final CountDownLatch dataLatch = new CountDownLatch(1);
|
||||
CountDownLatch commitLatch = new CountDownLatch(1);
|
||||
CountDownLatch resetLatch = new CountDownLatch(1);
|
||||
CountDownLatch dataLatch = new CountDownLatch(1);
|
||||
start(new HttpServlet()
|
||||
{
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException
|
||||
{
|
||||
Charset charset = StandardCharsets.UTF_8;
|
||||
byte[] data = "AFTER RESET".getBytes(charset);
|
||||
|
@ -258,11 +258,15 @@ public class StreamResetTest extends AbstractTest
|
|||
response.setContentType("text/plain;charset=" + charset.name());
|
||||
response.setContentLength(data.length * 10);
|
||||
response.flushBuffer();
|
||||
// Wait for the commit callback to complete.
|
||||
commitLatch.countDown();
|
||||
|
||||
try
|
||||
{
|
||||
// Wait for the reset to happen.
|
||||
Assert.assertTrue(resetLatch.await(10, TimeUnit.SECONDS));
|
||||
// Wait for the reset to be sent.
|
||||
Assert.assertTrue(resetLatch.await(5, TimeUnit.SECONDS));
|
||||
// Wait for the reset to arrive to the server and be processed.
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
catch (InterruptedException x)
|
||||
{
|
||||
|
@ -282,7 +286,7 @@ public class StreamResetTest extends AbstractTest
|
|||
}
|
||||
catch (InterruptedException x)
|
||||
{
|
||||
|
||||
throw new InterruptedIOException();
|
||||
}
|
||||
catch (IOException x)
|
||||
{
|
||||
|
@ -299,23 +303,33 @@ public class StreamResetTest extends AbstractTest
|
|||
@Override
|
||||
public void onHeaders(Stream stream, HeadersFrame frame)
|
||||
{
|
||||
stream.reset(new ResetFrame(stream.getId(), ErrorCode.CANCEL_STREAM_ERROR.code), Callback.NOOP);
|
||||
resetLatch.countDown();
|
||||
try
|
||||
{
|
||||
commitLatch.await(5, TimeUnit.SECONDS);
|
||||
Callback.Completable completable = new Callback.Completable();
|
||||
stream.reset(new ResetFrame(stream.getId(), ErrorCode.CANCEL_STREAM_ERROR.code), completable);
|
||||
completable.thenRun(resetLatch::countDown);
|
||||
}
|
||||
catch (InterruptedException x)
|
||||
{
|
||||
x.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Assert.assertTrue(dataLatch.await(10, TimeUnit.SECONDS));
|
||||
Assert.assertTrue(dataLatch.await(5, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAsyncWriteAfterStreamReceivingReset() throws Exception
|
||||
{
|
||||
final CountDownLatch resetLatch = new CountDownLatch(1);
|
||||
final CountDownLatch dataLatch = new CountDownLatch(1);
|
||||
CountDownLatch commitLatch = new CountDownLatch(1);
|
||||
CountDownLatch resetLatch = new CountDownLatch(1);
|
||||
CountDownLatch dataLatch = new CountDownLatch(1);
|
||||
start(new HttpServlet()
|
||||
{
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException
|
||||
protected void doGet(HttpServletRequest request, final HttpServletResponse response) throws IOException
|
||||
{
|
||||
Charset charset = StandardCharsets.UTF_8;
|
||||
final ByteBuffer data = ByteBuffer.wrap("AFTER RESET".getBytes(charset));
|
||||
|
@ -324,6 +338,8 @@ public class StreamResetTest extends AbstractTest
|
|||
response.setContentType("text/plain;charset=" + charset.name());
|
||||
response.setContentLength(data.remaining());
|
||||
response.flushBuffer();
|
||||
// Wait for the commit callback to complete.
|
||||
commitLatch.countDown();
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -339,34 +355,30 @@ public class StreamResetTest extends AbstractTest
|
|||
|
||||
// Write some content asynchronously after the stream has been reset.
|
||||
final AsyncContext context = request.startAsync();
|
||||
new Thread()
|
||||
new Thread(() ->
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
// Wait for the request thread to exit
|
||||
// doGet() so this is really asynchronous.
|
||||
Thread.sleep(1000);
|
||||
// Wait for the request thread to exit
|
||||
// doGet() so this is really asynchronous.
|
||||
Thread.sleep(1000);
|
||||
|
||||
HttpOutput output = (HttpOutput)response.getOutputStream();
|
||||
output.sendContent(data, new Callback()
|
||||
{
|
||||
@Override
|
||||
public void failed(Throwable x)
|
||||
{
|
||||
context.complete();
|
||||
dataLatch.countDown();
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Throwable x)
|
||||
HttpOutput output = (HttpOutput)response.getOutputStream();
|
||||
output.sendContent(data, new Callback()
|
||||
{
|
||||
x.printStackTrace();
|
||||
}
|
||||
@Override
|
||||
public void failed(Throwable x)
|
||||
{
|
||||
context.complete();
|
||||
dataLatch.countDown();
|
||||
}
|
||||
});
|
||||
}
|
||||
}.start();
|
||||
catch (Throwable x)
|
||||
{
|
||||
x.printStackTrace();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -378,8 +390,17 @@ public class StreamResetTest extends AbstractTest
|
|||
@Override
|
||||
public void onHeaders(Stream stream, HeadersFrame frame)
|
||||
{
|
||||
stream.reset(new ResetFrame(stream.getId(), ErrorCode.CANCEL_STREAM_ERROR.code), Callback.NOOP);
|
||||
resetLatch.countDown();
|
||||
try
|
||||
{
|
||||
commitLatch.await(5, TimeUnit.SECONDS);
|
||||
Callback.Completable completable = new Callback.Completable();
|
||||
stream.reset(new ResetFrame(stream.getId(), ErrorCode.CANCEL_STREAM_ERROR.code), completable);
|
||||
completable.thenRun(resetLatch::countDown);
|
||||
}
|
||||
catch (InterruptedException x)
|
||||
{
|
||||
x.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -439,7 +460,7 @@ public class StreamResetTest extends AbstractTest
|
|||
context.addServlet(new ServletHolder(new HttpServlet()
|
||||
{
|
||||
@Override
|
||||
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
protected void service(HttpServletRequest request, HttpServletResponse response) throws IOException
|
||||
{
|
||||
phaser.get().countDown();
|
||||
IO.copy(request.getInputStream(), response.getOutputStream());
|
||||
|
@ -526,7 +547,7 @@ public class StreamResetTest extends AbstractTest
|
|||
start(new HttpServlet()
|
||||
{
|
||||
@Override
|
||||
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
protected void service(HttpServletRequest request, HttpServletResponse response) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -578,7 +599,7 @@ public class StreamResetTest extends AbstractTest
|
|||
start(new HttpServlet()
|
||||
{
|
||||
@Override
|
||||
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
protected void service(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
AsyncContext asyncContext = request.startAsync();
|
||||
asyncContext.start(() ->
|
||||
|
@ -642,7 +663,7 @@ public class StreamResetTest extends AbstractTest
|
|||
start(new HttpServlet()
|
||||
{
|
||||
@Override
|
||||
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
protected void service(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -694,7 +715,7 @@ public class StreamResetTest extends AbstractTest
|
|||
start(new HttpServlet()
|
||||
{
|
||||
@Override
|
||||
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
protected void service(HttpServletRequest request, HttpServletResponse response) throws IOException
|
||||
{
|
||||
AsyncContext asyncContext = request.startAsync();
|
||||
ServletOutputStream output = response.getOutputStream();
|
||||
|
|
|
@ -18,7 +18,56 @@
|
|||
|
||||
package org.eclipse.jetty.http2;
|
||||
|
||||
/**
|
||||
* The set of close states for a stream or a session.
|
||||
* <pre>
|
||||
* rcv hc
|
||||
* NOT_CLOSED ---------------> REMOTELY_CLOSED
|
||||
* | |
|
||||
* gen| |gen
|
||||
* hc| |hc
|
||||
* | |
|
||||
* v rcv hc v
|
||||
* LOCALLY_CLOSING --------------> CLOSING
|
||||
* | |
|
||||
* snd| |gen
|
||||
* hc| |hc
|
||||
* | |
|
||||
* v rcv hc v
|
||||
* LOCALLY_CLOSED ----------------> CLOSED
|
||||
* </pre>
|
||||
*/
|
||||
public enum CloseState
|
||||
{
|
||||
NOT_CLOSED, LOCALLY_CLOSED, REMOTELY_CLOSED, CLOSED
|
||||
/**
|
||||
* Fully open.
|
||||
*/
|
||||
NOT_CLOSED,
|
||||
/**
|
||||
* A half-close frame has been generated.
|
||||
*/
|
||||
LOCALLY_CLOSING,
|
||||
/**
|
||||
* A half-close frame has been generated and sent.
|
||||
*/
|
||||
LOCALLY_CLOSED,
|
||||
/**
|
||||
* A half-close frame has been received.
|
||||
*/
|
||||
REMOTELY_CLOSED,
|
||||
/**
|
||||
* A half-close frame has been received and a half-close frame has been generated, but not yet sent.
|
||||
*/
|
||||
CLOSING,
|
||||
/**
|
||||
* Fully closed.
|
||||
*/
|
||||
CLOSED;
|
||||
|
||||
public enum Event
|
||||
{
|
||||
RECEIVED,
|
||||
BEFORE_SEND,
|
||||
AFTER_SEND
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ import org.eclipse.jetty.http2.generator.Generator;
|
|||
import org.eclipse.jetty.http2.parser.Parser;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.util.AtomicBiInteger;
|
||||
import org.eclipse.jetty.util.Atomics;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.CountingCallback;
|
||||
|
@ -72,7 +73,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
private final AtomicInteger streamIds = new AtomicInteger();
|
||||
private final AtomicInteger lastStreamId = new AtomicInteger();
|
||||
private final AtomicInteger localStreamCount = new AtomicInteger();
|
||||
private final AtomicInteger remoteStreamCount = new AtomicInteger();
|
||||
private final AtomicBiInteger remoteStreamCount = new AtomicBiInteger();
|
||||
private final AtomicInteger sendWindow = new AtomicInteger();
|
||||
private final AtomicInteger recvWindow = new AtomicInteger();
|
||||
private final AtomicReference<CloseState> closed = new AtomicReference<>(CloseState.NOT_CLOSED);
|
||||
|
@ -718,14 +719,16 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
// SPEC: exceeding max concurrent streams is treated as stream error.
|
||||
while (true)
|
||||
{
|
||||
int remoteCount = remoteStreamCount.get();
|
||||
long encoded = remoteStreamCount.get();
|
||||
int remoteCount = AtomicBiInteger.getHi(encoded);
|
||||
int remoteClosing = AtomicBiInteger.getLo(encoded);
|
||||
int maxCount = getMaxRemoteStreams();
|
||||
if (maxCount >= 0 && remoteCount >= maxCount)
|
||||
if (maxCount >= 0 && remoteCount - remoteClosing >= maxCount)
|
||||
{
|
||||
reset(new ResetFrame(streamId, ErrorCode.REFUSED_STREAM_ERROR.code), Callback.NOOP);
|
||||
return null;
|
||||
}
|
||||
if (remoteStreamCount.compareAndSet(remoteCount, remoteCount + 1))
|
||||
if (remoteStreamCount.compareAndSet(encoded, remoteCount + 1, remoteClosing))
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -748,6 +751,14 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
}
|
||||
}
|
||||
|
||||
void updateStreamCount(boolean local, int deltaStreams, int deltaClosing)
|
||||
{
|
||||
if (local)
|
||||
localStreamCount.addAndGet(deltaStreams);
|
||||
else
|
||||
remoteStreamCount.add(deltaStreams, deltaClosing);
|
||||
}
|
||||
|
||||
protected IStream newStream(int streamId, boolean local)
|
||||
{
|
||||
return new HTTP2Stream(scheduler, this, streamId, local);
|
||||
|
@ -759,18 +770,10 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
IStream removed = streams.remove(stream.getId());
|
||||
if (removed != null)
|
||||
{
|
||||
boolean local = stream.isLocal();
|
||||
if (local)
|
||||
localStreamCount.decrementAndGet();
|
||||
else
|
||||
remoteStreamCount.decrementAndGet();
|
||||
|
||||
onStreamClosed(stream);
|
||||
|
||||
flowControl.onStreamDestroyed(stream);
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Removed {} {}", local ? "local" : "remote", stream);
|
||||
LOG.debug("Removed {} {}", stream.isLocal() ? "local" : "remote", stream);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1167,7 +1170,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
bytes = frameBytes = generator.control(lease, frame);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Generated {}", frame);
|
||||
prepare();
|
||||
beforeSend();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1184,10 +1187,16 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
* sender, the action may have not been performed yet, causing the larger
|
||||
* data to be rejected, when it should have been accepted.</p>
|
||||
*/
|
||||
private void prepare()
|
||||
private void beforeSend()
|
||||
{
|
||||
switch (frame.getType())
|
||||
{
|
||||
case HEADERS:
|
||||
{
|
||||
HeadersFrame headersFrame = (HeadersFrame)frame;
|
||||
stream.updateClose(headersFrame.isEndStream(), CloseState.Event.BEFORE_SEND);
|
||||
break;
|
||||
}
|
||||
case SETTINGS:
|
||||
{
|
||||
SettingsFrame settingsFrame = (SettingsFrame)frame;
|
||||
|
@ -1213,7 +1222,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
{
|
||||
onStreamOpened(stream);
|
||||
HeadersFrame headersFrame = (HeadersFrame)frame;
|
||||
if (stream.updateClose(headersFrame.isEndStream(), true))
|
||||
if (stream.updateClose(headersFrame.isEndStream(), CloseState.Event.AFTER_SEND))
|
||||
removeStream(stream);
|
||||
break;
|
||||
}
|
||||
|
@ -1230,7 +1239,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
{
|
||||
// Pushed streams are implicitly remotely closed.
|
||||
// They are closed when sending an end-stream DATA frame.
|
||||
stream.updateClose(true, false);
|
||||
stream.updateClose(true, CloseState.Event.RECEIVED);
|
||||
break;
|
||||
}
|
||||
case GO_AWAY:
|
||||
|
@ -1317,15 +1326,17 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
int length = Math.min(dataBytes, window);
|
||||
|
||||
// Only one DATA frame is generated.
|
||||
bytes = frameBytes = generator.data(lease, (DataFrame)frame, length);
|
||||
DataFrame dataFrame = (DataFrame)frame;
|
||||
bytes = frameBytes = generator.data(lease, dataFrame, length);
|
||||
int written = bytes - Frame.HEADER_LENGTH;
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Generated {}, length/window/data={}/{}/{}", frame, written, window, dataBytes);
|
||||
LOG.debug("Generated {}, length/window/data={}/{}/{}", dataFrame, written, window, dataBytes);
|
||||
|
||||
this.dataWritten = written;
|
||||
this.dataBytes -= written;
|
||||
|
||||
flowControl.onDataSending(stream, written);
|
||||
stream.updateClose(dataFrame.isEndStream(), CloseState.Event.BEFORE_SEND);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1342,7 +1353,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
{
|
||||
// Only now we can update the close state
|
||||
// and eventually remove the stream.
|
||||
if (stream.updateClose(dataFrame.isEndStream(), true))
|
||||
if (stream.updateClose(dataFrame.isEndStream(), CloseState.Event.AFTER_SEND))
|
||||
removeStream(stream);
|
||||
super.succeeded();
|
||||
}
|
||||
|
|
|
@ -264,7 +264,7 @@ public class HTTP2Stream extends IdleTimeout implements IStream, Callback, Dumpa
|
|||
|
||||
private void onHeaders(HeadersFrame frame, Callback callback)
|
||||
{
|
||||
if (updateClose(frame.isEndStream(), false))
|
||||
if (updateClose(frame.isEndStream(), CloseState.Event.RECEIVED))
|
||||
session.removeStream(this);
|
||||
callback.succeeded();
|
||||
}
|
||||
|
@ -295,7 +295,7 @@ public class HTTP2Stream extends IdleTimeout implements IStream, Callback, Dumpa
|
|||
return;
|
||||
}
|
||||
|
||||
if (updateClose(frame.isEndStream(), false))
|
||||
if (updateClose(frame.isEndStream(), CloseState.Event.RECEIVED))
|
||||
session.removeStream(this);
|
||||
notifyData(this, frame, callback);
|
||||
}
|
||||
|
@ -312,7 +312,7 @@ public class HTTP2Stream extends IdleTimeout implements IStream, Callback, Dumpa
|
|||
{
|
||||
// Pushed streams are implicitly locally closed.
|
||||
// They are closed when receiving an end-stream DATA frame.
|
||||
updateClose(true, true);
|
||||
updateClose(true, CloseState.Event.AFTER_SEND);
|
||||
callback.succeeded();
|
||||
}
|
||||
|
||||
|
@ -322,14 +322,29 @@ public class HTTP2Stream extends IdleTimeout implements IStream, Callback, Dumpa
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean updateClose(boolean update, boolean local)
|
||||
public boolean updateClose(boolean update, CloseState.Event event)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Update close for {} close={} local={}", this, update, local);
|
||||
LOG.debug("Update close for {} update={} event={}", this, update, event);
|
||||
|
||||
if (!update)
|
||||
return false;
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case RECEIVED:
|
||||
return updateCloseAfterReceived();
|
||||
case BEFORE_SEND:
|
||||
return updateCloseBeforeSend();
|
||||
case AFTER_SEND:
|
||||
return updateCloseAfterSend();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean updateCloseAfterReceived()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
CloseState current = closeState.get();
|
||||
|
@ -337,22 +352,79 @@ public class HTTP2Stream extends IdleTimeout implements IStream, Callback, Dumpa
|
|||
{
|
||||
case NOT_CLOSED:
|
||||
{
|
||||
CloseState newValue = local ? CloseState.LOCALLY_CLOSED : CloseState.REMOTELY_CLOSED;
|
||||
if (closeState.compareAndSet(current, newValue))
|
||||
if (closeState.compareAndSet(current, CloseState.REMOTELY_CLOSED))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case LOCALLY_CLOSING:
|
||||
{
|
||||
if (closeState.compareAndSet(current, CloseState.CLOSING))
|
||||
{
|
||||
updateStreamCount(0, 1);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LOCALLY_CLOSED:
|
||||
{
|
||||
if (local)
|
||||
return false;
|
||||
close();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean updateCloseBeforeSend()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
CloseState current = closeState.get();
|
||||
switch (current)
|
||||
{
|
||||
case NOT_CLOSED:
|
||||
{
|
||||
if (closeState.compareAndSet(current, CloseState.LOCALLY_CLOSING))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case REMOTELY_CLOSED:
|
||||
{
|
||||
if (!local)
|
||||
if (closeState.compareAndSet(current, CloseState.CLOSING))
|
||||
{
|
||||
updateStreamCount(0, 1);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean updateCloseAfterSend()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
CloseState current = closeState.get();
|
||||
switch (current)
|
||||
{
|
||||
case NOT_CLOSED:
|
||||
case LOCALLY_CLOSING:
|
||||
{
|
||||
if (closeState.compareAndSet(current, CloseState.LOCALLY_CLOSED))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case REMOTELY_CLOSED:
|
||||
case CLOSING:
|
||||
{
|
||||
close();
|
||||
return true;
|
||||
}
|
||||
|
@ -389,8 +461,18 @@ public class HTTP2Stream extends IdleTimeout implements IStream, Callback, Dumpa
|
|||
@Override
|
||||
public void close()
|
||||
{
|
||||
if (closeState.getAndSet(CloseState.CLOSED) != CloseState.CLOSED)
|
||||
CloseState oldState = closeState.getAndSet(CloseState.CLOSED);
|
||||
if (oldState != CloseState.CLOSED)
|
||||
{
|
||||
int deltaClosing = oldState == CloseState.CLOSING ? -1 : 0;
|
||||
updateStreamCount(-1, deltaClosing);
|
||||
onClose();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateStreamCount(int deltaStream, int deltaClosing)
|
||||
{
|
||||
((HTTP2Session)session).updateStreamCount(isLocal(), deltaStream, deltaClosing);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -76,12 +76,10 @@ public interface IStream extends Stream, Closeable
|
|||
* <p>Updates the close state of this stream.</p>
|
||||
*
|
||||
* @param update whether to update the close state
|
||||
* @param local whether the update comes from a local operation
|
||||
* (such as sending a frame that ends the stream)
|
||||
* or a remote operation (such as receiving a frame
|
||||
* @param event the event that caused the close state update
|
||||
* @return whether the stream has been fully closed by this invocation
|
||||
*/
|
||||
public boolean updateClose(boolean update, boolean local);
|
||||
public boolean updateClose(boolean update, CloseState.Event event);
|
||||
|
||||
/**
|
||||
* <p>Forcibly closes this stream.</p>
|
||||
|
|
|
@ -16,35 +16,27 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http2.client.http;
|
||||
|
||||
package org.eclipse.jetty.gcloud.session;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.jetty.server.session.AbstractModifyMaxInactiveIntervalTest;
|
||||
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
|
||||
import org.junit.After;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* ModifyMaxInactiveIntervalTest
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ModifyMaxInactiveIntervalTest extends AbstractModifyMaxInactiveIntervalTest
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
|
||||
public class EmptyServerHandler extends AbstractHandler.ErrorDispatchHandler
|
||||
{
|
||||
|
||||
@After
|
||||
public void teardown () throws Exception
|
||||
{
|
||||
GCloudTestSuite.__testSupport.deleteSessions();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
protected final void doNonErrorHandle(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
jettyRequest.setHandled(true);
|
||||
service(target, jettyRequest, request, response);
|
||||
}
|
||||
|
||||
protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
return GCloudSessionTestSupport.newSessionDataStoreFactory(GCloudTestSuite.__testSupport.getDatastore());
|
||||
}
|
||||
}
|
|
@ -18,11 +18,10 @@
|
|||
|
||||
package org.eclipse.jetty.http2.client.http;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
@ -32,7 +31,6 @@ import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory;
|
|||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -53,12 +51,11 @@ public class MaxConcurrentStreamsTest extends AbstractTest
|
|||
public void testOneConcurrentStream() throws Exception
|
||||
{
|
||||
long sleep = 1000;
|
||||
start(1, new AbstractHandler()
|
||||
start(1, new EmptyServerHandler()
|
||||
{
|
||||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
// Sleep a bit to allow the second request to be queued.
|
||||
sleep(sleep);
|
||||
}
|
||||
|
@ -91,17 +88,42 @@ public class MaxConcurrentStreamsTest extends AbstractTest
|
|||
Assert.assertTrue(latch.await(5 * sleep, TimeUnit.MILLISECONDS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testManyIterationsWithConcurrentStreams() throws Exception
|
||||
{
|
||||
int concurrency = 1;
|
||||
start(concurrency, new EmptyServerHandler());
|
||||
|
||||
int iterations = 50;
|
||||
IntStream.range(0, concurrency).parallel().forEach(i ->
|
||||
IntStream.range(0, iterations).forEach(j ->
|
||||
{
|
||||
try
|
||||
{
|
||||
ContentResponse response = client.newRequest("localhost", connector.getLocalPort())
|
||||
.path("/" + i + "_" + j)
|
||||
.timeout(5, TimeUnit.SECONDS)
|
||||
.send();
|
||||
Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
throw new RuntimeException(x);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTwoConcurrentStreamsThirdWaits() throws Exception
|
||||
{
|
||||
int maxStreams = 2;
|
||||
long sleep = 1000;
|
||||
start(maxStreams, new AbstractHandler()
|
||||
start(maxStreams, new EmptyServerHandler()
|
||||
{
|
||||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
sleep(sleep);
|
||||
}
|
||||
});
|
||||
|
@ -140,12 +162,11 @@ public class MaxConcurrentStreamsTest extends AbstractTest
|
|||
public void testAbortedWhileQueued() throws Exception
|
||||
{
|
||||
long sleep = 1000;
|
||||
start(1, new AbstractHandler()
|
||||
start(1, new EmptyServerHandler()
|
||||
{
|
||||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
sleep(sleep);
|
||||
}
|
||||
});
|
||||
|
@ -170,12 +191,11 @@ public class MaxConcurrentStreamsTest extends AbstractTest
|
|||
{
|
||||
int maxConcurrent = 10;
|
||||
long sleep = 500;
|
||||
start(maxConcurrent, new AbstractHandler()
|
||||
start(maxConcurrent, new EmptyServerHandler()
|
||||
{
|
||||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
sleep(sleep);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -303,9 +303,10 @@ public class HttpTransportOverHTTP2 implements HttpTransport
|
|||
commit = this.commit;
|
||||
if (state == State.WRITING)
|
||||
{
|
||||
this.state = State.IDLE;
|
||||
callback = this.callback;
|
||||
this.callback = null;
|
||||
this.state = State.IDLE;
|
||||
this.commit = false;
|
||||
}
|
||||
}
|
||||
if (LOG.isDebugEnabled())
|
||||
|
@ -330,13 +331,13 @@ public class HttpTransportOverHTTP2 implements HttpTransport
|
|||
if (state == State.WRITING)
|
||||
{
|
||||
this.state = State.FAILED;
|
||||
this.failure = failure;
|
||||
callback = this.callback;
|
||||
this.callback = null;
|
||||
this.failure = failure;
|
||||
}
|
||||
}
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug(String.format("HTTP2 Response #%d/%h failed to %s", stream.getId(), stream.getSession(), commit ? "commit" : "flush"), failure);
|
||||
LOG.debug(String.format("HTTP2 Response #%d/%h %s %s", stream.getId(), stream.getSession(), commit ? "commit" : "flush", callback == null ? "ignored" : "failed"), failure);
|
||||
if (callback != null)
|
||||
callback.failed(failure);
|
||||
}
|
||||
|
|
|
@ -24,9 +24,9 @@ import java.util.Set;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.eclipse.jetty.server.SessionIdManager;
|
||||
import org.eclipse.jetty.server.session.AbstractSessionDataStore;
|
||||
import org.eclipse.jetty.server.session.SessionData;
|
||||
import org.eclipse.jetty.server.session.UnreadableSessionDataException;
|
||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
|
@ -84,8 +84,8 @@ public class InfinispanSessionDataStore extends AbstractSessionDataStore
|
|||
@Override
|
||||
public SessionData load(String id) throws Exception
|
||||
{
|
||||
final AtomicReference<SessionData> reference = new AtomicReference<SessionData>();
|
||||
final AtomicReference<Exception> exception = new AtomicReference<Exception>();
|
||||
final AtomicReference<SessionData> reference = new AtomicReference<>();
|
||||
final AtomicReference<Exception> exception = new AtomicReference<>();
|
||||
|
||||
Runnable load = new Runnable()
|
||||
{
|
||||
|
@ -103,7 +103,7 @@ public class InfinispanSessionDataStore extends AbstractSessionDataStore
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
exception.set(e);
|
||||
exception.set(new UnreadableSessionDataException(id, _context, e));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -139,11 +139,10 @@ public class InfinispanSessionDataStore extends AbstractSessionDataStore
|
|||
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
Set<String> expired = new HashSet<String>();
|
||||
Set<String> expired = new HashSet<>();
|
||||
|
||||
//TODO if there is NOT an idle timeout set on entries in infinispan, need to check other sessions
|
||||
//that are not currently in the SessionDataStore (eg they've been passivated)
|
||||
|
||||
//that are not currently in the SessionDataStore (eg they've been passivated)
|
||||
for (String candidate:candidates)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
|
@ -205,8 +204,6 @@ public class InfinispanSessionDataStore extends AbstractSessionDataStore
|
|||
@Override
|
||||
public void doStore(String id, SessionData data, long lastSaveTime) throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
//Put an idle timeout on the cache entry if the session is not immortal -
|
||||
//if no requests arrive at any node before this timeout occurs, or no node
|
||||
//scavenges the session before this timeout occurs, the session will be removed.
|
||||
|
@ -218,10 +215,6 @@ public class InfinispanSessionDataStore extends AbstractSessionDataStore
|
|||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Session {} saved to infinispan, expires {} ", id, data.getExpiry());
|
||||
} catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -265,8 +258,8 @@ public class InfinispanSessionDataStore extends AbstractSessionDataStore
|
|||
{
|
||||
// TODO find a better way to do this that does not pull into memory the
|
||||
// whole session object
|
||||
final AtomicReference<Boolean> reference = new AtomicReference<Boolean>();
|
||||
final AtomicReference<Exception> exception = new AtomicReference<Exception>();
|
||||
final AtomicReference<Boolean> reference = new AtomicReference<>();
|
||||
final AtomicReference<Exception> exception = new AtomicReference<>();
|
||||
|
||||
Runnable load = new Runnable()
|
||||
{
|
||||
|
|
|
@ -154,8 +154,13 @@ public class ManagedSelector extends ContainerLifeCycle implements Dumpable
|
|||
_selecting = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (selector != null)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("wakeup on submit {}", this);
|
||||
selector.wakeup();
|
||||
}
|
||||
}
|
||||
|
||||
private void execute(Runnable task)
|
||||
|
@ -258,6 +263,8 @@ public class ManagedSelector extends ContainerLifeCycle implements Dumpable
|
|||
_updates.addFirst(dump);
|
||||
_selecting = false;
|
||||
}
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("wakeup on dump {}", this);
|
||||
selector.wakeup();
|
||||
keys = dump.get(5, TimeUnit.SECONDS);
|
||||
String keysAt = DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(ZonedDateTime.now());
|
||||
|
@ -370,7 +377,11 @@ public class ManagedSelector extends ContainerLifeCycle implements Dumpable
|
|||
LOG.debug("updates {}",updates);
|
||||
|
||||
if (selector != null)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("wakeup on updates {}", this);
|
||||
selector.wakeup();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean select()
|
||||
|
@ -381,12 +392,16 @@ public class ManagedSelector extends ContainerLifeCycle implements Dumpable
|
|||
if (selector != null && selector.isOpen())
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Selector {} waiting on select", selector);
|
||||
LOG.debug("Selector {} waiting with {} keys", selector, selector.keys().size());
|
||||
int selected = selector.select();
|
||||
if (selected == 0)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Selector {} woken with none selected", selector);
|
||||
selected = selector.selectNow();
|
||||
}
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Selector {} woken up from select, {}/{} selected", selector, selected, selector.keys().size());
|
||||
LOG.debug("Selector {} woken up from select, {}/{}/{} selected", selector, selected, selector.selectedKeys().size(), selector.keys().size());
|
||||
|
||||
int updates;
|
||||
synchronized(ManagedSelector.this)
|
||||
|
|
|
@ -78,35 +78,6 @@
|
|||
<artifactId>ant</artifactId>
|
||||
<version>1.8.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>apache-jstl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-servlets</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-proxy</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.http2</groupId>
|
||||
<artifactId>http2-client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<reporting>
|
||||
<plugins>
|
||||
|
|
|
@ -148,24 +148,6 @@
|
|||
<artifactId>javax.transaction-api</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.http2</groupId>
|
||||
<artifactId>http2-client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.http2</groupId>
|
||||
<artifactId>http2-http-client-transport</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-home</artifactId>
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
invoker.goals = verify -V
|
||||
#test-compile failsafe:integration-test
|
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty.its.jetty-run-package-jar-mojo-it</groupId>
|
||||
<artifactId>jetty-simple-project</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>jetty-simple-base</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Jetty :: Simple :: Base</name>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<type>jar</type>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-perf-helper</artifactId>
|
||||
<version>1.0.5</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.8.1</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -16,35 +16,30 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.server.session;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
package org.eclipse.jetty.its.jetty_run_mojo_it;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* ClusteredLastAccessTimeTest
|
||||
*
|
||||
*/
|
||||
public class ClusteredLastAccessTimeTest extends AbstractClusteredLastAccessTimeTest
|
||||
@WebServlet("/hello")
|
||||
public class HelloServlet
|
||||
extends HttpServlet
|
||||
{
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
protected void doGet( HttpServletRequest req, HttpServletResponse resp )
|
||||
throws ServletException, IOException
|
||||
{
|
||||
return JdbcTestHelper.newSessionDataStoreFactory();
|
||||
String who = req.getParameter( "name" );
|
||||
|
||||
resp.getWriter().write( "hello " + (who == null ? "unknown" : who) );
|
||||
}
|
||||
@Test
|
||||
@Override
|
||||
public void testLastAccessTime() throws Exception
|
||||
{
|
||||
super.testLastAccessTime();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception
|
||||
{
|
||||
JdbcTestHelper.shutdown(null);
|
||||
}
|
||||
|
||||
}
|
|
@ -17,36 +17,25 @@
|
|||
//
|
||||
|
||||
|
||||
package org.eclipse.jetty.server.session;
|
||||
package org.eclipse.jetty.its.jetty_run_mojo_it;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
public class SessionInvalidateCreateScavengeTest extends AbstractSessionInvalidateCreateScavengeTest
|
||||
public class PingServlet
|
||||
extends HttpServlet
|
||||
{
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
protected void doGet( HttpServletRequest req, HttpServletResponse resp )
|
||||
throws ServletException, IOException
|
||||
{
|
||||
return JdbcTestHelper.newSessionDataStoreFactory();
|
||||
}
|
||||
|
||||
String who = req.getParameter( "name" );
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testSessionScavenge() throws Exception
|
||||
{
|
||||
super.testSessionScavenge();
|
||||
resp.getWriter().write( "pong " + (who == null ? "unknown" : who) );
|
||||
}
|
||||
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception
|
||||
{
|
||||
JdbcTestHelper.shutdown(null);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<web-fragment
|
||||
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-fragment_3_1.xsd"
|
||||
version="3.1">
|
||||
|
||||
<name>FragmentA</name>
|
||||
|
||||
<ordering>
|
||||
<after><others/></after>
|
||||
</ordering>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Ping</servlet-name>
|
||||
<servlet-class>org.eclipse.jetty.its.jetty_run_mojo_it.PingServlet</servlet-class>
|
||||
<init-param>
|
||||
<param-name>extra1</param-name><param-value>123</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>extra2</param-name><param-value>345</param-value>
|
||||
</init-param>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Ping</servlet-name>
|
||||
<url-pattern>/ping</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
|
||||
</web-fragment>
|
|
@ -0,0 +1,122 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty.its.jetty-run-package-jar-mojo-it</groupId>
|
||||
<artifactId>jetty-simple-project</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>jetty-simple-webapp</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Jetty :: Simple :: Webapp as a Jar</name>
|
||||
|
||||
|
||||
<properties>
|
||||
<jetty.port.file>${project.build.directory}/jetty-run-war-port.txt</jetty.port.file>
|
||||
</properties>
|
||||
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.its.jetty-run-package-jar-mojo-it</groupId>
|
||||
<artifactId>jetty-simple-base</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-servlet</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-client</artifactId>
|
||||
<version>@project.version@</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>@surefireVersion@</version>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
<systemPropertyVariables>
|
||||
<jetty.port.file>${jetty.port.file}</jetty.port.file>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>@surefireVersion@</version>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<jetty.port.file>${jetty.port.file}</jetty.port.file>
|
||||
</systemPropertyVariables>
|
||||
<includes>
|
||||
<include>**/*TestHelloServlet*</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>integration-test</id>
|
||||
<goals>
|
||||
<goal>integration-test</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>verify</id>
|
||||
<goals>
|
||||
<goal>verify</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>start-jetty</id>
|
||||
<phase>test-compile</phase>
|
||||
<goals>
|
||||
<goal>run-war</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<supportedPackagings>
|
||||
<supportedPackaging>jar</supportedPackaging>
|
||||
</supportedPackagings>
|
||||
<nonBlocking>true</nonBlocking>
|
||||
<systemProperties>
|
||||
<systemProperty>
|
||||
<name>jetty.port.file</name>
|
||||
<value>${jetty.port.file}</value>
|
||||
</systemProperty>
|
||||
</systemProperties>
|
||||
<jettyXml>${basedir}/src/config/jetty.xml</jettyXml>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
</project>
|
|
@ -0,0 +1,40 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
<New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
|
||||
<Set name="secureScheme">https</Set>
|
||||
<Set name="securePort"><Property name="jetty.secure.port" default="8443" /></Set>
|
||||
<Set name="outputBufferSize">32768</Set>
|
||||
<Set name="requestHeaderSize">8192</Set>
|
||||
<Set name="responseHeaderSize">8192</Set>
|
||||
<Set name="headerCacheSize">512</Set>
|
||||
</New>
|
||||
|
||||
<Call name="addConnector">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.server.ServerConnector">
|
||||
<Arg name="server"><Ref refid="Server" /></Arg>
|
||||
<Arg name="factories">
|
||||
<Array type="org.eclipse.jetty.server.ConnectionFactory">
|
||||
<Item>
|
||||
<New class="org.eclipse.jetty.server.HttpConnectionFactory">
|
||||
<Arg name="config"><Ref refid="httpConfig" /></Arg>
|
||||
</New>
|
||||
</Item>
|
||||
</Array>
|
||||
</Arg>
|
||||
<Call name="addLifeCycleListener">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.maven.plugin.ServerConnectorListener">
|
||||
<Set name="fileName"><Property name="jetty.port.file" default="port.txt"/></Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
<Set name="host"><Property name="jetty.host" /></Set>
|
||||
<Set name="port"><Property name="jetty.port" default="0" />0</Set>
|
||||
<Set name="idleTimeout">30000</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
</Configure>
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0"?>
|
||||
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
|
||||
version="3.1">
|
||||
<display-name>Jetty Simple Webapp run-mojo-it</display-name>
|
||||
</web-app>
|
|
@ -0,0 +1,94 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.its.jetty_run_forked_mojo_it;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.LineNumberReader;
|
||||
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class TestGetContent
|
||||
|
||||
{
|
||||
@Test
|
||||
public void get_ping_response()
|
||||
throws Exception
|
||||
{
|
||||
|
||||
int port = getPort();
|
||||
Assert.assertTrue(port > 0);
|
||||
HttpClient httpClient = new HttpClient();
|
||||
try
|
||||
{
|
||||
httpClient.start();
|
||||
|
||||
String response = httpClient.GET( "http://localhost:" + port + "/hello?name=beer" ).getContentAsString();
|
||||
|
||||
Assert.assertEquals( "hello beer", response.trim() );
|
||||
|
||||
response = httpClient.GET( "http://localhost:" + port + "/ping?name=beer" ).getContentAsString();
|
||||
|
||||
Assert.assertEquals( "pong beer", response.trim() );
|
||||
}
|
||||
finally
|
||||
{
|
||||
httpClient.stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int getPort()
|
||||
throws Exception
|
||||
{
|
||||
int attempts = 20;
|
||||
int port = -1;
|
||||
String s = System.getProperty("jetty.port.file");
|
||||
Assert.assertNotNull(s);
|
||||
File f = new File(s);
|
||||
while (true)
|
||||
{
|
||||
if (f.exists())
|
||||
{
|
||||
try (FileReader r = new FileReader(f);
|
||||
LineNumberReader lnr = new LineNumberReader(r);
|
||||
)
|
||||
{
|
||||
s = lnr.readLine();
|
||||
Assert.assertNotNull(s);
|
||||
port = Integer.parseInt(s.trim());
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (--attempts < 0)
|
||||
break;
|
||||
else
|
||||
Thread.currentThread().sleep(100);
|
||||
}
|
||||
}
|
||||
return port;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.eclipse.jetty.its.jetty-run-package-jar-mojo-it</groupId>
|
||||
<artifactId>jetty-simple-project</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>Jetty :: Simple</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<maven-war-plugin-version>3.0.0</maven-war-plugin-version>
|
||||
<jetty.version>@project.version@</jetty.version>
|
||||
</properties>
|
||||
|
||||
<modules>
|
||||
<module>jetty-simple-base</module>
|
||||
<module>jetty-simple-webapp</module>
|
||||
</modules>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.its.jetty-run-package-jar-mojo-it</groupId>
|
||||
<artifactId>jetty-simple-base</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<type>jar</type>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.7.21</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.5</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-servlet</artifactId>
|
||||
<version>${jetty.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.5.1</version>
|
||||
<configuration>
|
||||
<target>1.8</target>
|
||||
<source>1.8</source>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-maven-plugin</artifactId>
|
||||
<version>${jetty.version}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -28,6 +28,7 @@ import java.nio.file.Path;
|
|||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
@ -288,19 +289,32 @@ public abstract class AbstractJettyMojo extends AbstractMojo
|
|||
* @parameter default-value="false"
|
||||
*/
|
||||
protected boolean nonBlocking = false;
|
||||
|
||||
/**
|
||||
* Per default this goal support only <code>war</code> packaging.
|
||||
* If your project use an other type please configure it here.
|
||||
*
|
||||
* @parameter
|
||||
*/
|
||||
protected List<String> supportedPackagings = Collections.singletonList( "war");
|
||||
|
||||
|
||||
public abstract void restartWebApp(boolean reconfigureScanner) throws Exception;
|
||||
|
||||
|
||||
public abstract void checkPomConfiguration() throws MojoExecutionException;
|
||||
|
||||
public abstract void checkPackagingConfiguration() throws MojoExecutionException;
|
||||
|
||||
public abstract void configureScanner () throws MojoExecutionException;
|
||||
|
||||
|
||||
|
||||
public abstract void configureScanner () throws MojoExecutionException;
|
||||
|
||||
|
||||
public void checkPackagingConfiguration() throws MojoExecutionException
|
||||
{
|
||||
if (!supportedPackagings.contains( project.getPackaging() ))
|
||||
{
|
||||
getLog().info( "Your project packaging is not supported by this plugin" );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -64,24 +64,6 @@ public class JettyDeployWar extends JettyRunWarMojo
|
|||
nonBlocking = daemon;
|
||||
super.execute();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.maven.plugin.JettyRunWarMojo#checkPackagingConfiguration()
|
||||
*/
|
||||
@Override
|
||||
public void checkPackagingConfiguration() throws MojoExecutionException
|
||||
{
|
||||
return; //do not require this to be a war project
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.net.URL;
|
|||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
|
@ -164,7 +165,6 @@ public class JettyRunMojo extends AbstractJettyMojo
|
|||
|
||||
|
||||
protected Resource originalBaseResource;
|
||||
|
||||
|
||||
@Parameter(defaultValue = "${reactorProjects}", readonly = true, required = true)
|
||||
private List<MavenProject> reactorProjects;
|
||||
|
@ -178,21 +178,6 @@ public class JettyRunMojo extends AbstractJettyMojo
|
|||
warPluginInfo = new WarPluginInfo(project);
|
||||
super.execute();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.maven.plugin.AbstractJettyMojo#checkPackagingConfiguration()
|
||||
*/
|
||||
@Override
|
||||
public void checkPackagingConfiguration() throws MojoExecutionException
|
||||
{
|
||||
if ( !"war".equals( project.getPackaging() ))
|
||||
throw new MojoExecutionException("Not war packaging");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Verify the configuration given in the pom.
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
package org.eclipse.jetty.maven.plugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
|
@ -57,10 +58,6 @@ public class JettyRunWarExplodedMojo extends AbstractJettyMojo
|
|||
*/
|
||||
private File war;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.maven.plugin.AbstractJettyMojo#execute()
|
||||
*/
|
||||
|
@ -78,18 +75,6 @@ public class JettyRunWarExplodedMojo extends AbstractJettyMojo
|
|||
server.setStopAtShutdown(true); //as we will normally be stopped with a cntrl-c, ensure server stopped
|
||||
super.finishConfigurationBeforeStart();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.maven.plugin.AbstractJettyMojo#checkPackagingConfiguration()
|
||||
*/
|
||||
@Override
|
||||
public void checkPackagingConfiguration() throws MojoExecutionException
|
||||
{
|
||||
if ( !"war".equals( project.getPackaging() ))
|
||||
throw new MojoExecutionException("Not war packaging");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
package org.eclipse.jetty.maven.plugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
|
@ -55,7 +56,6 @@ public class JettyRunWarMojo extends AbstractJettyMojo
|
|||
*/
|
||||
private File war;
|
||||
|
||||
|
||||
/**
|
||||
* @see org.apache.maven.plugin.Mojo#execute()
|
||||
*/
|
||||
|
@ -95,20 +95,6 @@ public class JettyRunWarMojo extends AbstractJettyMojo
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.maven.plugin.AbstractJettyMojo#checkPackagingConfiguration()
|
||||
*/
|
||||
@Override
|
||||
public void checkPackagingConfiguration() throws MojoExecutionException
|
||||
{
|
||||
if ( !"war".equals( project.getPackaging() ))
|
||||
throw new MojoExecutionException("Not war packaging");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see AbstractJettyMojo#configureScanner()
|
||||
*/
|
||||
|
|
|
@ -48,15 +48,6 @@ public class JettyStartMojo extends JettyRunMojo
|
|||
super.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.maven.plugin.AbstractJettyMojo#checkPackagingConfiguration()
|
||||
*/
|
||||
@Override
|
||||
public void checkPackagingConfiguration() throws MojoExecutionException
|
||||
{
|
||||
return; //don't check that the project is a war
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishConfigurationBeforeStart() throws Exception
|
||||
{
|
||||
|
|
|
@ -37,12 +37,13 @@ public abstract class NoSqlSessionDataStore extends AbstractSessionDataStore
|
|||
public class NoSqlSessionData extends SessionData
|
||||
{
|
||||
private Object _version;
|
||||
private Set<String> _dirtyAttributes = new HashSet<String>();
|
||||
private Set<String> _dirtyAttributes = new HashSet<>();
|
||||
|
||||
|
||||
public NoSqlSessionData(String id, String cpath, String vhost, long created, long accessed, long lastAccessed, long maxInactiveMs)
|
||||
{
|
||||
super(id, cpath, vhost, created, accessed, lastAccessed, maxInactiveMs);
|
||||
setVersion (new Long(0));
|
||||
}
|
||||
|
||||
public void setVersion (Object v)
|
||||
|
|
|
@ -19,6 +19,20 @@
|
|||
|
||||
package org.eclipse.jetty.nosql.mongodb;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.eclipse.jetty.nosql.NoSqlSessionDataStore;
|
||||
import org.eclipse.jetty.server.session.SessionContext;
|
||||
import org.eclipse.jetty.server.session.SessionData;
|
||||
import org.eclipse.jetty.server.session.UnreadableSessionDataException;
|
||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
import com.mongodb.BasicDBList;
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.BasicDBObjectBuilder;
|
||||
|
@ -29,26 +43,6 @@ import com.mongodb.MongoException;
|
|||
import com.mongodb.WriteConcern;
|
||||
import com.mongodb.WriteResult;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.eclipse.jetty.nosql.NoSqlSessionDataStore;
|
||||
import org.eclipse.jetty.server.session.SessionData;
|
||||
import org.eclipse.jetty.util.ClassLoadingObjectInputStream;
|
||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
/**
|
||||
* MongoSessionDataStore
|
||||
*
|
||||
|
@ -108,12 +102,12 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
|
|||
/**
|
||||
* Special attribute for a session that is context-specific
|
||||
*/
|
||||
private final static String __METADATA = "__metadata__";
|
||||
public final static String __METADATA = "__metadata__";
|
||||
|
||||
/**
|
||||
* Name of nested document field containing 1 sub document per context for which the session id is in use
|
||||
*/
|
||||
private final static String __CONTEXT = "context";
|
||||
public final static String __CONTEXT = "context";
|
||||
|
||||
/**
|
||||
* Special attribute per session per context, incremented each time attributes are modified
|
||||
|
@ -131,6 +125,9 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
|
|||
*/
|
||||
public final static String __ACCESSED = "accessed";
|
||||
|
||||
|
||||
public final static String __LAST_ACCESSED = "lastAccessed";
|
||||
|
||||
/**
|
||||
* Time this session will expire, based on last access time and maxIdle
|
||||
*/
|
||||
|
@ -144,7 +141,7 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
|
|||
/**
|
||||
* Time of session creation
|
||||
*/
|
||||
private final static String __CREATED = "created";
|
||||
public final static String __CREATED = "created";
|
||||
|
||||
/**
|
||||
* Whether or not session is valid
|
||||
|
@ -188,8 +185,8 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
|
|||
@Override
|
||||
public SessionData load(String id) throws Exception
|
||||
{
|
||||
final AtomicReference<SessionData> reference = new AtomicReference<SessionData>();
|
||||
final AtomicReference<Exception> exception = new AtomicReference<Exception>();
|
||||
final AtomicReference<SessionData> reference = new AtomicReference<>();
|
||||
final AtomicReference<Exception> exception = new AtomicReference<>();
|
||||
Runnable r = new Runnable()
|
||||
{
|
||||
@Override
|
||||
|
@ -212,19 +209,20 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
|
|||
if (valid == null || !valid)
|
||||
return;
|
||||
|
||||
Object version = getNestedValue(sessionDocument, getContextSubfield(__VERSION));
|
||||
Long lastSaved = (Long)getNestedValue(sessionDocument, getContextSubfield(__LASTSAVED));
|
||||
String lastNode = (String)getNestedValue(sessionDocument, getContextSubfield(__LASTNODE));
|
||||
Object version = MongoUtils.getNestedValue(sessionDocument, getContextSubfield(__VERSION));
|
||||
Long lastSaved = (Long)MongoUtils.getNestedValue(sessionDocument, getContextSubfield(__LASTSAVED));
|
||||
String lastNode = (String)MongoUtils.getNestedValue(sessionDocument, getContextSubfield(__LASTNODE));
|
||||
|
||||
Long created = (Long)sessionDocument.get(__CREATED);
|
||||
Long accessed = (Long)sessionDocument.get(__ACCESSED);
|
||||
Long lastAccessed = (Long)sessionDocument.get(__LAST_ACCESSED);
|
||||
Long maxInactive = (Long)sessionDocument.get(__MAX_IDLE);
|
||||
Long expiry = (Long)sessionDocument.get(__EXPIRY);
|
||||
|
||||
NoSqlSessionData data = null;
|
||||
|
||||
// get the session for the context
|
||||
DBObject sessionSubDocumentForContext = (DBObject)getNestedValue(sessionDocument,getContextField());
|
||||
DBObject sessionSubDocumentForContext = (DBObject)MongoUtils.getNestedValue(sessionDocument,getContextField());
|
||||
|
||||
if (LOG.isDebugEnabled()) LOG.debug("attrs {}", sessionSubDocumentForContext);
|
||||
|
||||
|
@ -234,7 +232,7 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
|
|||
LOG.debug("Session {} present for context {}", id, _context);
|
||||
|
||||
//only load a session if it exists for this context
|
||||
data = (NoSqlSessionData)newSessionData(id, created, accessed, accessed, maxInactive);
|
||||
data = (NoSqlSessionData)newSessionData(id, created, accessed, (lastAccessed == null? accessed:lastAccessed), maxInactive);
|
||||
data.setVersion(version);
|
||||
data.setExpiry(expiry);
|
||||
data.setContextPath(_context.getCanonicalContextPath());
|
||||
|
@ -248,8 +246,8 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
|
|||
//skip special metadata attribute which is not one of the actual session attributes
|
||||
if ( __METADATA.equals(name) )
|
||||
continue;
|
||||
String attr = decodeName(name);
|
||||
Object value = decodeValue(sessionSubDocumentForContext.get(name));
|
||||
String attr = MongoUtils.decodeName(name);
|
||||
Object value = MongoUtils.decodeValue(sessionSubDocumentForContext.get(name));
|
||||
attributes.put(attr,value);
|
||||
}
|
||||
|
||||
|
@ -265,7 +263,7 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
exception.set(e);
|
||||
exception.set(new UnreadableSessionDataException(id, _context, e));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -298,7 +296,7 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
|
|||
|
||||
if (sessionDocument != null)
|
||||
{
|
||||
DBObject c = (DBObject)getNestedValue(sessionDocument, __CONTEXT);
|
||||
DBObject c = (DBObject)MongoUtils.getNestedValue(sessionDocument, __CONTEXT);
|
||||
if (c == null)
|
||||
{
|
||||
//delete whole doc
|
||||
|
@ -326,7 +324,7 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
|
|||
BasicDBObject unsets = new BasicDBObject();
|
||||
unsets.put(getContextField(),1);
|
||||
remove.put("$unset",unsets);
|
||||
WriteResult result = _dbSessions.update(mongoKey,remove,false,false,WriteConcern.SAFE);
|
||||
_dbSessions.update(mongoKey,remove,false,false,WriteConcern.SAFE);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
@ -347,6 +345,7 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
|
|||
DBObject fields = new BasicDBObject();
|
||||
fields.put(__EXPIRY, 1);
|
||||
fields.put(__VALID, 1);
|
||||
fields.put(getContextSubfield(__VERSION), 1);
|
||||
|
||||
DBObject sessionDocument = _dbSessions.findOne(new BasicDBObject(__ID, id), fields);
|
||||
|
||||
|
@ -359,9 +358,16 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
|
|||
|
||||
Long expiry = (Long)sessionDocument.get(__EXPIRY);
|
||||
|
||||
if (expiry.longValue() <= 0)
|
||||
return true; //never expires, its good
|
||||
return (expiry.longValue() > System.currentTimeMillis()); //expires later
|
||||
//expired?
|
||||
if (expiry.longValue() > 0 && expiry.longValue() < System.currentTimeMillis())
|
||||
return false; //it's expired
|
||||
|
||||
//does it exist for this context?
|
||||
Object version = MongoUtils.getNestedValue(sessionDocument, getContextSubfield(__VERSION));
|
||||
if (version == null)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -425,24 +431,51 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
|
|||
if (LOG.isDebugEnabled()) LOG.debug("{} Mongo found old expired session {}", _context, id+" exp="+session.get(__EXPIRY));
|
||||
expiredSessions.add(id);
|
||||
}
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
oldExpiredSessions.close();
|
||||
if (oldExpiredSessions != null)
|
||||
oldExpiredSessions.close();
|
||||
}
|
||||
|
||||
|
||||
//check through sessions that were candidates, but not found as expired.
|
||||
//they may no longer be persisted, in which case they are treated as expired.
|
||||
for (String c:candidates)
|
||||
{
|
||||
if (!expiredSessions.contains(c))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!exists(c))
|
||||
expiredSessions.add(c);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.warn("Problem checking potentially expired session {}", c, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return expiredSessions;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.SessionDataStore#initialize(org.eclipse.jetty.server.session.SessionContext)
|
||||
*/
|
||||
public void initialize (SessionContext context) throws Exception
|
||||
{
|
||||
if (isStarted())
|
||||
throw new IllegalStateException("Context set after SessionDataStore started");
|
||||
_context = context;
|
||||
ensureIndexes();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractSessionDataStore#doStore(String, SessionData, long)
|
||||
*/
|
||||
@Override
|
||||
public void doStore(String id, SessionData data, long lastSaveTime) throws Exception
|
||||
{
|
||||
NoSqlSessionData nsqd = (NoSqlSessionData)data;
|
||||
|
||||
{
|
||||
// Form query for upsert
|
||||
BasicDBObject key = new BasicDBObject(__ID, id);
|
||||
|
||||
|
@ -459,21 +492,21 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
|
|||
{
|
||||
upsert = true;
|
||||
version = new Long(1);
|
||||
sets.put(__CREATED,nsqd.getCreated());
|
||||
sets.put(__CREATED,data.getCreated());
|
||||
sets.put(__VALID,true);
|
||||
sets.put(getContextSubfield(__VERSION),version);
|
||||
sets.put(getContextSubfield(__LASTSAVED), data.getLastSaved());
|
||||
sets.put(getContextSubfield(__LASTNODE), data.getLastNode());
|
||||
sets.put(__MAX_IDLE, nsqd.getMaxInactiveMs());
|
||||
sets.put(__EXPIRY, nsqd.getExpiry());
|
||||
nsqd.setVersion(version);
|
||||
sets.put(__MAX_IDLE, data.getMaxInactiveMs());
|
||||
sets.put(__EXPIRY, data.getExpiry());
|
||||
((NoSqlSessionData)data).setVersion(version);
|
||||
}
|
||||
else
|
||||
{
|
||||
sets.put(getContextSubfield(__LASTSAVED), data.getLastSaved());
|
||||
sets.put(getContextSubfield(__LASTNODE), data.getLastNode());
|
||||
version = new Long(((Number)version).longValue() + 1);
|
||||
nsqd.setVersion(version);
|
||||
((NoSqlSessionData)data).setVersion(version);
|
||||
update.put("$inc",_version_1);
|
||||
//if max idle time and/or expiry is smaller for this context, then choose that for the whole session doc
|
||||
BasicDBObject fields = new BasicDBObject();
|
||||
|
@ -487,23 +520,24 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
|
|||
tmpLong = (Long)o.get(__EXPIRY);
|
||||
long currentExpiry = (tmpLong == null? 0 : tmpLong.longValue());
|
||||
|
||||
if (currentMaxIdle != nsqd.getMaxInactiveMs())
|
||||
sets.put(__MAX_IDLE, nsqd.getMaxInactiveMs());
|
||||
if (currentMaxIdle != data.getMaxInactiveMs())
|
||||
sets.put(__MAX_IDLE, data.getMaxInactiveMs());
|
||||
|
||||
if (currentExpiry != nsqd.getExpiry())
|
||||
sets.put(__EXPIRY, nsqd.getExpiry());
|
||||
if (currentExpiry != data.getExpiry())
|
||||
sets.put(__EXPIRY, data.getExpiry());
|
||||
}
|
||||
else
|
||||
LOG.warn("Session {} not found, can't update", id);
|
||||
}
|
||||
|
||||
sets.put(__ACCESSED, nsqd.getAccessed());
|
||||
sets.put(__ACCESSED, data.getAccessed());
|
||||
sets.put(__LAST_ACCESSED, data.getLastAccessed());
|
||||
|
||||
Set<String> names = nsqd.takeDirtyAttributes();
|
||||
Set<String> names = ((NoSqlSessionData)data).takeDirtyAttributes();
|
||||
|
||||
if (lastSaveTime <= 0)
|
||||
{
|
||||
names.addAll(nsqd.getAllAttributeNames()); // note dirty may include removed names
|
||||
names.addAll(((NoSqlSessionData)data).getAllAttributeNames()); // note dirty may include removed names
|
||||
}
|
||||
|
||||
|
||||
|
@ -511,9 +545,9 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
|
|||
{
|
||||
Object value = data.getAttribute(name);
|
||||
if (value == null)
|
||||
unsets.put(getContextField() + "." + encodeName(name),1);
|
||||
unsets.put(getContextField() + "." + MongoUtils.encodeName(name),1);
|
||||
else
|
||||
sets.put(getContextField() + "." + encodeName(name),encodeName(value));
|
||||
sets.put(getContextField() + "." + MongoUtils.encodeName(name), MongoUtils.encodeName(value));
|
||||
}
|
||||
|
||||
// Do the upsert
|
||||
|
@ -521,37 +555,16 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
|
|||
update.put("$set",sets);
|
||||
if (!unsets.isEmpty())
|
||||
update.put("$unset",unsets);
|
||||
|
||||
WriteResult res = _dbSessions.update(key,update,upsert,false,WriteConcern.SAFE);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Save:db.sessions.update( {}, {},{} )", key, update, res);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void doStart() throws Exception
|
||||
{
|
||||
if (_dbSessions == null)
|
||||
throw new IllegalStateException("DBCollection not set");
|
||||
|
||||
_version_1 = new BasicDBObject(getContextSubfield(__VERSION),1);
|
||||
|
||||
ensureIndexes();
|
||||
|
||||
super.doStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStop() throws Exception
|
||||
{
|
||||
super.doStop();
|
||||
}
|
||||
|
||||
|
||||
protected void ensureIndexes() throws MongoException
|
||||
{
|
||||
DBObject idKey = BasicDBObjectBuilder.start().add("id", 1).get();
|
||||
_version_1 = new BasicDBObject(getContextSubfield(__VERSION),1);
|
||||
DBObject idKey = BasicDBObjectBuilder.start().add("id", 1).get();
|
||||
_dbSessions.createIndex(idKey,
|
||||
BasicDBObjectBuilder.start()
|
||||
.add("name", "id_1")
|
||||
|
@ -560,16 +573,19 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
|
|||
.add("unique", true)
|
||||
.get());
|
||||
|
||||
DBObject versionKey = BasicDBObjectBuilder.start().add("id", 1).add("version", 1).get();
|
||||
DBObject versionKey = BasicDBObjectBuilder.start().add("id", 1).add("version", 1).get();
|
||||
_dbSessions.createIndex(versionKey, BasicDBObjectBuilder.start()
|
||||
.add("name", "id_1_version_1")
|
||||
.add("ns", _dbSessions.getFullName())
|
||||
.add("sparse", false)
|
||||
.add("unique", true)
|
||||
.get());
|
||||
LOG.debug( "done ensure Mongodb indexes existing" );
|
||||
//TODO perhaps index on expiry time?
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*------------------------------------------------------------ */
|
||||
private String getContextField ()
|
||||
{
|
||||
|
@ -597,105 +613,6 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
|
|||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------ */
|
||||
protected Object decodeValue(final Object valueToDecode) throws IOException, ClassNotFoundException
|
||||
{
|
||||
if (valueToDecode == null || valueToDecode instanceof Number || valueToDecode instanceof String || valueToDecode instanceof Boolean || valueToDecode instanceof Date)
|
||||
{
|
||||
return valueToDecode;
|
||||
}
|
||||
else if (valueToDecode instanceof byte[])
|
||||
{
|
||||
final byte[] decodeObject = (byte[])valueToDecode;
|
||||
final ByteArrayInputStream bais = new ByteArrayInputStream(decodeObject);
|
||||
final ClassLoadingObjectInputStream objectInputStream = new ClassLoadingObjectInputStream(bais);
|
||||
return objectInputStream.readUnshared();
|
||||
}
|
||||
else if (valueToDecode instanceof DBObject)
|
||||
{
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
for (String name : ((DBObject)valueToDecode).keySet())
|
||||
{
|
||||
String attr = decodeName(name);
|
||||
map.put(attr,decodeValue(((DBObject)valueToDecode).get(name)));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalStateException(valueToDecode.getClass().toString());
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------ */
|
||||
protected String decodeName(String name)
|
||||
{
|
||||
return name.replace("%2E",".").replace("%25","%");
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------ */
|
||||
protected String encodeName(String name)
|
||||
{
|
||||
return name.replace("%","%25").replace(".","%2E");
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------ */
|
||||
protected Object encodeName(Object value) throws IOException
|
||||
{
|
||||
if (value instanceof Number || value instanceof String || value instanceof Boolean || value instanceof Date)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else if (value.getClass().equals(HashMap.class))
|
||||
{
|
||||
BasicDBObject o = new BasicDBObject();
|
||||
for (Map.Entry<?, ?> entry : ((Map<?, ?>)value).entrySet())
|
||||
{
|
||||
if (!(entry.getKey() instanceof String))
|
||||
{
|
||||
o = null;
|
||||
break;
|
||||
}
|
||||
o.append(encodeName(entry.getKey().toString()),encodeName(entry.getValue()));
|
||||
}
|
||||
|
||||
if (o != null)
|
||||
return o;
|
||||
}
|
||||
|
||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||
ObjectOutputStream out = new ObjectOutputStream(bout);
|
||||
out.reset();
|
||||
out.writeUnshared(value);
|
||||
out.flush();
|
||||
return bout.toByteArray();
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------ */
|
||||
/**
|
||||
* Dig through a given dbObject for the nested value
|
||||
*/
|
||||
private Object getNestedValue(DBObject dbObject, String nestedKey)
|
||||
{
|
||||
String[] keyChain = nestedKey.split("\\.");
|
||||
|
||||
DBObject temp = dbObject;
|
||||
|
||||
for (int i = 0; i < keyChain.length - 1; ++i)
|
||||
{
|
||||
temp = (DBObject)temp.get(keyChain[i]);
|
||||
|
||||
if ( temp == null )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return temp.get(keyChain[keyChain.length - 1]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.SessionDataStore#isPassivating()
|
||||
*/
|
||||
|
|
|
@ -149,4 +149,6 @@ public class MongoSessionDataStoreFactory extends AbstractSessionDataStoreFactor
|
|||
return store;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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 java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jetty.util.ClassLoadingObjectInputStream;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* MongoUtils
|
||||
*
|
||||
* Some utility methods for manipulating mongo data. This class facilitates testing.
|
||||
*
|
||||
*/
|
||||
public class MongoUtils
|
||||
{
|
||||
|
||||
public static Object decodeValue(final Object valueToDecode) throws IOException, ClassNotFoundException
|
||||
{
|
||||
if (valueToDecode == null || valueToDecode instanceof Number || valueToDecode instanceof String || valueToDecode instanceof Boolean || valueToDecode instanceof Date)
|
||||
{
|
||||
return valueToDecode;
|
||||
}
|
||||
else if (valueToDecode instanceof byte[])
|
||||
{
|
||||
final byte[] decodeObject = (byte[])valueToDecode;
|
||||
final ByteArrayInputStream bais = new ByteArrayInputStream(decodeObject);
|
||||
final ClassLoadingObjectInputStream objectInputStream = new ClassLoadingObjectInputStream(bais);
|
||||
return objectInputStream.readUnshared();
|
||||
}
|
||||
else if (valueToDecode instanceof DBObject)
|
||||
{
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
for (String name : ((DBObject)valueToDecode).keySet())
|
||||
{
|
||||
String attr = decodeName(name);
|
||||
map.put(attr,decodeValue(((DBObject)valueToDecode).get(name)));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalStateException(valueToDecode.getClass().toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static String decodeName(String name)
|
||||
{
|
||||
return name.replace("%2E",".").replace("%25","%");
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static String encodeName(String name)
|
||||
{
|
||||
return name.replace("%","%25").replace(".","%2E");
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static Object encodeName(Object value) throws IOException
|
||||
{
|
||||
if (value instanceof Number || value instanceof String || value instanceof Boolean || value instanceof Date)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else if (value.getClass().equals(HashMap.class))
|
||||
{
|
||||
BasicDBObject o = new BasicDBObject();
|
||||
for (Map.Entry<?, ?> entry : ((Map<?, ?>)value).entrySet())
|
||||
{
|
||||
if (!(entry.getKey() instanceof String))
|
||||
{
|
||||
o = null;
|
||||
break;
|
||||
}
|
||||
o.append(encodeName(entry.getKey().toString()),encodeName(entry.getValue()));
|
||||
}
|
||||
|
||||
if (o != null)
|
||||
return o;
|
||||
}
|
||||
|
||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||
ObjectOutputStream out = new ObjectOutputStream(bout);
|
||||
out.reset();
|
||||
out.writeUnshared(value);
|
||||
out.flush();
|
||||
return bout.toByteArray();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Dig through a given dbObject for the nested value
|
||||
*
|
||||
* @param dbObject the mongo object to search
|
||||
* @param nestedKey the field key to find
|
||||
*
|
||||
* @return the value of the field key
|
||||
*/
|
||||
public static Object getNestedValue(DBObject dbObject, String nestedKey)
|
||||
{
|
||||
String[] keyChain = nestedKey.split("\\.");
|
||||
|
||||
DBObject temp = dbObject;
|
||||
|
||||
for (int i = 0; i < keyChain.length - 1; ++i)
|
||||
{
|
||||
temp = (DBObject)temp.get(keyChain[i]);
|
||||
|
||||
if ( temp == null )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return temp.get(keyChain[keyChain.length - 1]);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -32,7 +32,6 @@ import org.eclipse.jetty.io.ssl.SslConnection;
|
|||
|
||||
public abstract class NegotiatingServerConnectionFactory extends AbstractConnectionFactory
|
||||
{
|
||||
|
||||
private final List<String> negotiatedProtocols;
|
||||
private String defaultProtocol;
|
||||
|
||||
|
@ -47,7 +46,7 @@ public abstract class NegotiatingServerConnectionFactory extends AbstractConnect
|
|||
{
|
||||
p = p.trim();
|
||||
if (!p.isEmpty())
|
||||
this.negotiatedProtocols.add(p.trim());
|
||||
this.negotiatedProtocols.add(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -75,25 +74,25 @@ public abstract class NegotiatingServerConnectionFactory extends AbstractConnect
|
|||
List<String> negotiated = this.negotiatedProtocols;
|
||||
if (negotiated.isEmpty())
|
||||
{
|
||||
// Generate list of protocols that we can negotiate
|
||||
// Generate list of protocols that we can negotiate.
|
||||
negotiated = connector.getProtocols().stream()
|
||||
.filter(p->
|
||||
{
|
||||
ConnectionFactory f=connector.getConnectionFactory(p);
|
||||
return !(f instanceof SslConnectionFactory)&&!(f instanceof NegotiatingServerConnectionFactory);
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
.filter(p ->
|
||||
{
|
||||
ConnectionFactory f = connector.getConnectionFactory(p);
|
||||
return !(f instanceof SslConnectionFactory) && !(f instanceof NegotiatingServerConnectionFactory);
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// if default protocol is not set, then it is either HTTP/1.1 or
|
||||
// the first protocol given
|
||||
// If default protocol is not set, then it is
|
||||
// either HTTP/1.1 or the first protocol given.
|
||||
String dft = defaultProtocol;
|
||||
if (dft == null && !negotiated.isEmpty())
|
||||
{
|
||||
if (negotiated.contains(HttpVersion.HTTP_1_1.asString()))
|
||||
dft = HttpVersion.HTTP_1_1.asString();
|
||||
else
|
||||
dft = negotiated.get(0);
|
||||
dft = negotiated.stream()
|
||||
.filter(HttpVersion.HTTP_1_1::is)
|
||||
.findFirst()
|
||||
.orElse(negotiated.get(0));
|
||||
}
|
||||
|
||||
SSLEngine engine = null;
|
||||
|
|
|
@ -156,7 +156,11 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
|
|||
|
||||
private int _minGzipSize=DEFAULT_MIN_GZIP_SIZE;
|
||||
private int _compressionLevel=Deflater.DEFAULT_COMPRESSION;
|
||||
private boolean _checkGzExists = true;
|
||||
/**
|
||||
* @deprecated feature will be removed in Jetty 10.x, with no replacement.
|
||||
*/
|
||||
@Deprecated
|
||||
private boolean _checkGzExists = false;
|
||||
private boolean _syncFlush = false;
|
||||
private int _inflateBufferSize = -1;
|
||||
private EnumSet<DispatcherType> _dispatchers = EnumSet.of(DispatcherType.REQUEST);
|
||||
|
@ -399,6 +403,10 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
|
|||
super.doStart();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated feature will be removed in Jetty 10.x, with no replacement.
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean getCheckGzExists()
|
||||
{
|
||||
return _checkGzExists;
|
||||
|
@ -780,7 +788,9 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
|
|||
*
|
||||
* @param checkGzExists whether to check if a static gz file exists for
|
||||
* the resource that the DefaultServlet may serve as precompressed.
|
||||
* @deprecated feature will be removed in Jetty 10.x, with no replacement.
|
||||
*/
|
||||
@Deprecated
|
||||
public void setCheckGzExists(boolean checkGzExists)
|
||||
{
|
||||
_checkGzExists = checkGzExists;
|
||||
|
|
|
@ -25,7 +25,6 @@ import java.util.concurrent.TimeUnit;
|
|||
|
||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
||||
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
|
|
@ -44,7 +44,7 @@ public class DefaultSessionCache extends AbstractSessionCache
|
|||
/**
|
||||
* The cache of sessions in a hashmap
|
||||
*/
|
||||
protected ConcurrentHashMap<String, Session> _sessions = new ConcurrentHashMap<String, Session>();
|
||||
protected ConcurrentHashMap<String, Session> _sessions = new ConcurrentHashMap<>();
|
||||
|
||||
private final CounterStatistic _stats = new CounterStatistic();
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.SessionIdManager;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||
|
|
|
@ -30,9 +30,7 @@ import java.io.ObjectOutputStream;
|
|||
import java.io.OutputStream;
|
||||
import java.nio.file.FileVisitOption;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.LinkOption;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.attribute.FileTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
@ -264,12 +262,19 @@ public class FileSessionDataStore extends AbstractSessionDataStore
|
|||
if (p == null)
|
||||
return;
|
||||
|
||||
long expiry = getExpiryFromFilename(p.getFileName().toString());
|
||||
//files with 0 expiry never expire
|
||||
if (expiry >0 && ((now - expiry) >= (5*TimeUnit.SECONDS.toMillis(_gracePeriodSec))))
|
||||
try
|
||||
{
|
||||
Files.deleteIfExists(p);
|
||||
if (LOG.isDebugEnabled()) LOG.debug("Sweep deleted {}", p.getFileName());
|
||||
long expiry = getExpiryFromFilename(p.getFileName().toString());
|
||||
//files with 0 expiry never expire
|
||||
if (expiry >0 && ((now - expiry) >= (5*TimeUnit.SECONDS.toMillis(_gracePeriodSec))))
|
||||
{
|
||||
Files.deleteIfExists(p);
|
||||
if (LOG.isDebugEnabled()) LOG.debug("Sweep deleted {}", p.getFileName());
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
LOG.warn("Not valid session filename {}", p.getFileName(), e);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -293,7 +298,7 @@ public class FileSessionDataStore extends AbstractSessionDataStore
|
|||
if (filename == null)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Unknown file {}",filename);
|
||||
LOG.debug("Unknown file {}",idWithContext);
|
||||
return;
|
||||
}
|
||||
File file = new File (_storeDir, filename);
|
||||
|
@ -542,7 +547,7 @@ public class FileSessionDataStore extends AbstractSessionDataStore
|
|||
* @param id identity of session
|
||||
* @return the session id plus context
|
||||
*/
|
||||
private String getIdWithContext (String id)
|
||||
protected String getIdWithContext (String id)
|
||||
{
|
||||
return _contextString+"_"+id;
|
||||
}
|
||||
|
@ -552,13 +557,13 @@ public class FileSessionDataStore extends AbstractSessionDataStore
|
|||
* @param data
|
||||
* @return the session id plus context and expiry
|
||||
*/
|
||||
private String getIdWithContextAndExpiry (SessionData data)
|
||||
protected String getIdWithContextAndExpiry (SessionData data)
|
||||
{
|
||||
return ""+data.getExpiry()+"_"+getIdWithContext(data.getId());
|
||||
}
|
||||
|
||||
|
||||
private String getIdFromFilename (String filename)
|
||||
protected String getIdFromFilename (String filename)
|
||||
{
|
||||
if (filename == null)
|
||||
return null;
|
||||
|
@ -567,7 +572,7 @@ public class FileSessionDataStore extends AbstractSessionDataStore
|
|||
|
||||
|
||||
|
||||
private long getExpiryFromFilename (String filename)
|
||||
protected long getExpiryFromFilename (String filename)
|
||||
{
|
||||
if (StringUtil.isBlank(filename) || filename.indexOf("_") < 0)
|
||||
throw new IllegalStateException ("Invalid or missing filename");
|
||||
|
@ -577,7 +582,7 @@ public class FileSessionDataStore extends AbstractSessionDataStore
|
|||
}
|
||||
|
||||
|
||||
private String getContextFromFilename (String filename)
|
||||
protected String getContextFromFilename (String filename)
|
||||
{
|
||||
if (StringUtil.isBlank(filename))
|
||||
return null;
|
||||
|
@ -593,7 +598,7 @@ public class FileSessionDataStore extends AbstractSessionDataStore
|
|||
* @param filename the name of the file to use
|
||||
* @return the session id plus context
|
||||
*/
|
||||
private String getIdWithContextFromFilename (String filename)
|
||||
protected String getIdWithContextFromFilename (String filename)
|
||||
{
|
||||
if (StringUtil.isBlank(filename) || filename.indexOf('_') < 0)
|
||||
return null;
|
||||
|
@ -607,7 +612,7 @@ public class FileSessionDataStore extends AbstractSessionDataStore
|
|||
* @param filename the filename to check
|
||||
* @return true if the filename has the correct filename format
|
||||
*/
|
||||
private boolean isSessionFilename (String filename)
|
||||
protected boolean isSessionFilename (String filename)
|
||||
{
|
||||
if (StringUtil.isBlank(filename))
|
||||
return false;
|
||||
|
@ -626,7 +631,7 @@ public class FileSessionDataStore extends AbstractSessionDataStore
|
|||
* @param filename the filename to check
|
||||
* @return true if the filename has the correct filename format and is for this context
|
||||
*/
|
||||
private boolean isOurContextSessionFilename (String filename)
|
||||
protected boolean isOurContextSessionFilename (String filename)
|
||||
{
|
||||
if (StringUtil.isBlank(filename))
|
||||
return false;
|
||||
|
|
|
@ -146,7 +146,7 @@ public class HouseKeeper extends AbstractLifeCycle
|
|||
_task.cancel();
|
||||
if (_runner == null)
|
||||
_runner = new Runner();
|
||||
LOG.info("Scavenging every {}ms", _intervalMs);
|
||||
LOG.info("{} Scavenging every {}ms", _sessionIdManager.getWorkerName(), _intervalMs);
|
||||
_task = _scheduler.schedule(_runner,_intervalMs,TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ public class HouseKeeper extends AbstractLifeCycle
|
|||
if (_task!=null)
|
||||
{
|
||||
_task.cancel();
|
||||
LOG.info("Stopped scavenging");
|
||||
LOG.info("{} Stopped scavenging", _sessionIdManager.getWorkerName());
|
||||
}
|
||||
_task = null;
|
||||
if (_ownScheduler)
|
||||
|
@ -204,13 +204,13 @@ public class HouseKeeper extends AbstractLifeCycle
|
|||
if (sec <= 0)
|
||||
{
|
||||
_intervalMs = 0L;
|
||||
LOG.info("Scavenging disabled");
|
||||
LOG.info("{} Scavenging disabled", _sessionIdManager.getWorkerName());
|
||||
stopScavenging();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sec < 10)
|
||||
LOG.warn("Short interval of {}sec for session scavenging.", sec);
|
||||
LOG.warn("{} Short interval of {}sec for session scavenging.", _sessionIdManager.getWorkerName(), sec);
|
||||
|
||||
_intervalMs=sec*1000L;
|
||||
|
||||
|
@ -261,7 +261,7 @@ public class HouseKeeper extends AbstractLifeCycle
|
|||
return;
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{} scavenging sessions", this);
|
||||
LOG.debug("{} scavenging sessions", _sessionIdManager.getWorkerName());
|
||||
|
||||
//find the session managers
|
||||
for (SessionHandler manager:_sessionIdManager.getSessionHandlers())
|
||||
|
|
|
@ -816,7 +816,7 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
|
|||
public Set<String> doGetExpired(Set<String> candidates)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Getting expired sessions "+System.currentTimeMillis());
|
||||
LOG.debug("Getting expired sessions at time {}", System.currentTimeMillis());
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
|
@ -830,7 +830,7 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
|
|||
*/
|
||||
long upperBound = now;
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug ("{}- Pass 1: Searching for sessions for context {} managed by me {} and expired before {}", _context.getCanonicalContextPath(), _context.getWorkerName(), upperBound);
|
||||
LOG.debug ("{}- Pass 1: Searching for sessions for context {} managed by me and expired before {}", _context.getWorkerName(), _context.getCanonicalContextPath(),upperBound);
|
||||
|
||||
try (PreparedStatement statement = _sessionTableSchema.getExpiredSessionsStatement(connection, _context.getCanonicalContextPath(), _context.getVhost(), upperBound))
|
||||
{
|
||||
|
@ -905,7 +905,7 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.warn("Problem checking if potentially expired session {} exists in db", k,e);
|
||||
LOG.warn("{} Problem checking if potentially expired session {} exists in db", _context.getWorkerName(), k,e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -372,9 +372,7 @@ public class SessionData implements Serializable
|
|||
return (getExpiry() <= time);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
|
|
|
@ -21,8 +21,6 @@ package org.eclipse.jetty.server.session;
|
|||
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
|
||||
/**
|
||||
* SessionDataStore
|
||||
*
|
||||
|
@ -68,10 +66,10 @@ public interface SessionDataStore extends SessionDataMap
|
|||
/**
|
||||
* Test if data exists for a given session id.
|
||||
*
|
||||
* @param id Identity of session whose existance should be checked
|
||||
* @param id Identity of session whose existence should be checked
|
||||
*
|
||||
* @return true if valid, non-expired session exists
|
||||
* @throws Exception if problem checking existance with persistence layer
|
||||
* @throws Exception if problem checking existence with persistence layer
|
||||
*/
|
||||
public boolean exists (String id) throws Exception;
|
||||
|
||||
|
|
|
@ -222,9 +222,9 @@ public class SessionHandler extends ScopedHandler
|
|||
protected boolean _secureCookies=false;
|
||||
protected boolean _secureRequestOnly=true;
|
||||
|
||||
protected final List<HttpSessionAttributeListener> _sessionAttributeListeners = new CopyOnWriteArrayList<HttpSessionAttributeListener>();
|
||||
protected final List<HttpSessionListener> _sessionListeners= new CopyOnWriteArrayList<HttpSessionListener>();
|
||||
protected final List<HttpSessionIdListener> _sessionIdListeners = new CopyOnWriteArrayList<HttpSessionIdListener>();
|
||||
protected final List<HttpSessionAttributeListener> _sessionAttributeListeners = new CopyOnWriteArrayList<>();
|
||||
protected final List<HttpSessionListener> _sessionListeners= new CopyOnWriteArrayList<>();
|
||||
protected final List<HttpSessionIdListener> _sessionIdListeners = new CopyOnWriteArrayList<>();
|
||||
|
||||
protected ClassLoader _loader;
|
||||
protected ContextHandler.Context _context;
|
||||
|
|
|
@ -1,421 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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 java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.toolchain.test.FS;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.StdErrLog;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
public class FileSessionManagerTest
|
||||
{
|
||||
public static final long ONE_DAY = (1000L*60L*60L*24L);
|
||||
private static StdErrLog _log;
|
||||
private static boolean _stacks;
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass ()
|
||||
{
|
||||
_log = ((StdErrLog)Log.getLogger("org.eclipse.jetty.server.session"));
|
||||
_stacks = _log.isHideStacks();
|
||||
_log.setHideStacks(true);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass()
|
||||
{
|
||||
_log.setHideStacks(_stacks);
|
||||
}
|
||||
|
||||
@After
|
||||
public void after()
|
||||
{
|
||||
File testDir = MavenTestingUtils.getTargetTestingDir("hashes");
|
||||
if (testDir.exists())
|
||||
FS.ensureEmpty(testDir);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDangerousSessionIdRemoval() throws Exception
|
||||
{
|
||||
String expectedFilename = "_0.0.0.0_dangerFile";
|
||||
File targetFile = MavenTestingUtils.getTargetFile(expectedFilename);
|
||||
|
||||
try
|
||||
{
|
||||
Server server = new Server();
|
||||
SessionHandler handler = new SessionHandler();
|
||||
handler.setServer(server);
|
||||
final DefaultSessionIdManager idmgr = new DefaultSessionIdManager(server);
|
||||
idmgr.setServer(server);
|
||||
server.setSessionIdManager(idmgr);
|
||||
|
||||
FileSessionDataStore ds = new FileSessionDataStore();
|
||||
ds.setDeleteUnrestorableFiles(true);
|
||||
DefaultSessionCache ss = new DefaultSessionCache(handler);
|
||||
handler.setSessionCache(ss);
|
||||
ss.setSessionDataStore(ds);
|
||||
File testDir = MavenTestingUtils.getTargetTestingDir("hashes");
|
||||
FS.ensureEmpty(testDir);
|
||||
ds.setStoreDir(testDir);
|
||||
handler.setSessionIdManager(idmgr);
|
||||
handler.start();
|
||||
|
||||
//Create a file that is in the parent dir of the session storeDir
|
||||
|
||||
targetFile.createNewFile();
|
||||
Assert.assertTrue("File should exist!", MavenTestingUtils.getTargetFile(expectedFilename).exists());
|
||||
|
||||
//Verify that passing in a relative filename outside of the storedir does not lead
|
||||
//to deletion of file (needs deleteUnrecoverableFiles(true))
|
||||
Session session = handler.getSession("../_0.0.0.0_dangerFile");
|
||||
Assert.assertTrue(session == null);
|
||||
Assert.assertTrue("File should exist!", MavenTestingUtils.getTargetFile(expectedFilename).exists());
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (targetFile.exists())
|
||||
IO.delete(targetFile);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* When starting the filestore, check that really old expired
|
||||
* files are deleted irrespective of context session belongs to.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testDeleteOfOlderFiles() throws Exception
|
||||
{
|
||||
Server server = new Server();
|
||||
SessionHandler handler = new SessionHandler();
|
||||
handler.setServer(server);
|
||||
final DefaultSessionIdManager idmgr = new DefaultSessionIdManager(server);
|
||||
idmgr.setServer(server);
|
||||
server.setSessionIdManager(idmgr);
|
||||
|
||||
FileSessionDataStore ds = new FileSessionDataStore();
|
||||
ds.setDeleteUnrestorableFiles(false); //turn off deletion of unreadable session files
|
||||
DefaultSessionCache ss = new DefaultSessionCache(handler);
|
||||
handler.setSessionCache(ss);
|
||||
ss.setSessionDataStore(ds);
|
||||
|
||||
File testDir = MavenTestingUtils.getTargetTestingDir("hashes");
|
||||
FS.ensureEmpty(testDir);
|
||||
ds.setStoreDir(testDir);
|
||||
|
||||
//create a really old file for session abc
|
||||
String name1 = "100__0.0.0.0_abc";
|
||||
File f1 = new File(testDir, name1);
|
||||
if (f1.exists())
|
||||
Assert.assertTrue(f1.delete());
|
||||
f1.createNewFile();
|
||||
|
||||
//create another really old file for session abc
|
||||
Thread.sleep(1100);
|
||||
String name2 = "101__0.0.0.0_abc";
|
||||
File f2 = new File(testDir, name2);
|
||||
if (f2.exists())
|
||||
Assert.assertTrue(f2.delete());
|
||||
f2.createNewFile();
|
||||
|
||||
//make one file for session abc that should not have expired
|
||||
Thread.sleep(1100);
|
||||
long exp = System.currentTimeMillis() + ONE_DAY;
|
||||
String name3 = Long.toString(exp)+"__0.0.0.0_abc";
|
||||
File f3 = new File(testDir, name3);
|
||||
if (f3.exists())
|
||||
Assert.assertTrue(f3.delete());
|
||||
f3.createNewFile();
|
||||
|
||||
//make a file that is for a different context
|
||||
//that expired a long time ago - should be
|
||||
//removed by sweep on startup
|
||||
Thread.sleep(1100);
|
||||
String name4 = "1099_foo_0.0.0.0_abc";
|
||||
File f4 = new File(testDir, name4);
|
||||
if (f4.exists())
|
||||
Assert.assertTrue(f4.delete());
|
||||
f4.createNewFile();
|
||||
|
||||
//make a file that is for a different context
|
||||
//that should not have expired - ensure it is
|
||||
//not removed
|
||||
exp = System.currentTimeMillis() + ONE_DAY;
|
||||
String name5 = Long.toString(exp)+"_foo_0.0.0.0_abcdefg";
|
||||
File f5 = new File(testDir, name5);
|
||||
if (f5.exists())
|
||||
Assert.assertTrue(f5.delete());
|
||||
f5.createNewFile();
|
||||
|
||||
//make a file that is for a different context
|
||||
//that expired, but only recently - it should
|
||||
//not be removed by the startup process
|
||||
exp = System.currentTimeMillis() - 1000L;
|
||||
String name6 = Long.toString(exp)+"_foo_0.0.0.0_abcdefg";
|
||||
File f6 = new File(testDir, name6);
|
||||
if (f6.exists())
|
||||
Assert.assertTrue(f6.delete());
|
||||
f6.createNewFile();
|
||||
|
||||
handler.setSessionIdManager(idmgr);
|
||||
handler.start();
|
||||
|
||||
Assert.assertTrue(!f1.exists());
|
||||
Assert.assertTrue(!f2.exists());
|
||||
Assert.assertTrue(f3.exists());
|
||||
Assert.assertTrue(!f4.exists());
|
||||
Assert.assertTrue(f5.exists());
|
||||
Assert.assertTrue(f6.exists());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests that only the most recent file will be
|
||||
* loaded into the cache, even if it is already
|
||||
* expired. Other recently expired files for
|
||||
* same session should be deleted.
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testLoadOnlyMostRecent() throws Exception
|
||||
{
|
||||
Server server = new Server();
|
||||
SessionHandler handler = new SessionHandler();
|
||||
handler.setServer(server);
|
||||
final DefaultSessionIdManager idmgr = new DefaultSessionIdManager(server);
|
||||
idmgr.setServer(server);
|
||||
server.setSessionIdManager(idmgr);
|
||||
|
||||
FileSessionDataStore ds = new FileSessionDataStore();
|
||||
ds.setGracePeriodSec(100); //set graceperiod to 100sec to control what we consider as very old
|
||||
ds.setDeleteUnrestorableFiles(false); //turn off deletion of unreadable session files
|
||||
DefaultSessionCache ss = new DefaultSessionCache(handler);
|
||||
handler.setSessionCache(ss);
|
||||
ss.setSessionDataStore(ds);
|
||||
|
||||
File testDir = MavenTestingUtils.getTargetTestingDir("hashes");
|
||||
FS.ensureEmpty(testDir);
|
||||
ds.setStoreDir(testDir);
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
//create a file for session abc that expired 5sec ago
|
||||
long exp = now - 5000L;
|
||||
String name1 = Long.toString(exp)+"__0.0.0.0_abc";
|
||||
File f1 = new File(testDir, name1);
|
||||
if (f1.exists())
|
||||
Assert.assertTrue(f1.delete());
|
||||
f1.createNewFile();
|
||||
|
||||
//create a file for same session that expired 4 sec ago
|
||||
exp = now - 4000L;
|
||||
String name2 = Long.toString(exp)+"__0.0.0.0_abc";
|
||||
File f2 = new File(testDir, name2);
|
||||
if (f2.exists())
|
||||
Assert.assertTrue(f2.delete());
|
||||
f2.createNewFile();
|
||||
|
||||
|
||||
//make a file for same session that expired 3 sec ago
|
||||
exp = now - 3000L;
|
||||
String name3 = Long.toString(exp)+"__0.0.0.0_abc";
|
||||
File f3 = new File(testDir, name3);
|
||||
if (f3.exists())
|
||||
Assert.assertTrue(f3.delete());
|
||||
f3.createNewFile();
|
||||
|
||||
handler.setSessionIdManager(idmgr);
|
||||
handler.start();
|
||||
|
||||
Assert.assertFalse(f1.exists());
|
||||
Assert.assertFalse(f2.exists());
|
||||
Assert.assertTrue(f3.exists());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testUnrestorableFileRemoval() throws Exception
|
||||
{
|
||||
Server server = new Server();
|
||||
SessionHandler handler = new SessionHandler();
|
||||
handler.setServer(server);
|
||||
final DefaultSessionIdManager idmgr = new DefaultSessionIdManager(server);
|
||||
idmgr.setServer(server);
|
||||
server.setSessionIdManager(idmgr);
|
||||
|
||||
File testDir = MavenTestingUtils.getTargetTestingDir("hashes");
|
||||
FS.ensureEmpty(testDir);
|
||||
String expectedFilename = (System.currentTimeMillis() + 10000)+"__0.0.0.0_validFile123";
|
||||
|
||||
Assert.assertTrue(new File(testDir, expectedFilename).createNewFile());
|
||||
Assert.assertTrue("File should exist!", new File(testDir, expectedFilename).exists());
|
||||
|
||||
DefaultSessionCache ss = new DefaultSessionCache(handler);
|
||||
FileSessionDataStore ds = new FileSessionDataStore();
|
||||
ss.setSessionDataStore(ds);
|
||||
handler.setSessionCache(ss);
|
||||
ds.setDeleteUnrestorableFiles(true); //invalid file will be removed
|
||||
handler.setSessionIdManager(idmgr);
|
||||
ds.setStoreDir(testDir);
|
||||
handler.start();
|
||||
|
||||
handler.getSession("validFile123");
|
||||
|
||||
Assert.assertTrue("File shouldn't exist!", !new File(testDir,expectedFilename).exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHashSession() throws Exception
|
||||
{
|
||||
File testDir = MavenTestingUtils.getTargetTestingDir("saved");
|
||||
FS.ensureEmpty(testDir);
|
||||
|
||||
Server server = new Server();
|
||||
SessionHandler handler = new SessionHandler();
|
||||
handler.setServer(server);
|
||||
|
||||
DefaultSessionCache ss = new DefaultSessionCache(handler);
|
||||
FileSessionDataStore ds = new FileSessionDataStore();
|
||||
ss.setSessionDataStore(ds);
|
||||
handler.setSessionCache(ss);
|
||||
ds.setStoreDir(testDir);
|
||||
handler.setMaxInactiveInterval(5);
|
||||
Assert.assertTrue(testDir.exists());
|
||||
Assert.assertTrue(testDir.canWrite());
|
||||
|
||||
|
||||
DefaultSessionIdManager idManager = new DefaultSessionIdManager(server);
|
||||
idManager.setServer(server);
|
||||
idManager.setWorkerName("foo");
|
||||
handler.setSessionIdManager(idManager);
|
||||
server.setSessionIdManager(idManager);
|
||||
|
||||
server.start();
|
||||
handler.start();
|
||||
|
||||
Session session = (Session)handler.newHttpSession(new Request(null, null));
|
||||
String sessionId = session.getId();
|
||||
|
||||
session.setAttribute("one", new Integer(1));
|
||||
session.setAttribute("two", new Integer(2));
|
||||
|
||||
//stop will persist sessions
|
||||
handler.setMaxInactiveInterval(30); // change max inactive interval for *new* sessions
|
||||
handler.stop();
|
||||
|
||||
final String expectedFilename = "_0.0.0.0_"+session.getId();
|
||||
|
||||
File[] files = testDir.listFiles(new FilenameFilter(){
|
||||
|
||||
@Override
|
||||
public boolean accept(File dir, String name)
|
||||
{
|
||||
return name.contains(expectedFilename);
|
||||
}
|
||||
|
||||
});
|
||||
Assert.assertNotNull(files);
|
||||
Assert.assertEquals(1, files.length);
|
||||
Assert.assertTrue("File should exist!", files[0].exists());
|
||||
|
||||
|
||||
|
||||
handler.start();
|
||||
|
||||
//restore session
|
||||
Session restoredSession = (Session)handler.getSession(sessionId);
|
||||
Assert.assertNotNull(restoredSession);
|
||||
|
||||
Object o = restoredSession.getAttribute("one");
|
||||
Assert.assertNotNull(o);
|
||||
|
||||
Assert.assertEquals(1, ((Integer)o).intValue());
|
||||
Assert.assertEquals(5, restoredSession.getMaxInactiveInterval());
|
||||
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIrregularFilenames() throws Exception
|
||||
{
|
||||
Server server = new Server();
|
||||
SessionHandler handler = new SessionHandler();
|
||||
handler.setServer(server);
|
||||
final DefaultSessionIdManager idmgr = new DefaultSessionIdManager(server);
|
||||
idmgr.setServer(server);
|
||||
server.setSessionIdManager(idmgr);
|
||||
|
||||
FileSessionDataStore ds = new FileSessionDataStore();
|
||||
ds.setDeleteUnrestorableFiles(true);
|
||||
DefaultSessionCache ss = new DefaultSessionCache(handler);
|
||||
handler.setSessionCache(ss);
|
||||
ss.setSessionDataStore(ds);
|
||||
File testDir = MavenTestingUtils.getTargetTestingDir("hashes");
|
||||
FS.ensureEmpty(testDir);
|
||||
ds.setStoreDir(testDir);
|
||||
handler.setSessionIdManager(idmgr);
|
||||
handler.start();
|
||||
|
||||
//Create a file in the session storeDir that has no underscore.
|
||||
File noUnderscore = new File(testDir, "spuriousFile");
|
||||
noUnderscore.createNewFile();
|
||||
try
|
||||
{
|
||||
Assert.assertTrue("Expired should be empty!", ds.getExpired(Collections.emptySet()).isEmpty());
|
||||
}
|
||||
finally
|
||||
{
|
||||
noUnderscore.delete();
|
||||
}
|
||||
|
||||
//Create a file that starts with a non-number before an underscore
|
||||
File nonNumber = new File(testDir, "nonNumber_0.0.0.0_spuriousFile");
|
||||
nonNumber.createNewFile();
|
||||
try
|
||||
{
|
||||
Assert.assertTrue("Expired should be empty!", ds.getExpired(Collections.emptySet()).isEmpty());
|
||||
}
|
||||
finally
|
||||
{
|
||||
nonNumber.delete();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -46,80 +46,49 @@ public class SessionCookieTest
|
|||
super(manager);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.SessionCache#shutdown()
|
||||
*/
|
||||
@Override
|
||||
public void shutdown()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractSessionCache#newSession(org.eclipse.jetty.server.session.SessionData)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public Session newSession(SessionData data)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractSessionCache#doGet(String)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public Session doGet(String key)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractSessionCache#doPutIfAbsent(String, Session)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public Session doPutIfAbsent(String key, Session session)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractSessionCache#doDelete(String)
|
||||
*/
|
||||
@Override
|
||||
public Session doDelete(String key)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractSessionCache#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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractSessionCache#newSession(javax.servlet.http.HttpServletRequest, org.eclipse.jetty.server.session.SessionData)
|
||||
*/
|
||||
@Override
|
||||
public Session newSession(HttpServletRequest request, SessionData data)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -131,18 +100,12 @@ public class SessionCookieTest
|
|||
super(server);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.SessionIdManager#isIdInUse(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public boolean isIdInUse(String id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.SessionIdManager#expireAll(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void expireAll(String id)
|
||||
{
|
||||
|
@ -206,8 +169,5 @@ public class SessionCookieTest
|
|||
//cookie is not secure: not on secured requests and request is secure
|
||||
cookie = mgr.getSessionCookie(session, "/foo", true);
|
||||
assertFalse(cookie.isSecure());
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Require-Capability>osgi.serviceloader; filter:="(osgi.serviceloader=org.eclipse.jetty.util.security.CredentialProvider)";resolution:=optional;cardinality:=multiple, osgi.extender; filter:="(osgi.extender=osgi.serviceloader.processor)"</Require-Capability>
|
||||
<Require-Capability>osgi.serviceloader; filter:="(osgi.serviceloader=org.eclipse.jetty.util.security.CredentialProvider)";resolution:=optional;cardinality:=multiple, osgi.extender; filter:="(osgi.extender=osgi.serviceloader.processor)";resolution:=optional</Require-Capability>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
|
|
@ -21,13 +21,12 @@ package org.eclipse.jetty.util;
|
|||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* An AtomicLong with additional methods to treat it has
|
||||
* two hi/lo integers.
|
||||
* An AtomicLong with additional methods to treat it as two hi/lo integers.
|
||||
*/
|
||||
public class AtomicBiInteger extends AtomicLong
|
||||
{
|
||||
/**
|
||||
* @return the hi integer value
|
||||
* @return the hi value
|
||||
*/
|
||||
public int getHi()
|
||||
{
|
||||
|
@ -35,7 +34,7 @@ public class AtomicBiInteger extends AtomicLong
|
|||
}
|
||||
|
||||
/**
|
||||
* @return the lo integer value
|
||||
* @return the lo value
|
||||
*/
|
||||
public int getLo()
|
||||
{
|
||||
|
@ -43,12 +42,12 @@ public class AtomicBiInteger extends AtomicLong
|
|||
}
|
||||
|
||||
/**
|
||||
* Atomically set the hi integer value without changing
|
||||
* the lo value.
|
||||
* Atomically sets the hi value without changing the lo value.
|
||||
*
|
||||
* @param hi the new hi value
|
||||
* @return the hi int value
|
||||
* @return the previous hi value
|
||||
*/
|
||||
public int setHi(int hi)
|
||||
public int getAndSetHi(int hi)
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
|
@ -60,11 +59,12 @@ public class AtomicBiInteger extends AtomicLong
|
|||
}
|
||||
|
||||
/**
|
||||
* Atomically set the lo integer value without changing
|
||||
* the hi value.
|
||||
* Atomically sets the lo value without changing the hi value.
|
||||
*
|
||||
* @param lo the new lo value
|
||||
* @return the previous lo value
|
||||
*/
|
||||
public int setLo(int lo)
|
||||
public int getAndSetLo(int lo)
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
|
@ -76,7 +76,8 @@ public class AtomicBiInteger extends AtomicLong
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the hi and lo integer values.
|
||||
* Sets the hi and lo values.
|
||||
*
|
||||
* @param hi the new hi value
|
||||
* @param lo the new lo value
|
||||
*/
|
||||
|
@ -86,20 +87,21 @@ public class AtomicBiInteger extends AtomicLong
|
|||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the hi int value to the given updated value
|
||||
* only if the current value {@code ==} the expected value.
|
||||
* Concurrent changes to the lo value result in a retry.
|
||||
* @param expect the expected value
|
||||
* @param hi the new value
|
||||
* <p>Atomically sets the hi value to the given updated value
|
||||
* only if the current value {@code ==} the expected value.</p>
|
||||
* <p>Concurrent changes to the lo value result in a retry.</p>
|
||||
*
|
||||
* @param expectHi the expected hi value
|
||||
* @param hi the new hi value
|
||||
* @return {@code true} if successful. False return indicates that
|
||||
* the actual value was not equal to the expected value.
|
||||
* the actual hi value was not equal to the expected hi value.
|
||||
*/
|
||||
public boolean compareAndSetHi(int expect, int hi)
|
||||
public boolean compareAndSetHi(int expectHi, int hi)
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
long encoded = get();
|
||||
if (getHi(encoded)!=expect)
|
||||
if (getHi(encoded)!=expectHi)
|
||||
return false;
|
||||
long update = encodeHi(encoded,hi);
|
||||
if (compareAndSet(encoded,update))
|
||||
|
@ -108,20 +110,21 @@ public class AtomicBiInteger extends AtomicLong
|
|||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the lo int value to the given updated value
|
||||
* only if the current value {@code ==} the expected value.
|
||||
* Concurrent changes to the hi value result in a retry.
|
||||
* @param expect the expected value
|
||||
* @param lo the new value
|
||||
* <p>Atomically sets the lo value to the given updated value
|
||||
* only if the current value {@code ==} the expected value.</p>
|
||||
* <p>Concurrent changes to the hi value result in a retry.</p>
|
||||
*
|
||||
* @param expectLo the expected lo value
|
||||
* @param lo the new lo value
|
||||
* @return {@code true} if successful. False return indicates that
|
||||
* the actual value was not equal to the expected value.
|
||||
* the actual lo value was not equal to the expected lo value.
|
||||
*/
|
||||
public boolean compareAndSetLo(int expect, int lo)
|
||||
public boolean compareAndSetLo(int expectLo, int lo)
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
long encoded = get();
|
||||
if (getLo(encoded)!=expect)
|
||||
if (getLo(encoded)!=expectLo)
|
||||
return false;
|
||||
long update = encodeLo(encoded,lo);
|
||||
if (compareAndSet(encoded,update))
|
||||
|
@ -130,30 +133,31 @@ public class AtomicBiInteger extends AtomicLong
|
|||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the values to the given updated values
|
||||
* only if the current encoded value {@code ==} the expected value.
|
||||
* @param expect the expected encoded values
|
||||
* Atomically sets the values to the given updated values only if
|
||||
* the current encoded value {@code ==} the expected encoded value.
|
||||
*
|
||||
* @param encoded the expected encoded value
|
||||
* @param hi the new hi value
|
||||
* @param lo the new lo value
|
||||
* @return {@code true} if successful. False return indicates that
|
||||
* the actual value was not equal to the expected value.
|
||||
* the actual encoded value was not equal to the expected encoded value.
|
||||
*/
|
||||
public boolean compareAndSet(long expect, int hi, int lo)
|
||||
public boolean compareAndSet(long encoded, int hi, int lo)
|
||||
{
|
||||
long encoded = get();
|
||||
long update = encode(hi,lo);
|
||||
return compareAndSet(encoded,update);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the values to the given updated values
|
||||
* only if the current encoded value {@code ==} the expected value.
|
||||
* @param expectHi the expected hi values
|
||||
* Atomically sets the hi and lo values to the given updated values only if
|
||||
* the current hi and lo values {@code ==} the expected hi and lo values.
|
||||
*
|
||||
* @param expectHi the expected hi value
|
||||
* @param hi the new hi value
|
||||
* @param expectLo the expected lo values
|
||||
* @param expectLo the expected lo value
|
||||
* @param lo the new lo value
|
||||
* @return {@code true} if successful. False return indicates that
|
||||
* the actual value was not equal to the expected value.
|
||||
* the actual hi and lo values were not equal to the expected hi and lo value.
|
||||
*/
|
||||
public boolean compareAndSet(int expectHi, int hi, int expectLo, int lo)
|
||||
{
|
||||
|
@ -163,13 +167,12 @@ public class AtomicBiInteger extends AtomicLong
|
|||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the current hi value with the results of
|
||||
* applying the given delta, returning the updated value.
|
||||
* Atomically adds the given delta to the current hi value, returning the updated hi value.
|
||||
*
|
||||
* @param delta the delta to apply
|
||||
* @return the updated value
|
||||
* @return the updated hi value
|
||||
*/
|
||||
public int updateHi(int delta)
|
||||
public int addAndGetHi(int delta)
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
|
@ -182,13 +185,12 @@ public class AtomicBiInteger extends AtomicLong
|
|||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the current lo value with the results of
|
||||
* applying the given delta, returning the updated value.
|
||||
* Atomically adds the given delta to the current lo value, returning the updated lo value.
|
||||
*
|
||||
* @param delta the delta to apply
|
||||
* @return the updated value
|
||||
* @return the updated lo value
|
||||
*/
|
||||
public int updateLo(int delta)
|
||||
public int addAndGetLo(int delta)
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
|
@ -201,13 +203,12 @@ public class AtomicBiInteger extends AtomicLong
|
|||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the current values with the results of
|
||||
* applying the given deltas.
|
||||
* Atomically adds the given deltas to the current hi and lo values.
|
||||
*
|
||||
* @param deltaHi the delta to apply to the hi value
|
||||
* @param deltaLo the delta to apply to the lo value
|
||||
*/
|
||||
public void update(int deltaHi, int deltaLo)
|
||||
public void add(int deltaHi, int deltaLo)
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
|
@ -219,73 +220,66 @@ public class AtomicBiInteger extends AtomicLong
|
|||
}
|
||||
|
||||
/**
|
||||
* Get a hi int value from an encoded long
|
||||
* Gets a hi value from the given encoded value.
|
||||
*
|
||||
* @param encoded the encoded value
|
||||
* @return the hi int value
|
||||
* @return the hi value
|
||||
*/
|
||||
public static int getHi(long encoded)
|
||||
{
|
||||
return (int) ((encoded>>32)&0xFFFF_FFFFl);
|
||||
return (int) ((encoded>>32)&0xFFFF_FFFFL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a lo int value from an encoded long
|
||||
* Gets a lo value from the given encoded value.
|
||||
*
|
||||
* @param encoded the encoded value
|
||||
* @return the lo int value
|
||||
* @return the lo value
|
||||
*/
|
||||
public static int getLo(long encoded)
|
||||
{
|
||||
return (int) (encoded&0xFFFF_FFFFl);
|
||||
return (int) (encoded&0xFFFF_FFFFL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode hi and lo int values into a long
|
||||
* @param hi the hi int value
|
||||
* @param lo the lo int value
|
||||
* Encodes hi and lo values into a long.
|
||||
*
|
||||
* @param hi the hi value
|
||||
* @param lo the lo value
|
||||
* @return the encoded value
|
||||
*
|
||||
*/
|
||||
public static long encode(int hi, int lo)
|
||||
{
|
||||
long h = ((long)hi)&0xFFFF_FFFFl;
|
||||
long l = ((long)lo)&0xFFFF_FFFFl;
|
||||
long encoded = (h<<32)+l;
|
||||
return encoded;
|
||||
long h = ((long)hi)&0xFFFF_FFFFL;
|
||||
long l = ((long)lo)&0xFFFF_FFFFL;
|
||||
return (h<<32)+l;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Encode hi int values into an already encoded long
|
||||
* Sets the hi value into the given encoded value.
|
||||
*
|
||||
* @param encoded the encoded value
|
||||
* @param hi the hi int value
|
||||
* @return the encoded value
|
||||
*
|
||||
* @param hi the hi value
|
||||
* @return the new encoded value
|
||||
*/
|
||||
public static long encodeHi(long encoded, int hi)
|
||||
{
|
||||
long h = ((long)hi)&0xFFFF_FFFFl;
|
||||
long l = encoded&0xFFFF_FFFFl;
|
||||
encoded = (h<<32)+l;
|
||||
return encoded;
|
||||
long h = ((long)hi)&0xFFFF_FFFFL;
|
||||
long l = encoded&0xFFFF_FFFFL;
|
||||
return (h<<32)+l;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode lo int values into an already encoded long
|
||||
* Sets the lo value into the given encoded value.
|
||||
*
|
||||
* @param encoded the encoded value
|
||||
* @param lo the lo int value
|
||||
* @return the encoded value
|
||||
*
|
||||
* @param lo the lo value
|
||||
* @return the new encoded value
|
||||
*/
|
||||
public static long encodeLo(long encoded, int lo)
|
||||
{
|
||||
long h = (encoded>>32)&0xFFFF_FFFFl;
|
||||
long l = ((long)lo)&0xFFFF_FFFFl;
|
||||
encoded = (h<<32)+l;
|
||||
return encoded;
|
||||
long h = (encoded>>32)&0xFFFF_FFFFL;
|
||||
long l = ((long)lo)&0xFFFF_FFFFL;
|
||||
return (h<<32)+l;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -18,11 +18,13 @@
|
|||
|
||||
package org.eclipse.jetty.util;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class AtomicBiIntegerTest
|
||||
{
|
||||
|
||||
|
@ -75,11 +77,11 @@ public class AtomicBiIntegerTest
|
|||
assertThat(abi.getHi(),is(0));
|
||||
assertThat(abi.getLo(),is(0));
|
||||
|
||||
abi.setHi(Integer.MAX_VALUE);
|
||||
abi.getAndSetHi(Integer.MAX_VALUE);
|
||||
assertThat(abi.getHi(),is(Integer.MAX_VALUE));
|
||||
assertThat(abi.getLo(),is(0));
|
||||
|
||||
abi.setLo(Integer.MIN_VALUE);
|
||||
abi.getAndSetLo(Integer.MIN_VALUE);
|
||||
assertThat(abi.getHi(),is(Integer.MAX_VALUE));
|
||||
assertThat(abi.getLo(),is(Integer.MIN_VALUE));
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Require-Capability>osgi.serviceloader; filter:="(osgi.serviceloader=org.eclipse.jetty.xml.ConfigurationProcessorFactory)";resolution:=optional;cardinality:=multiple, osgi.extender; filter:="(osgi.extender=osgi.serviceloader.processor)"</Require-Capability>
|
||||
<Require-Capability>osgi.serviceloader; filter:="(osgi.serviceloader=org.eclipse.jetty.xml.ConfigurationProcessorFactory)";resolution:=optional;cardinality:=multiple, osgi.extender; filter:="(osgi.extender=osgi.serviceloader.processor)";resolution:=optional</Require-Capability>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
|
36
pom.xml
36
pom.xml
|
@ -448,7 +448,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-invoker-plugin</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<version>3.0.2-SNAPSHOT</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
|
@ -1068,16 +1068,6 @@
|
|||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
<pluginRepository>
|
||||
<id>apache.snapshots</id>
|
||||
<url>https://repository.apache.org/content/repositories/snapshots</url>
|
||||
<releases>
|
||||
<enabled>false</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
</profile>
|
||||
<profile>
|
||||
|
@ -1814,6 +1804,30 @@
|
|||
</repository>
|
||||
</repositories>
|
||||
-->
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>apache.snapshots</id>
|
||||
<url>https://repository.apache.org/content/repositories/snapshots</url>
|
||||
<releases>
|
||||
<enabled>false</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>apache.snapshots</id>
|
||||
<url>https://repository.apache.org/content/repositories/snapshots</url>
|
||||
<releases>
|
||||
<enabled>false</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
</build>
|
||||
<modules>
|
||||
<module>test-sessions-common</module>
|
||||
<module>test-hash-sessions</module>
|
||||
<module>test-file-sessions</module>
|
||||
<module>test-jdbc-sessions</module>
|
||||
<module>test-mongodb-sessions</module>
|
||||
|
|
|
@ -19,19 +19,16 @@
|
|||
|
||||
package org.eclipse.jetty.server.session;
|
||||
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* ProxySerializationTest
|
||||
* FileSessionDataStoreTest
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ProxySerializationTest extends AbstractProxySerializationTest
|
||||
{
|
||||
|
||||
public class FileSessionDataStoreTest extends AbstractSessionDataStoreTest
|
||||
{
|
||||
@Before
|
||||
public void before() throws Exception
|
||||
{
|
||||
|
@ -43,35 +40,44 @@ public class ProxySerializationTest extends AbstractProxySerializationTest
|
|||
{
|
||||
FileTestHelper.teardown();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
return FileTestHelper.newSessionDataStoreFactory();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testProxySerialization() throws Exception
|
||||
public void persistSession(SessionData data) throws Exception
|
||||
{
|
||||
super.testProxySerialization();
|
||||
FileTestHelper.createFile(data.getId(), data.getContextPath(), data.getVhost(), data.getLastNode(), data.getCreated(),
|
||||
data.getAccessed(), data.getLastAccessed(), data.getMaxInactiveMs(), data.getExpiry(), data.getCookieSet(), data.getAllAttributes());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void persistUnreadableSession(SessionData data) throws Exception
|
||||
{
|
||||
FileTestHelper.createFile(data.getId(), data.getContextPath(), data.getVhost(), data.getLastNode(), data.getCreated(),
|
||||
data.getAccessed(), data.getLastAccessed(), data.getMaxInactiveMs(), data.getExpiry(), data.getCookieSet(), null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean checkSessionExists(SessionData data) throws Exception
|
||||
{
|
||||
return (FileTestHelper.getFile(data.getId()) != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractProxySerializationTest#customizeContext(org.eclipse.jetty.servlet.ServletContextHandler)
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public void customizeContext(ServletContextHandler c)
|
||||
public boolean checkSessionPersisted(SessionData data) throws Exception
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
return FileTestHelper.checkSessionPersisted(data);
|
||||
}
|
||||
|
||||
}
|
|
@ -23,10 +23,20 @@ import static org.junit.Assert.assertFalse;
|
|||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jetty.util.ClassLoadingObjectInputStream;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
|
||||
/**
|
||||
|
@ -142,6 +152,105 @@ public class FileTestHelper
|
|||
}
|
||||
|
||||
|
||||
|
||||
public static void createFile (String id, String contextPath, String vhost,
|
||||
String lastNode, long created, long accessed,
|
||||
long lastAccessed, long maxIdle, long expiry,
|
||||
long cookieSet, Map<String,Object> attributes)
|
||||
throws Exception
|
||||
{
|
||||
String filename = ""+expiry+"_"+contextPath+"_"+vhost+"_"+id;
|
||||
File file = new File(_tmpDir, filename);
|
||||
try(FileOutputStream fos = new FileOutputStream(file,false))
|
||||
{
|
||||
DataOutputStream out = new DataOutputStream(fos);
|
||||
out.writeUTF(id);
|
||||
out.writeUTF(contextPath);
|
||||
out.writeUTF(vhost);
|
||||
out.writeUTF(lastNode);
|
||||
out.writeLong(created);
|
||||
out.writeLong(accessed);
|
||||
out.writeLong(lastAccessed);
|
||||
out.writeLong(cookieSet);
|
||||
out.writeLong(expiry);
|
||||
out.writeLong(maxIdle);
|
||||
|
||||
if (attributes != null)
|
||||
{
|
||||
List<String> keys = new ArrayList<String>(attributes.keySet());
|
||||
out.writeInt(keys.size());
|
||||
ObjectOutputStream oos = new ObjectOutputStream(out);
|
||||
for (String name:keys)
|
||||
{
|
||||
oos.writeUTF(name);
|
||||
oos.writeObject(attributes.get(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static boolean checkSessionPersisted (SessionData data)
|
||||
throws Exception
|
||||
{
|
||||
String filename = ""+data.getExpiry()+"_"+data.getContextPath()+"_"+data.getVhost()+"_"+data.getId();
|
||||
File file = new File(_tmpDir, filename);
|
||||
assertTrue(file.exists());
|
||||
|
||||
try (FileInputStream in = new FileInputStream(file))
|
||||
{
|
||||
DataInputStream di = new DataInputStream(in);
|
||||
|
||||
String id = di.readUTF();
|
||||
String contextPath = di.readUTF();
|
||||
String vhost = di.readUTF();
|
||||
String lastNode = di.readUTF();
|
||||
long created = di.readLong();
|
||||
long accessed = di.readLong();
|
||||
long lastAccessed = di.readLong();
|
||||
long cookieSet = di.readLong();
|
||||
long expiry = di.readLong();
|
||||
long maxIdle = di.readLong();
|
||||
|
||||
assertEquals(data.getId(), id);
|
||||
assertEquals(data.getContextPath(), contextPath);
|
||||
assertEquals(data.getVhost(), vhost);
|
||||
assertEquals(data.getLastNode(), lastNode);
|
||||
assertEquals(data.getCreated(), created);
|
||||
assertEquals(data.getAccessed(), accessed);
|
||||
assertEquals(data.getLastAccessed(), lastAccessed);
|
||||
assertEquals(data.getCookieSet(), cookieSet);
|
||||
assertEquals(data.getExpiry(), expiry);
|
||||
assertEquals(data.getMaxInactiveMs(), maxIdle);
|
||||
|
||||
Map<String,Object> attributes = new HashMap<>();
|
||||
|
||||
int size = di.readInt();
|
||||
if (size > 0)
|
||||
{
|
||||
ClassLoadingObjectInputStream ois = new ClassLoadingObjectInputStream(di);
|
||||
for (int i=0; i<size;i++)
|
||||
{
|
||||
String key = ois.readUTF();
|
||||
Object value = ois.readObject();
|
||||
attributes.put(key,value);
|
||||
}
|
||||
}
|
||||
|
||||
//same number of attributes
|
||||
assertEquals(data.getAllAttributes().size(), attributes.size());
|
||||
//same keys
|
||||
assertTrue(data.getKeys().equals(attributes.keySet()));
|
||||
//same values
|
||||
for (String name:data.getKeys())
|
||||
{
|
||||
assertTrue(data.getAttribute(name).equals(attributes.get(name)));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void deleteFile (String sessionId)
|
||||
{
|
||||
assertNotNull(_tmpDir);
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* NonClusteredSessionScavengingTest
|
||||
*/
|
||||
public class NonClusteredSessionScavengingTest extends AbstractNonClusteredSessionScavengingTest
|
||||
{
|
||||
@Before
|
||||
public void before() throws Exception
|
||||
{
|
||||
FileTestHelper.setup();
|
||||
}
|
||||
|
||||
@After
|
||||
public void after()
|
||||
{
|
||||
FileTestHelper.teardown();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractNonClusteredSessionScavengingTest#assertSession(java.lang.String, boolean)
|
||||
*/
|
||||
@Override
|
||||
public void assertSession(String id, boolean exists)
|
||||
{
|
||||
FileTestHelper.assertSessionExists(id, exists);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
return FileTestHelper.newSessionDataStoreFactory();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SessionInvalidateCreateScavengeTest extends AbstractSessionInvalidateCreateScavengeTest
|
||||
{
|
||||
|
||||
@Before
|
||||
public void before() throws Exception
|
||||
{
|
||||
FileTestHelper.setup();
|
||||
}
|
||||
|
||||
@After
|
||||
public void after()
|
||||
{
|
||||
FileTestHelper.teardown();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
return FileTestHelper.newSessionDataStoreFactory();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testSessionScavenge() throws Exception
|
||||
{
|
||||
super.testSessionScavenge();
|
||||
}
|
||||
}
|
|
@ -21,21 +21,14 @@ package org.eclipse.jetty.server.session;
|
|||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
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.servlet.ServletContextHandler;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
@ -60,205 +53,396 @@ public class TestFileSessions extends AbstractTestBase
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
return FileTestHelper.newSessionDataStoreFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that passing in a filename that contains ".." chars does not
|
||||
* remove a file outside of the store dir.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testLoadForeignContext() throws Exception
|
||||
{
|
||||
//create the SessionDataStore
|
||||
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
||||
context.setContextPath("/test");
|
||||
SessionDataStoreFactory factory = createSessionDataStoreFactory();
|
||||
((AbstractSessionDataStoreFactory)factory).setGracePeriodSec(10);
|
||||
FileSessionDataStore store = (FileSessionDataStore)factory.getSessionDataStore(context.getSessionHandler());
|
||||
store.setDeleteUnrestorableFiles(true);
|
||||
SessionContext sessionContext = new SessionContext("foo", context.getServletContext());
|
||||
store.initialize(sessionContext);
|
||||
|
||||
|
||||
//make a file for foobar context
|
||||
FileTestHelper.createFile((System.currentTimeMillis()+TimeUnit.DAYS.toMillis(1))+"__foobar_0.0.0.0_1234");
|
||||
|
||||
store.start();
|
||||
|
||||
//test this context can't load it
|
||||
assertNull(store.load("1234"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testSweep () throws Exception
|
||||
public void testFilenamesWithContext() throws Exception
|
||||
{
|
||||
int scavengePeriod = 2;
|
||||
String contextPath = "/test";
|
||||
String servletMapping = "/server";
|
||||
int inactivePeriod = 5;
|
||||
int gracePeriod = 10;
|
||||
DefaultSessionCacheFactory cacheFactory = new DefaultSessionCacheFactory();
|
||||
cacheFactory.setEvictionPolicy(SessionCache.NEVER_EVICT);
|
||||
FileSessionDataStoreFactory storeFactory = (FileSessionDataStoreFactory)createSessionDataStoreFactory();
|
||||
storeFactory.setGracePeriodSec(gracePeriod);
|
||||
TestServer server1 = new TestServer(0, inactivePeriod, scavengePeriod, cacheFactory, storeFactory);
|
||||
server1.addContext(contextPath).addServlet(TestServlet.class, servletMapping);
|
||||
//create the SessionDataStore
|
||||
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
||||
context.setContextPath("/test");
|
||||
SessionDataStoreFactory factory = createSessionDataStoreFactory();
|
||||
((AbstractSessionDataStoreFactory)factory).setGracePeriodSec(10);
|
||||
FileSessionDataStore store = (FileSessionDataStore)factory.getSessionDataStore(context.getSessionHandler());
|
||||
SessionContext sessionContext = new SessionContext("foo", context.getServletContext());
|
||||
store.initialize(sessionContext);
|
||||
|
||||
String s = store.getIdWithContext("1234");
|
||||
assertEquals("_test_0.0.0.0_1234", s);
|
||||
|
||||
s = store.getIdFromFilename("0__test_0.0.0.0_1234");
|
||||
assertEquals("1234", s);
|
||||
|
||||
s = store.getIdFromFilename(null);
|
||||
assertNull(s);
|
||||
|
||||
long l = store.getExpiryFromFilename("100__test_0.0.0.0_1234");
|
||||
assertEquals(100, l);
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
server1.start();
|
||||
|
||||
//create file not for our context that expired long ago and should be removed by sweep
|
||||
FileTestHelper.createFile("101_foobar_0.0.0.0_sessiona");
|
||||
FileTestHelper.assertSessionExists("sessiona", true);
|
||||
|
||||
//create a file not for our context that is not expired and should be ignored
|
||||
String nonExpiredForeign = (System.currentTimeMillis()+TimeUnit.DAYS.toMillis(1))+"_foobar_0.0.0.0_sessionb";
|
||||
FileTestHelper.createFile(nonExpiredForeign);
|
||||
FileTestHelper.assertFileExists(nonExpiredForeign, true);
|
||||
|
||||
//create a file not for our context that is recently expired, a thus ignored by sweep
|
||||
String expiredForeign = (System.currentTimeMillis()-TimeUnit.SECONDS.toMillis(1))+"_foobar_0.0.0.0_sessionc";
|
||||
FileTestHelper.createFile(expiredForeign);
|
||||
FileTestHelper.assertFileExists(expiredForeign, true);
|
||||
|
||||
//create a file that is not a session file, it should be ignored
|
||||
FileTestHelper.createFile("whatever.txt");
|
||||
FileTestHelper.assertFileExists("whatever.txt", true);
|
||||
|
||||
//create a file that is a non-expired session file for our context that should be ignored
|
||||
String nonExpired = (System.currentTimeMillis()+TimeUnit.DAYS.toMillis(1))+"_test_0.0.0.0_sessionb";
|
||||
FileTestHelper.createFile(nonExpired);
|
||||
FileTestHelper.assertFileExists(nonExpired, true);
|
||||
|
||||
//create a file that is a never-expire session file for our context that should be ignored
|
||||
String neverExpired = "0_test_0.0.0.0_sessionc";
|
||||
FileTestHelper.createFile(neverExpired);
|
||||
FileTestHelper.assertFileExists(neverExpired, true);
|
||||
|
||||
//create a file that is a never-expire session file for another context that should be ignored
|
||||
String foreignNeverExpired = "0_test_0.0.0.0_sessionc";
|
||||
FileTestHelper.createFile(foreignNeverExpired);
|
||||
FileTestHelper.assertFileExists(foreignNeverExpired, true);
|
||||
|
||||
|
||||
//need to wait to ensure scavenge runs so sweeper runs
|
||||
Thread.currentThread().sleep(2000L*scavengePeriod);
|
||||
FileTestHelper.assertSessionExists("sessiona", false);
|
||||
FileTestHelper.assertFileExists("whatever.txt", true);
|
||||
FileTestHelper.assertFileExists(nonExpired, true);
|
||||
FileTestHelper.assertFileExists(nonExpiredForeign, true);
|
||||
FileTestHelper.assertFileExists(expiredForeign, true);
|
||||
FileTestHelper.assertFileExists(neverExpired, true);
|
||||
FileTestHelper.assertFileExists(foreignNeverExpired, true);
|
||||
long ll = store.getExpiryFromFilename("nonnumber__test_0.0.0.0_1234");
|
||||
fail ("Should be non numeric");
|
||||
}
|
||||
finally
|
||||
catch (Exception e)
|
||||
{
|
||||
server1.stop();
|
||||
//expected
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void test () throws Exception
|
||||
{
|
||||
String contextPath = "/test";
|
||||
String servletMapping = "/server";
|
||||
int inactivePeriod = 5;
|
||||
DefaultSessionCacheFactory cacheFactory = new DefaultSessionCacheFactory();
|
||||
cacheFactory.setEvictionPolicy(SessionCache.NEVER_EVICT);
|
||||
SessionDataStoreFactory storeFactory = createSessionDataStoreFactory();
|
||||
TestServer server1 = new TestServer(0, inactivePeriod, 2, cacheFactory, storeFactory);
|
||||
server1.addContext(contextPath).addServlet(TestServlet.class, servletMapping);
|
||||
|
||||
try
|
||||
{
|
||||
server1.start();
|
||||
int port1 = server1.getPort();
|
||||
|
||||
HttpClient client = new HttpClient();
|
||||
client.start();
|
||||
|
||||
try
|
||||
{
|
||||
// Connect to server1 to create a session and get its session cookie
|
||||
ContentResponse response1 = client.GET("http://localhost:" + port1 + contextPath + servletMapping + "?action=init");
|
||||
assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
|
||||
String sessionCookie = response1.getHeaders().get("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
||||
//check that the file for the session exists after creating the session
|
||||
FileTestHelper.assertSessionExists(TestServer.extractSessionId(sessionCookie), true);
|
||||
File file1 = FileTestHelper.getFile(TestServer.extractSessionId(sessionCookie));
|
||||
|
||||
|
||||
//request the session and check that the file for the session was changed
|
||||
Request request = client.newRequest("http://localhost:" + port1 + contextPath + servletMapping + "?action=check");
|
||||
request.header("Cookie", sessionCookie);
|
||||
ContentResponse response2 = request.send();
|
||||
assertEquals(HttpServletResponse.SC_OK,response2.getStatus());
|
||||
FileTestHelper.assertSessionExists(TestServer.extractSessionId(sessionCookie), true);
|
||||
File file2 = FileTestHelper.getFile(TestServer.extractSessionId(sessionCookie));
|
||||
|
||||
assertFalse (file1.exists());
|
||||
assertTrue(file2.exists());
|
||||
|
||||
//check expiry time in filename changed
|
||||
String tmp = file1.getName();
|
||||
tmp = tmp.substring(0, tmp.indexOf("_"));
|
||||
|
||||
long f1 = Long.valueOf(tmp);
|
||||
tmp = file2.getName();
|
||||
tmp = tmp.substring(0, tmp.indexOf("_"));
|
||||
long f2 = Long.valueOf(tmp);
|
||||
assertTrue (f2>f1);
|
||||
|
||||
//invalidate the session and verify that the session file is deleted
|
||||
request = client.newRequest("http://localhost:" + port1 + contextPath + servletMapping + "?action=remove");
|
||||
request.header("Cookie", sessionCookie);
|
||||
response2 = request.send();
|
||||
assertEquals(HttpServletResponse.SC_OK,response2.getStatus());
|
||||
FileTestHelper.assertSessionExists(TestServer.extractSessionId(sessionCookie), false);
|
||||
|
||||
//make another session
|
||||
response1 = client.GET("http://localhost:" + port1 + contextPath + servletMapping + "?action=init");
|
||||
assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
|
||||
sessionCookie = response1.getHeaders().get("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
FileTestHelper.assertSessionExists(TestServer.extractSessionId(sessionCookie), true);
|
||||
|
||||
//wait for it to be scavenged
|
||||
Thread.currentThread().sleep((inactivePeriod + 2)*1000);
|
||||
FileTestHelper.assertSessionExists(TestServer.extractSessionId(sessionCookie), false);
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.stop();
|
||||
}
|
||||
long ll = store.getExpiryFromFilename(null);
|
||||
fail("Should throw ISE");
|
||||
}
|
||||
finally
|
||||
catch (Exception e)
|
||||
{
|
||||
server1.stop();
|
||||
//expected;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
long ll = store.getExpiryFromFilename("thisisnotavalidsessionfilename");
|
||||
fail("Should throw ISE");
|
||||
}
|
||||
catch (IllegalStateException e)
|
||||
{
|
||||
//expected;
|
||||
}
|
||||
|
||||
s = store.getContextFromFilename("100__test_0.0.0.0_1234");
|
||||
assertEquals("_test_0.0.0.0", s);
|
||||
|
||||
assertNull (store.getContextFromFilename(null));
|
||||
|
||||
try
|
||||
{
|
||||
s = store.getContextFromFilename("thisisnotavalidfilename");
|
||||
fail("Should throw exception");
|
||||
}
|
||||
catch (StringIndexOutOfBoundsException e)
|
||||
{
|
||||
//expected;
|
||||
}
|
||||
|
||||
s = store.getIdWithContextFromFilename("100__test_0.0.0.0_1234");
|
||||
assertEquals("_test_0.0.0.0_1234",s);
|
||||
|
||||
assertNull(store.getIdWithContextFromFilename(null));
|
||||
assertNull(store.getIdWithContextFromFilename("thisisnotavalidfilename"));
|
||||
|
||||
assertTrue(store.isOurContextSessionFilename("100__test_0.0.0.0_1234"));
|
||||
assertFalse(store.isOurContextSessionFilename("100__other_0.0.0.0_1234"));
|
||||
}
|
||||
|
||||
public static class TestServlet extends HttpServlet
|
||||
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testFilenamesWithDefaultContext() throws Exception
|
||||
{
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
//create the SessionDataStore
|
||||
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
||||
context.setContextPath("/");
|
||||
SessionDataStoreFactory factory = createSessionDataStoreFactory();
|
||||
((AbstractSessionDataStoreFactory)factory).setGracePeriodSec(10);
|
||||
FileSessionDataStore store = (FileSessionDataStore)factory.getSessionDataStore(context.getSessionHandler());
|
||||
SessionContext sessionContext = new SessionContext("foo", context.getServletContext());
|
||||
store.initialize(sessionContext);
|
||||
|
||||
String s = store.getIdWithContext("1234");
|
||||
assertEquals("_0.0.0.0_1234", s);
|
||||
|
||||
s = store.getIdFromFilename("0__0.0.0.0_1234");
|
||||
assertEquals("1234", s);
|
||||
|
||||
long l = store.getExpiryFromFilename("100__0.0.0.0_1234");
|
||||
assertEquals(100, l);
|
||||
|
||||
try
|
||||
{
|
||||
String action = request.getParameter("action");
|
||||
if ("init".equals(action))
|
||||
{
|
||||
HttpSession session = request.getSession(true);
|
||||
session.setAttribute("A", "A");
|
||||
}
|
||||
else if ("remove".equals(action))
|
||||
{
|
||||
HttpSession session = request.getSession(false);
|
||||
session.invalidate();
|
||||
}
|
||||
else if ("check".equals(action))
|
||||
{
|
||||
HttpSession session = request.getSession(false);
|
||||
assertTrue(session != null);
|
||||
try {Thread.currentThread().sleep(1);}catch (Exception e) {e.printStackTrace();}
|
||||
}
|
||||
long ll = store.getExpiryFromFilename("nonnumber__0.0.0.0_1234");
|
||||
fail ("Should be non numeric");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//expected
|
||||
}
|
||||
|
||||
s = store.getContextFromFilename("100__0.0.0.0_1234");
|
||||
assertEquals("_0.0.0.0", s);
|
||||
|
||||
s = store.getIdWithContextFromFilename("100__0.0.0.0_1234");
|
||||
assertEquals("_0.0.0.0_1234",s);
|
||||
|
||||
assertTrue(store.isOurContextSessionFilename("100__0.0.0.0_1234"));
|
||||
assertFalse(store.isOurContextSessionFilename("100__other_0.0.0.0_1234"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Test the FileSessionDataStore sweeper function
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testSweep () throws Exception
|
||||
{
|
||||
|
||||
//create the SessionDataStore
|
||||
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
||||
context.setContextPath("/test");
|
||||
SessionDataStoreFactory factory = createSessionDataStoreFactory();
|
||||
((AbstractSessionDataStoreFactory)factory).setGracePeriodSec(10);
|
||||
SessionDataStore store = factory.getSessionDataStore(context.getSessionHandler());
|
||||
SessionContext sessionContext = new SessionContext("foo", context.getServletContext());
|
||||
store.initialize(sessionContext);
|
||||
|
||||
store.start();
|
||||
|
||||
//create file not for our context that expired long ago and should be removed by sweep
|
||||
FileTestHelper.createFile("101__foobar_0.0.0.0_sessiona");
|
||||
FileTestHelper.assertSessionExists("sessiona", true);
|
||||
|
||||
//create a file not for our context that is not expired and should be ignored
|
||||
String nonExpiredForeign = (System.currentTimeMillis()+TimeUnit.DAYS.toMillis(1))+"__foobar_0.0.0.0_sessionb";
|
||||
FileTestHelper.createFile(nonExpiredForeign);
|
||||
FileTestHelper.assertFileExists(nonExpiredForeign, true);
|
||||
|
||||
//create a file not for our context that is recently expired, a thus ignored by sweep
|
||||
String expiredForeign = (System.currentTimeMillis()-TimeUnit.SECONDS.toMillis(1))+"__foobar_0.0.0.0_sessionc";
|
||||
FileTestHelper.createFile(expiredForeign);
|
||||
FileTestHelper.assertFileExists(expiredForeign, true);
|
||||
|
||||
//create a file that is not a session file, it should be ignored
|
||||
FileTestHelper.createFile("whatever.txt");
|
||||
FileTestHelper.assertFileExists("whatever.txt", true);
|
||||
|
||||
//create a file that is not a valid session filename, should be ignored
|
||||
FileTestHelper.createFile("nonNumber__0.0.0.0_spuriousFile");
|
||||
FileTestHelper.assertFileExists("nonNumber__0.0.0.0_spuriousFile", true);
|
||||
|
||||
//create a file that is a non-expired session file for our context that should be ignored
|
||||
String nonExpired = (System.currentTimeMillis()+TimeUnit.DAYS.toMillis(1))+"__test_0.0.0.0_sessionb";
|
||||
FileTestHelper.createFile(nonExpired);
|
||||
FileTestHelper.assertFileExists(nonExpired, true);
|
||||
|
||||
//create a file that is a never-expire session file for our context that should be ignored
|
||||
String neverExpired = "0__test_0.0.0.0_sessionc";
|
||||
FileTestHelper.createFile(neverExpired);
|
||||
FileTestHelper.assertFileExists(neverExpired, true);
|
||||
|
||||
//create a file that is a never-expire session file for another context that should be ignored
|
||||
String foreignNeverExpired = "0__other_0.0.0.0_sessionc";
|
||||
FileTestHelper.createFile(foreignNeverExpired);
|
||||
FileTestHelper.assertFileExists(foreignNeverExpired, true);
|
||||
|
||||
//sweep
|
||||
((FileSessionDataStore)store).sweepDisk();
|
||||
|
||||
//check results
|
||||
FileTestHelper.assertSessionExists("sessiona", false);
|
||||
FileTestHelper.assertFileExists("whatever.txt", true);
|
||||
FileTestHelper.assertFileExists("nonNumber__0.0.0.0_spuriousFile", true);
|
||||
FileTestHelper.assertFileExists(nonExpired, true);
|
||||
FileTestHelper.assertFileExists(nonExpiredForeign, true);
|
||||
FileTestHelper.assertFileExists(expiredForeign, true);
|
||||
FileTestHelper.assertFileExists(neverExpired, true);
|
||||
FileTestHelper.assertFileExists(foreignNeverExpired, true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test that when it initializes, the FileSessionDataStore deletes old expired sessions.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testInitialize ()
|
||||
throws Exception
|
||||
{
|
||||
//create the SessionDataStore
|
||||
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
||||
context.setContextPath("/");
|
||||
SessionDataStoreFactory factory = createSessionDataStoreFactory();
|
||||
((AbstractSessionDataStoreFactory)factory).setGracePeriodSec(10);
|
||||
SessionDataStore store = factory.getSessionDataStore(context.getSessionHandler());
|
||||
SessionContext sessionContext = new SessionContext("foo", context.getServletContext());
|
||||
store.initialize(sessionContext);
|
||||
|
||||
//create file not for our context that expired long ago and should be removed
|
||||
FileTestHelper.createFile("101_foobar_0.0.0.0_sessiona");
|
||||
FileTestHelper.assertSessionExists("sessiona", true);
|
||||
|
||||
//create a file not for our context that is not expired and should be ignored
|
||||
String nonExpiredForeign = (System.currentTimeMillis()+TimeUnit.DAYS.toMillis(1))+"_foobar_0.0.0.0_sessionb";
|
||||
FileTestHelper.createFile(nonExpiredForeign);
|
||||
FileTestHelper.assertFileExists(nonExpiredForeign, true);
|
||||
|
||||
//create a file not for our context that is recently expired, a thus ignored
|
||||
String expiredForeign = (System.currentTimeMillis()-TimeUnit.SECONDS.toMillis(1))+"_foobar_0.0.0.0_sessionc";
|
||||
FileTestHelper.createFile(expiredForeign);
|
||||
FileTestHelper.assertFileExists(expiredForeign, true);
|
||||
|
||||
//create a file that is not a session file, it should be ignored
|
||||
FileTestHelper.createFile("whatever.txt");
|
||||
FileTestHelper.assertFileExists("whatever.txt", true);
|
||||
|
||||
//create a file that is not a valid session filename, should be ignored
|
||||
FileTestHelper.createFile("nonNumber_0.0.0.0_spuriousFile");
|
||||
FileTestHelper.assertFileExists("nonNumber_0.0.0.0_spuriousFile", true);
|
||||
|
||||
//create a file that is a non-expired session file for our context that should be ignored
|
||||
String nonExpired = (System.currentTimeMillis()+TimeUnit.DAYS.toMillis(1))+"_test_0.0.0.0_sessionb";
|
||||
FileTestHelper.createFile(nonExpired);
|
||||
FileTestHelper.assertFileExists(nonExpired, true);
|
||||
|
||||
//create a file that is a never-expire session file for our context that should be ignored
|
||||
String neverExpired = "0_test_0.0.0.0_sessionc";
|
||||
FileTestHelper.createFile(neverExpired);
|
||||
FileTestHelper.assertFileExists(neverExpired, true);
|
||||
|
||||
//create a file that is a never-expire session file for another context that should be ignored
|
||||
String foreignNeverExpired = "0_test_0.0.0.0_sessionc";
|
||||
FileTestHelper.createFile(foreignNeverExpired);
|
||||
FileTestHelper.assertFileExists(foreignNeverExpired, true);
|
||||
|
||||
//walk all files in the store
|
||||
((FileSessionDataStore)store).initializeStore();
|
||||
|
||||
//check results
|
||||
FileTestHelper.assertSessionExists("sessiona", false);
|
||||
FileTestHelper.assertFileExists("whatever.txt", true);
|
||||
FileTestHelper.assertFileExists("nonNumber_0.0.0.0_spuriousFile", true);
|
||||
FileTestHelper.assertFileExists(nonExpired, true);
|
||||
FileTestHelper.assertFileExists(nonExpiredForeign, true);
|
||||
FileTestHelper.assertFileExists(expiredForeign, true);
|
||||
FileTestHelper.assertFileExists(neverExpired, true);
|
||||
FileTestHelper.assertFileExists(foreignNeverExpired, true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If deleteUnrestorableFiles option is true, a damaged or unrestorable
|
||||
* file should be deleted.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testDeleteUnrestorableFiles ()
|
||||
throws Exception
|
||||
{
|
||||
//create the SessionDataStore
|
||||
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
||||
context.setContextPath("/test");
|
||||
SessionDataStoreFactory factory = createSessionDataStoreFactory();
|
||||
((AbstractSessionDataStoreFactory)factory).setGracePeriodSec(10);
|
||||
SessionDataStore store = factory.getSessionDataStore(context.getSessionHandler());
|
||||
SessionContext sessionContext = new SessionContext("foo", context.getServletContext());
|
||||
((FileSessionDataStore)store).setDeleteUnrestorableFiles(true); //invalid file will be removed
|
||||
store.initialize(sessionContext);
|
||||
|
||||
String expectedFilename = (System.currentTimeMillis() + 10000)+"__test_0.0.0.0_validFile123";
|
||||
FileTestHelper.createFile(expectedFilename);
|
||||
FileTestHelper.assertFileExists(expectedFilename, true);
|
||||
|
||||
store.start();
|
||||
|
||||
try
|
||||
{
|
||||
store.load("validFile123");
|
||||
fail("Load should fail");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//expected exception
|
||||
}
|
||||
|
||||
FileTestHelper.assertFileExists(expectedFilename, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests that only the most recent file will be
|
||||
* loaded into the cache, even if it is already
|
||||
* expired. Other recently expired files for
|
||||
* same session should be deleted.
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testLoadOnlyMostRecentFiles ()
|
||||
throws Exception
|
||||
{
|
||||
//create the SessionDataStore
|
||||
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
||||
context.setContextPath("/test");
|
||||
SessionDataStoreFactory factory = createSessionDataStoreFactory();
|
||||
((AbstractSessionDataStoreFactory)factory).setGracePeriodSec(100);
|
||||
SessionDataStore store = factory.getSessionDataStore(context.getSessionHandler());
|
||||
SessionContext sessionContext = new SessionContext("foo", context.getServletContext());
|
||||
store.initialize(sessionContext);
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
//create a file for session abc that expired 5sec ago
|
||||
long exp = now - 5000L;
|
||||
String name1 = Long.toString(exp)+"__test_0.0.0.0_abc";
|
||||
FileTestHelper.createFile(name1);
|
||||
|
||||
|
||||
//create a file for same session that expired 4 sec ago
|
||||
exp = now - 4000L;
|
||||
String name2 = Long.toString(exp)+"__test_0.0.0.0_abc";
|
||||
FileTestHelper.createFile(name2);
|
||||
|
||||
|
||||
//make a file for same session that expired 3 sec ago
|
||||
exp = now - 3000L;
|
||||
String name3 = Long.toString(exp)+"__test_0.0.0.0_abc";
|
||||
FileTestHelper.createFile(name3);
|
||||
|
||||
store.start();
|
||||
|
||||
FileTestHelper.assertFileExists(name1, false);
|
||||
FileTestHelper.assertFileExists(name2, false);
|
||||
FileTestHelper.assertFileExists(name3, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.gcloud.session;
|
||||
|
||||
import org.eclipse.jetty.server.session.AbstractClusteredLastAccessTimeTest;
|
||||
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* ClusteredLastAccessTimeTest
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ClusteredLastAccessTimeTest extends AbstractClusteredLastAccessTimeTest
|
||||
{
|
||||
|
||||
@AfterClass
|
||||
public static void teardown () throws Exception
|
||||
{
|
||||
GCloudTestSuite.__testSupport.deleteSessions();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
return GCloudSessionTestSupport.newSessionDataStoreFactory(GCloudTestSuite.__testSupport.getDatastore());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testLastAccessTime() throws Exception
|
||||
{
|
||||
super.testLastAccessTime();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.gcloud.session;
|
||||
|
||||
import org.eclipse.jetty.server.session.AbstractClusteredSessionMigrationTest;
|
||||
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* ClusteredSessionMigrationTest
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ClusteredSessionMigrationTest extends AbstractClusteredSessionMigrationTest
|
||||
{
|
||||
@AfterClass
|
||||
public static void teardown () throws Exception
|
||||
{
|
||||
GCloudTestSuite.__testSupport.deleteSessions();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
return GCloudSessionTestSupport.newSessionDataStoreFactory(GCloudTestSuite.__testSupport.getDatastore());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testSessionMigration() throws Exception
|
||||
{
|
||||
super.testSessionMigration();
|
||||
}
|
||||
}
|
|
@ -48,12 +48,5 @@ public class ClusteredSessionScavengingTest extends AbstractClusteredSessionScav
|
|||
return GCloudSessionTestSupport.newSessionDataStoreFactory(GCloudTestSuite.__testSupport.getDatastore());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testLocalSessionsScavenging() throws Exception
|
||||
{
|
||||
super.testLocalSessionsScavenging();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.gcloud.session;
|
||||
|
||||
import org.eclipse.jetty.server.session.AbstractSessionDataStoreTest;
|
||||
import org.eclipse.jetty.server.session.SessionData;
|
||||
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
|
||||
import org.junit.After;
|
||||
|
||||
/**
|
||||
* GCloudSessionDataStoreTest
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class GCloudSessionDataStoreTest extends AbstractSessionDataStoreTest
|
||||
{
|
||||
|
||||
@After
|
||||
public void teardown () throws Exception
|
||||
{
|
||||
GCloudTestSuite.__testSupport.deleteSessions();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
return GCloudSessionTestSupport.newSessionDataStoreFactory(GCloudTestSuite.__testSupport.getDatastore());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void persistSession(SessionData data) throws Exception
|
||||
{
|
||||
GCloudTestSuite.__testSupport.createSession(data.getId(), data.getContextPath(), data.getVhost(), data.getLastNode(), data.getCreated(),
|
||||
data.getAccessed(), data.getLastAccessed(), data.getMaxInactiveMs(), data.getExpiry(),
|
||||
data.getCookieSet(), data.getLastSaved(), data.getAllAttributes());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void persistUnreadableSession(SessionData data) throws Exception
|
||||
{
|
||||
|
||||
GCloudTestSuite.__testSupport.createSession(data.getId(), data.getContextPath(), data.getVhost(), data.getLastNode(), data.getCreated(),
|
||||
data.getAccessed(), data.getLastAccessed(), data.getMaxInactiveMs(), data.getExpiry(),
|
||||
data.getCookieSet(), data.getLastSaved(), null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean checkSessionExists(SessionData data) throws Exception
|
||||
{
|
||||
return GCloudTestSuite.__testSupport.checkSessionExists(data.getId());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public boolean checkSessionPersisted(SessionData data) throws Exception
|
||||
{
|
||||
return GCloudTestSuite.__testSupport.checkSessionPersisted(data);
|
||||
}
|
||||
|
||||
}
|
|
@ -21,24 +21,36 @@ package org.eclipse.jetty.gcloud.session;
|
|||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jetty.gcloud.session.GCloudSessionDataStore.EntityDataModel;
|
||||
import org.eclipse.jetty.server.session.SessionData;
|
||||
import org.eclipse.jetty.server.session.SessionDataStore;
|
||||
import org.eclipse.jetty.server.session.SessionHandler;
|
||||
import org.eclipse.jetty.util.ClassLoadingObjectInputStream;
|
||||
import org.threeten.bp.Duration;
|
||||
|
||||
import com.google.cloud.datastore.Blob;
|
||||
import com.google.cloud.datastore.BlobValue;
|
||||
import com.google.cloud.datastore.Datastore;
|
||||
import com.google.cloud.datastore.DatastoreOptions;
|
||||
import com.google.cloud.datastore.Entity;
|
||||
import com.google.cloud.datastore.GqlQuery;
|
||||
import com.google.cloud.datastore.Key;
|
||||
import com.google.cloud.datastore.KeyFactory;
|
||||
import com.google.cloud.datastore.Query;
|
||||
import com.google.cloud.datastore.Query.ResultType;
|
||||
import com.google.cloud.datastore.QueryResults;
|
||||
import com.google.cloud.datastore.StructuredQuery.PropertyFilter;
|
||||
import com.google.cloud.datastore.testing.LocalDatastoreHelper;
|
||||
|
||||
/**
|
||||
|
@ -50,6 +62,7 @@ public class GCloudSessionTestSupport
|
|||
{
|
||||
LocalDatastoreHelper _helper = LocalDatastoreHelper.create(1.0);
|
||||
Datastore _ds;
|
||||
KeyFactory _keyFactory;
|
||||
|
||||
|
||||
public static class TestGCloudSessionDataStoreFactory extends GCloudSessionDataStoreFactory
|
||||
|
@ -82,6 +95,7 @@ public class GCloudSessionTestSupport
|
|||
{
|
||||
DatastoreOptions options = _helper.getOptions();
|
||||
_ds = options.getService();
|
||||
_keyFactory =_ds.newKeyFactory().setKind(EntityDataModel.KIND);
|
||||
}
|
||||
|
||||
|
||||
|
@ -111,6 +125,103 @@ public class GCloudSessionTestSupport
|
|||
_helper.reset();
|
||||
}
|
||||
|
||||
public void createSession (String id, String contextPath, String vhost,
|
||||
String lastNode, long created, long accessed,
|
||||
long lastAccessed, long maxIdle, long expiry,
|
||||
long cookieset, long lastSaved,
|
||||
Map<String,Object> attributes)
|
||||
throws Exception
|
||||
{
|
||||
//serialize the attribute map
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
if (attributes != null)
|
||||
{
|
||||
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
||||
oos.writeObject(attributes);
|
||||
oos.flush();
|
||||
}
|
||||
|
||||
//turn a session into an entity
|
||||
Entity.Builder builder = Entity.newBuilder(_keyFactory.newKey(contextPath+"_"+vhost+"_"+id))
|
||||
.set(EntityDataModel.ID, id)
|
||||
.set(EntityDataModel.CONTEXTPATH, contextPath)
|
||||
.set(EntityDataModel.VHOST, vhost)
|
||||
.set(EntityDataModel.ACCESSED, accessed)
|
||||
.set(EntityDataModel.LASTACCESSED, lastAccessed)
|
||||
.set(EntityDataModel.CREATETIME, created)
|
||||
.set(EntityDataModel.COOKIESETTIME, cookieset)
|
||||
.set(EntityDataModel.LASTNODE, lastNode)
|
||||
.set(EntityDataModel.EXPIRY, expiry)
|
||||
.set(EntityDataModel.MAXINACTIVE, maxIdle)
|
||||
.set(EntityDataModel.LASTSAVED, lastSaved);
|
||||
if (attributes != null)
|
||||
builder.set(EntityDataModel.ATTRIBUTES, BlobValue.newBuilder(Blob.copyFrom(baos.toByteArray())).setExcludeFromIndexes(true).build());
|
||||
|
||||
Entity entity = builder.build();
|
||||
|
||||
_ds.put(entity);
|
||||
}
|
||||
|
||||
public boolean checkSessionPersisted (SessionData data)
|
||||
throws Exception
|
||||
{
|
||||
Entity entity = _ds.get(_keyFactory.newKey(data.getContextPath()+"_"+data.getVhost()+"_"+data.getId()));
|
||||
if (entity == null)
|
||||
return false;
|
||||
|
||||
//turn an Entity into a Session
|
||||
assertEquals(data.getId(), entity.getString(EntityDataModel.ID));
|
||||
assertEquals(data.getContextPath(), entity.getString(EntityDataModel.CONTEXTPATH));
|
||||
assertEquals(data.getVhost(), entity.getString(EntityDataModel.VHOST));
|
||||
assertEquals(data.getAccessed(), entity.getLong(EntityDataModel.ACCESSED));
|
||||
assertEquals(data.getLastAccessed(), entity.getLong(EntityDataModel.LASTACCESSED));
|
||||
assertEquals(data.getCreated(), entity.getLong(EntityDataModel.CREATETIME));
|
||||
assertEquals(data.getCookieSet(), entity.getLong(EntityDataModel.COOKIESETTIME));
|
||||
assertEquals(data.getLastNode(), entity.getString(EntityDataModel.LASTNODE));
|
||||
assertEquals(data.getLastSaved(), entity.getLong(EntityDataModel.LASTSAVED));
|
||||
assertEquals(data.getExpiry(), entity.getLong(EntityDataModel.EXPIRY));
|
||||
assertEquals(data.getMaxInactiveMs(), entity.getLong(EntityDataModel.MAXINACTIVE));
|
||||
Blob blob = (Blob) entity.getBlob(EntityDataModel.ATTRIBUTES);
|
||||
|
||||
Map<String,Object> attributes = new HashMap<>();
|
||||
try (ClassLoadingObjectInputStream ois = new ClassLoadingObjectInputStream(blob.asInputStream()))
|
||||
{
|
||||
Object o = ois.readObject();
|
||||
attributes.putAll((Map<String,Object>)o);
|
||||
}
|
||||
|
||||
//same number of attributes
|
||||
assertEquals(data.getAllAttributes().size(), attributes.size());
|
||||
//same keys
|
||||
assertTrue(data.getKeys().equals(attributes.keySet()));
|
||||
//same values
|
||||
for (String name:data.getKeys())
|
||||
{
|
||||
assertTrue(data.getAttribute(name).equals(attributes.get(name)));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public boolean checkSessionExists (String id)
|
||||
throws Exception
|
||||
{
|
||||
Query<Entity> query = Query.newEntityQueryBuilder()
|
||||
.setKind(EntityDataModel.KIND)
|
||||
.setFilter(PropertyFilter.eq(EntityDataModel.ID, id))
|
||||
.build();
|
||||
|
||||
QueryResults<Entity> results = _ds.run(query);
|
||||
|
||||
|
||||
if (results.hasNext())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public Set<String> getSessionIds () throws Exception
|
||||
{
|
||||
|
|
|
@ -31,15 +31,10 @@ import org.junit.runners.Suite;
|
|||
*/
|
||||
@RunWith(Suite.class)
|
||||
@Suite.SuiteClasses({
|
||||
GCloudSessionDataStoreTest.class,
|
||||
InvalidationSessionTest.class,
|
||||
ClusteredLastAccessTimeTest.class,
|
||||
ClusteredSessionScavengingTest.class,
|
||||
NonClusteredSessionScavengingTest.class,
|
||||
ClusteredOrphanedSessionTest.class,
|
||||
SessionExpiryTest.class,
|
||||
SessionInvalidateCreateScavengeTest.class,
|
||||
ClusteredSessionMigrationTest.class,
|
||||
ModifyMaxInactiveIntervalTest.class
|
||||
ClusteredOrphanedSessionTest.class
|
||||
})
|
||||
|
||||
|
||||
|
|
|
@ -1,82 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.gcloud.session;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jetty.server.session.AbstractNonClusteredSessionScavengingTest;
|
||||
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* NonClusteredSessionScavengingTest
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class NonClusteredSessionScavengingTest extends AbstractNonClusteredSessionScavengingTest
|
||||
{
|
||||
|
||||
|
||||
@After
|
||||
public void teardown () throws Exception
|
||||
{
|
||||
GCloudTestSuite.__testSupport.deleteSessions();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractNonClusteredSessionScavengingTest#assertSession(java.lang.String, boolean)
|
||||
*/
|
||||
@Override
|
||||
public void assertSession(String id, boolean exists)
|
||||
{
|
||||
try
|
||||
{
|
||||
Set<String> ids = GCloudTestSuite.__testSupport.getSessionIds();
|
||||
if (exists)
|
||||
assertTrue(ids.contains(id));
|
||||
else
|
||||
assertFalse(ids.contains(id));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
fail(e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
return GCloudSessionTestSupport.newSessionDataStoreFactory(GCloudTestSuite.__testSupport.getDatastore());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.gcloud.session;
|
||||
|
||||
import org.eclipse.jetty.server.session.AbstractSessionExpiryTest;
|
||||
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
/**
|
||||
* SessionExpiryTest
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class SessionExpiryTest extends AbstractSessionExpiryTest
|
||||
{
|
||||
|
||||
@After
|
||||
public void teardown () throws Exception
|
||||
{
|
||||
GCloudTestSuite.__testSupport.deleteSessions();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
return GCloudSessionTestSupport.newSessionDataStoreFactory(GCloudTestSuite.__testSupport.getDatastore());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void verifySessionCreated(TestHttpSessionListener listener, String sessionId)
|
||||
{
|
||||
super.verifySessionCreated(listener, sessionId);
|
||||
try {GCloudTestSuite.__testSupport.assertSessions(1);}catch(Exception e){ Assert.fail(e.getMessage());}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void verifySessionDestroyed(TestHttpSessionListener listener, String sessionId)
|
||||
{
|
||||
super.verifySessionDestroyed(listener, sessionId);
|
||||
//try{GCloudTestSuite.__testSupport.assertSessions(0);}catch(Exception e) {Assert.fail(e.getMessage());}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.gcloud.session;
|
||||
|
||||
import org.eclipse.jetty.server.session.AbstractSessionInvalidateCreateScavengeTest;
|
||||
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* SessionInvalidateCreateScavengeTest
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class SessionInvalidateCreateScavengeTest extends AbstractSessionInvalidateCreateScavengeTest
|
||||
{
|
||||
@AfterClass
|
||||
public static void teardown () throws Exception
|
||||
{
|
||||
GCloudTestSuite.__testSupport.deleteSessions();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
return GCloudSessionTestSupport.newSessionDataStoreFactory(GCloudTestSuite.__testSupport.getDatastore());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testSessionScavenge() throws Exception
|
||||
{
|
||||
super.testSessionScavenge();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty.tests</groupId>
|
||||
<artifactId>test-sessions-parent</artifactId>
|
||||
<version>9.4.10-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>test-hash-sessions</artifactId>
|
||||
<name>Jetty Tests :: Sessions :: Hash</name>
|
||||
<url>http://www.eclipse.org/jetty</url>
|
||||
<properties>
|
||||
<bundle-symbolic-name>${project.groupId}.sessions.hash</bundle-symbolic-name>
|
||||
</properties>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<configuration>
|
||||
<!-- DO NOT DEPLOY (or Release) -->
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-webapp</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.tests</groupId>
|
||||
<artifactId>test-sessions-common</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-test-helper</artifactId>
|
||||
<!-- Leaving at compile scope for intellij bug reasons -->
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -1,56 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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;
|
||||
|
||||
/**
|
||||
* NonClusteredSessionScavengingTest
|
||||
*/
|
||||
public class NonClusteredSessionScavengingTest extends AbstractNonClusteredSessionScavengingTest
|
||||
{
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractNonClusteredSessionScavengingTest#assertSession(java.lang.String, boolean)
|
||||
*/
|
||||
@Override
|
||||
public void assertSession(String id, boolean exists)
|
||||
{
|
||||
//noop, as we do not have a session store
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testNewSession() throws Exception
|
||||
{
|
||||
super.testNewSession();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
return HashTestHelper.newSessionDataStoreFactory();
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.hazelcast.session;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.server.session.AbstractClusteredLastAccessTimeTest;
|
||||
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
|
||||
import org.junit.After;
|
||||
|
||||
public class ClusteredLastAccessTimeTest
|
||||
extends AbstractClusteredLastAccessTimeTest
|
||||
{
|
||||
|
||||
HazelcastSessionDataStoreFactory factory;
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
factory = new HazelcastSessionDataStoreFactory();
|
||||
factory.setMapName( Long.toString( TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) ) );
|
||||
return factory;
|
||||
}
|
||||
|
||||
@After
|
||||
public void shutdown()
|
||||
{
|
||||
factory.getHazelcastInstance().getMap( factory.getMapName() ).clear();
|
||||
}
|
||||
|
||||
}
|
|
@ -24,6 +24,7 @@ import java.util.concurrent.TimeUnit;
|
|||
import org.eclipse.jetty.server.session.AbstractClusteredOrphanedSessionTest;
|
||||
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
/**
|
||||
* ClusteredOrphanedSessionTest
|
||||
|
@ -34,20 +35,26 @@ public class ClusteredOrphanedSessionTest
|
|||
|
||||
HazelcastSessionDataStoreFactory factory;
|
||||
|
||||
HazelcastTestHelper _testHelper;
|
||||
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
_testHelper = new HazelcastTestHelper();
|
||||
}
|
||||
|
||||
@After
|
||||
public void shutdown()
|
||||
{
|
||||
_testHelper.tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
factory = new HazelcastSessionDataStoreFactory();
|
||||
factory.setMapName( Long.toString( TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) ) );
|
||||
return factory;
|
||||
}
|
||||
|
||||
@After
|
||||
public void shutdown()
|
||||
{
|
||||
factory.getHazelcastInstance().getMap( factory.getMapName() ).clear();
|
||||
return _testHelper.createSessionDataStoreFactory(false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.hazelcast.session;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.server.session.AbstractClusteredSessionMigrationTest;
|
||||
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
|
||||
import org.junit.After;
|
||||
|
||||
/**
|
||||
* ClusteredSessionMigrationTest
|
||||
*/
|
||||
public class ClusteredSessionMigrationTest
|
||||
extends AbstractClusteredSessionMigrationTest
|
||||
{
|
||||
HazelcastSessionDataStoreFactory factory;
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
factory = new HazelcastSessionDataStoreFactory();
|
||||
factory.setMapName( Long.toString( TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) ) );
|
||||
return factory;
|
||||
}
|
||||
|
||||
@After
|
||||
public void shutdown()
|
||||
{
|
||||
factory.getHazelcastInstance().getMap( factory.getMapName() ).clear();
|
||||
}
|
||||
}
|
|
@ -24,6 +24,7 @@ import java.util.concurrent.TimeUnit;
|
|||
import org.eclipse.jetty.server.session.AbstractClusteredSessionScavengingTest;
|
||||
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
/**
|
||||
* ClusteredSessionScavengingTest
|
||||
|
@ -34,20 +35,27 @@ public class ClusteredSessionScavengingTest
|
|||
|
||||
HazelcastSessionDataStoreFactory factory;
|
||||
|
||||
HazelcastTestHelper _testHelper;
|
||||
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
_testHelper = new HazelcastTestHelper();
|
||||
}
|
||||
|
||||
@After
|
||||
public void shutdown()
|
||||
{
|
||||
_testHelper.tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
factory = new HazelcastSessionDataStoreFactory();
|
||||
factory.setMapName( Long.toString( TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) ) );
|
||||
return factory;
|
||||
return _testHelper.createSessionDataStoreFactory(false);
|
||||
}
|
||||
|
||||
@After
|
||||
public void shutdown()
|
||||
{
|
||||
factory.getHazelcastInstance().getMap( factory.getMapName() ).clear();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.hazelcast.session;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import org.eclipse.jetty.server.session.AbstractSessionDataStoreFactory;
|
||||
import org.eclipse.jetty.server.session.AbstractSessionDataStoreTest;
|
||||
import org.eclipse.jetty.server.session.SessionContext;
|
||||
import org.eclipse.jetty.server.session.SessionData;
|
||||
import org.eclipse.jetty.server.session.SessionDataStore;
|
||||
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
|
||||
import org.eclipse.jetty.server.session.UnreadableSessionDataException;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
/**
|
||||
* HazelcastSessionDataStoreTest
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class HazelcastSessionDataStoreTest extends AbstractSessionDataStoreTest
|
||||
{
|
||||
|
||||
HazelcastTestHelper _testHelper;
|
||||
|
||||
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
return _testHelper.createSessionDataStoreFactory(false);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
_testHelper = new HazelcastTestHelper();
|
||||
}
|
||||
|
||||
@After
|
||||
public void shutdown()
|
||||
{
|
||||
_testHelper.tearDown();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void persistSession(SessionData data) throws Exception
|
||||
{
|
||||
_testHelper.createSession(data);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void persistUnreadableSession(SessionData data) throws Exception
|
||||
{
|
||||
//not used by testLoadSessionFails()
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean checkSessionExists(SessionData data) throws Exception
|
||||
{
|
||||
return _testHelper.checkSessionExists(data);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* This test deliberately sets the sessionDataMap to null
|
||||
* for the HazelcastSessionDataStore to provoke an exception
|
||||
* in the load() method.
|
||||
*/
|
||||
@Override
|
||||
public void testLoadSessionFails() throws Exception
|
||||
{
|
||||
//create the SessionDataStore
|
||||
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
||||
context.setContextPath("/test");
|
||||
SessionDataStoreFactory factory = createSessionDataStoreFactory();
|
||||
((AbstractSessionDataStoreFactory)factory).setGracePeriodSec(GRACE_PERIOD_SEC);
|
||||
SessionDataStore store = factory.getSessionDataStore(context.getSessionHandler());
|
||||
SessionContext sessionContext = new SessionContext("foo", context.getServletContext());
|
||||
store.initialize(sessionContext);
|
||||
|
||||
|
||||
//persist a session
|
||||
long now = System.currentTimeMillis();
|
||||
SessionData data = store.newSessionData("222", 100, now, now-1, -1);
|
||||
data.setLastNode(sessionContext.getWorkerName());
|
||||
persistSession(data);
|
||||
|
||||
store.start();
|
||||
|
||||
((HazelcastSessionDataStore)store).setSessionDataMap(null);
|
||||
|
||||
|
||||
//test that loading it fails
|
||||
try
|
||||
{
|
||||
store.load("222");
|
||||
fail("Session should be unreadable");
|
||||
}
|
||||
catch (UnreadableSessionDataException e)
|
||||
{
|
||||
//expected exception
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This test currently won't work for Hazelcast - there is currently no
|
||||
* means to query it to find sessions that have expired.
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public void testGetExpiredPersistedAndExpiredOnly() throws Exception
|
||||
{
|
||||
//ignore
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This test currently won't work for Hazelcast - there is currently no
|
||||
* means to query it to find sessions that have expired.
|
||||
*/
|
||||
@Override
|
||||
public void testGetExpiredDifferentNode() throws Exception
|
||||
{
|
||||
//ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkSessionPersisted(SessionData data) throws Exception
|
||||
{
|
||||
return _testHelper.checkSessionPersisted(data);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.hazelcast.session;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.server.session.SessionData;
|
||||
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
|
||||
|
||||
import com.hazelcast.config.Config;
|
||||
import com.hazelcast.config.MapConfig;
|
||||
import com.hazelcast.core.Hazelcast;
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
|
||||
/**
|
||||
* HazelcastTestHelper
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class HazelcastTestHelper
|
||||
{
|
||||
static String _hazelcastInstanceName = "SESSION_TEST_"+Long.toString( TimeUnit.NANOSECONDS.toMillis(System.nanoTime()));
|
||||
|
||||
static String _name = Long.toString( TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) );
|
||||
static HazelcastInstance _instance;
|
||||
static {
|
||||
MapConfig mapConfig = new MapConfig();
|
||||
mapConfig.setName(_name);
|
||||
Config config = new Config();
|
||||
config.setInstanceName(_hazelcastInstanceName );
|
||||
config.addMapConfig( mapConfig );
|
||||
_instance = Hazelcast.getOrCreateHazelcastInstance( config );
|
||||
}
|
||||
|
||||
|
||||
public HazelcastTestHelper ()
|
||||
{
|
||||
// noop
|
||||
}
|
||||
|
||||
// definitely not thread safe so tests cannot be executed in parallel
|
||||
// TODO use ThreadContext variable for this Map name
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory(boolean onlyClient)
|
||||
{
|
||||
HazelcastSessionDataStoreFactory factory = new HazelcastSessionDataStoreFactory();
|
||||
_name = Long.toString( TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) );
|
||||
factory.setOnlyClient( onlyClient );
|
||||
factory.setMapName(_name);
|
||||
factory.setHazelcastInstance(_instance);
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
|
||||
public void tearDown()
|
||||
{
|
||||
_instance.getMap(_name).clear();
|
||||
}
|
||||
|
||||
public void createSession (SessionData data)
|
||||
{
|
||||
_instance.getMap(_name).put(data.getContextPath() + "_" + data.getVhost() + "_" + data.getId(), data);
|
||||
}
|
||||
|
||||
public boolean checkSessionExists (SessionData data)
|
||||
{
|
||||
return (_instance.getMap(_name).get(data.getContextPath() + "_" + data.getVhost() + "_" + data.getId()) != null);
|
||||
}
|
||||
|
||||
public boolean checkSessionPersisted (SessionData data)
|
||||
{
|
||||
Object obj = _instance.getMap(_name).get(data.getContextPath() + "_" + data.getVhost() + "_" + data.getId());
|
||||
if (obj == null)
|
||||
return false;
|
||||
|
||||
SessionData saved = (SessionData)obj;
|
||||
|
||||
assertEquals(data.getId(),saved.getId());
|
||||
assertEquals(data.getContextPath(), saved.getContextPath());
|
||||
assertEquals(data.getVhost(), saved.getVhost());
|
||||
assertEquals(data.getLastNode(), saved.getLastNode());
|
||||
assertEquals(data.getCreated(), saved.getCreated());
|
||||
assertEquals(data.getAccessed(), saved.getAccessed());
|
||||
assertEquals(data.getLastAccessed(), saved.getLastAccessed());
|
||||
assertEquals(data.getCookieSet(), saved.getCookieSet());
|
||||
assertEquals(data.getExpiry(), saved.getExpiry());
|
||||
assertEquals(data.getMaxInactiveMs(), saved.getMaxInactiveMs());
|
||||
|
||||
|
||||
//same number of attributes
|
||||
assertEquals(data.getAllAttributes().size(),saved.getAllAttributes().size());
|
||||
//same keys
|
||||
assertTrue(data.getKeys().equals(saved.getKeys()));
|
||||
//same values
|
||||
for (String name:data.getKeys())
|
||||
{
|
||||
assertTrue(data.getAttribute(name).equals(saved.getAttribute(name)));
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.hazelcast.session;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.server.session.AbstractModifyMaxInactiveIntervalTest;
|
||||
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
|
||||
import org.junit.After;
|
||||
|
||||
/**
|
||||
* ModifyMaxInactiveIntervalTest
|
||||
*/
|
||||
public class ModifyMaxInactiveIntervalTest
|
||||
extends AbstractModifyMaxInactiveIntervalTest
|
||||
{
|
||||
|
||||
HazelcastSessionDataStoreFactory factory;
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
factory = new HazelcastSessionDataStoreFactory();
|
||||
factory.setMapName( Long.toString( TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) ) );
|
||||
return factory;
|
||||
}
|
||||
|
||||
@After
|
||||
public void shutdown()
|
||||
{
|
||||
factory.getHazelcastInstance().getMap( factory.getMapName() ).clear();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.hazelcast.session;
|
||||
|
||||
import org.eclipse.jetty.server.session.AbstractNonClusteredSessionScavengingTest;
|
||||
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
|
||||
import org.junit.After;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* NonClusteredSessionScavengingTest
|
||||
*/
|
||||
public class NonClusteredSessionScavengingTest
|
||||
extends AbstractNonClusteredSessionScavengingTest
|
||||
{
|
||||
|
||||
HazelcastSessionDataStoreFactory factory;
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractNonClusteredSessionScavengingTest#assertSession(java.lang.String, boolean)
|
||||
*/
|
||||
@Override
|
||||
public void assertSession( String id, boolean exists )
|
||||
{
|
||||
assertNotNull( _dataStore );
|
||||
|
||||
try
|
||||
{
|
||||
boolean inmap = _dataStore.exists( id );
|
||||
if ( exists )
|
||||
{
|
||||
assertTrue( inmap );
|
||||
}
|
||||
else
|
||||
{
|
||||
assertFalse( inmap );
|
||||
}
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
fail( e.getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
factory = new HazelcastSessionDataStoreFactory();
|
||||
factory.setMapName( Long.toString( TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) ) );
|
||||
return factory;
|
||||
}
|
||||
|
||||
@After
|
||||
public void shutdown()
|
||||
{
|
||||
factory.getHazelcastInstance().getMap( factory.getMapName() ).clear();
|
||||
}
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.hazelcast.session;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.server.session.AbstractSessionExpiryTest;
|
||||
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SessionExpiryTest
|
||||
extends AbstractSessionExpiryTest
|
||||
{
|
||||
|
||||
HazelcastSessionDataStoreFactory factory;
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
factory = new HazelcastSessionDataStoreFactory();
|
||||
factory.setMapName( Long.toString( TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) ) );
|
||||
return factory;
|
||||
}
|
||||
|
||||
@After
|
||||
public void shutdown()
|
||||
{
|
||||
factory.getHazelcastInstance().getMap( factory.getMapName() ).clear();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.hazelcast.session;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.server.session.AbstractSessionInvalidateCreateScavengeTest;
|
||||
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
|
||||
import org.junit.After;
|
||||
|
||||
/**
|
||||
* SessionInvalidateCreateScavengeTest
|
||||
*/
|
||||
public class SessionInvalidateCreateScavengeTest
|
||||
extends AbstractSessionInvalidateCreateScavengeTest
|
||||
{
|
||||
|
||||
HazelcastSessionDataStoreFactory factory;
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
factory = new HazelcastSessionDataStoreFactory();
|
||||
factory.setMapName( Long.toString( TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) ) );
|
||||
return factory;
|
||||
}
|
||||
|
||||
@After
|
||||
public void shutdown()
|
||||
{
|
||||
factory.getHazelcastInstance().getMap( factory.getMapName() ).clear();
|
||||
}
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.hazelcast.session.client;
|
||||
|
||||
import com.hazelcast.config.Config;
|
||||
import com.hazelcast.config.MapConfig;
|
||||
import com.hazelcast.core.Hazelcast;
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.hazelcast.session.HazelcastSessionDataStoreFactory;
|
||||
import org.eclipse.jetty.server.session.AbstractClusteredLastAccessTimeTest;
|
||||
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
public class ClientLastAccessTimeTest
|
||||
extends AbstractClusteredLastAccessTimeTest
|
||||
{
|
||||
|
||||
private static final String MAP_NAME = Long.toString( TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) );
|
||||
|
||||
private HazelcastInstance hazelcastInstance;
|
||||
|
||||
@Before
|
||||
public void startHazelcast()
|
||||
throws Exception
|
||||
{
|
||||
Config config = new Config().addMapConfig( new MapConfig().setName( MAP_NAME ) ) //
|
||||
.setInstanceName( Long.toString( System.currentTimeMillis() ) );
|
||||
// start Hazelcast instance
|
||||
hazelcastInstance = Hazelcast.getOrCreateHazelcastInstance( config );
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopHazelcast()
|
||||
throws Exception
|
||||
{
|
||||
hazelcastInstance.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
HazelcastSessionDataStoreFactory factory = new HazelcastSessionDataStoreFactory();
|
||||
factory.setOnlyClient( true );
|
||||
factory.setMapName( MAP_NAME );
|
||||
return factory;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.hazelcast.session.client;
|
||||
|
||||
import com.hazelcast.config.Config;
|
||||
import com.hazelcast.config.MapConfig;
|
||||
import com.hazelcast.core.Hazelcast;
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.hazelcast.session.HazelcastSessionDataStoreFactory;
|
||||
import org.eclipse.jetty.server.session.AbstractModifyMaxInactiveIntervalTest;
|
||||
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
/**
|
||||
* ModifyMaxInactiveIntervalTest
|
||||
*/
|
||||
public class ClientModifyMaxInactiveIntervalTest
|
||||
extends AbstractModifyMaxInactiveIntervalTest
|
||||
{
|
||||
|
||||
private static final String MAP_NAME = Long.toString( TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) );
|
||||
|
||||
private HazelcastInstance hazelcastInstance;
|
||||
|
||||
@Before
|
||||
public void startHazelcast()
|
||||
throws Exception
|
||||
{
|
||||
Config config = new Config().addMapConfig( new MapConfig().setName( MAP_NAME ) ) //
|
||||
.setInstanceName( Long.toString( System.currentTimeMillis() ) );
|
||||
// start Hazelcast instance
|
||||
hazelcastInstance = Hazelcast.getOrCreateHazelcastInstance( config );
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopHazelcast()
|
||||
throws Exception
|
||||
{
|
||||
hazelcastInstance.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
HazelcastSessionDataStoreFactory factory = new HazelcastSessionDataStoreFactory();
|
||||
factory.setOnlyClient( true );
|
||||
factory.setMapName( MAP_NAME );
|
||||
return factory;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.hazelcast.session.client;
|
||||
|
||||
import com.hazelcast.config.Config;
|
||||
import com.hazelcast.config.MapConfig;
|
||||
import com.hazelcast.core.Hazelcast;
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
import org.eclipse.jetty.hazelcast.session.HazelcastSessionDataStoreFactory;
|
||||
import org.eclipse.jetty.server.session.AbstractNonClusteredSessionScavengingTest;
|
||||
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class ClientNonClusteredSessionScavengingTest
|
||||
extends AbstractNonClusteredSessionScavengingTest
|
||||
{
|
||||
|
||||
/**
|
||||
* @see AbstractNonClusteredSessionScavengingTest#assertSession(String, boolean)
|
||||
*/
|
||||
@Override
|
||||
public void assertSession( String id, boolean exists )
|
||||
{
|
||||
assertNotNull( _dataStore );
|
||||
|
||||
try
|
||||
{
|
||||
boolean inmap = _dataStore.exists( id );
|
||||
if ( exists )
|
||||
{
|
||||
assertTrue( inmap );
|
||||
}
|
||||
else
|
||||
{
|
||||
assertFalse( inmap );
|
||||
}
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
fail( e.getMessage() );
|
||||
}
|
||||
}
|
||||
private static final String MAP_NAME = Long.toString( TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) );
|
||||
|
||||
private HazelcastInstance hazelcastInstance;
|
||||
|
||||
@Before
|
||||
public void startHazelcast()
|
||||
throws Exception
|
||||
{
|
||||
Config config = new Config().addMapConfig( new MapConfig().setName( MAP_NAME ) ) //
|
||||
.setInstanceName( Long.toString( System.currentTimeMillis() ) );
|
||||
// start Hazelcast instance
|
||||
hazelcastInstance = Hazelcast.getOrCreateHazelcastInstance( config );
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopHazelcast()
|
||||
throws Exception
|
||||
{
|
||||
hazelcastInstance.shutdown();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
HazelcastSessionDataStoreFactory factory = new HazelcastSessionDataStoreFactory();
|
||||
factory.setOnlyClient( true );
|
||||
factory.setMapName( MAP_NAME );
|
||||
return factory;
|
||||
}
|
||||
}
|
|
@ -27,6 +27,7 @@ import com.hazelcast.core.HazelcastInstance;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.hazelcast.session.HazelcastSessionDataStoreFactory;
|
||||
import org.eclipse.jetty.hazelcast.session.HazelcastTestHelper;
|
||||
import org.eclipse.jetty.server.session.AbstractClusteredOrphanedSessionTest;
|
||||
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
|
||||
import org.junit.After;
|
||||
|
@ -36,37 +37,24 @@ public class ClientOrphanedSessionTest
|
|||
extends AbstractClusteredOrphanedSessionTest
|
||||
{
|
||||
|
||||
private static final String MAP_NAME = Long.toString( TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) );
|
||||
HazelcastTestHelper _testHelper;
|
||||
|
||||
private HazelcastInstance hazelcastInstance;
|
||||
|
||||
@Before
|
||||
public void startHazelcast()
|
||||
throws Exception
|
||||
{
|
||||
Config config = new Config().addMapConfig( new MapConfig().setName( MAP_NAME ) ) //
|
||||
.setInstanceName( Long.toString( System.currentTimeMillis() ) );
|
||||
// start Hazelcast instance
|
||||
hazelcastInstance = Hazelcast.getOrCreateHazelcastInstance( config );
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopHazelcast()
|
||||
throws Exception
|
||||
{
|
||||
hazelcastInstance.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
HazelcastSessionDataStoreFactory factory = new HazelcastSessionDataStoreFactory();
|
||||
factory.setOnlyClient( true );
|
||||
factory.setMapName( MAP_NAME );
|
||||
return factory;
|
||||
return _testHelper.createSessionDataStoreFactory(true);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
_testHelper = new HazelcastTestHelper();
|
||||
}
|
||||
|
||||
@After
|
||||
public void shutdown()
|
||||
{
|
||||
_testHelper.tearDown();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,73 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.hazelcast.session.client;
|
||||
|
||||
import com.hazelcast.config.Config;
|
||||
import com.hazelcast.config.MapConfig;
|
||||
import com.hazelcast.core.Hazelcast;
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.hazelcast.session.HazelcastSessionDataStoreFactory;
|
||||
import org.eclipse.jetty.server.session.AbstractSessionExpiryTest;
|
||||
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
public class ClientSessionExpiryTest
|
||||
extends AbstractSessionExpiryTest
|
||||
{
|
||||
|
||||
private static final String MAP_NAME = Long.toString( TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) );
|
||||
|
||||
private HazelcastInstance hazelcastInstance;
|
||||
|
||||
@Before
|
||||
public void startHazelcast()
|
||||
throws Exception
|
||||
{
|
||||
Config config = new Config().addMapConfig( new MapConfig().setName( MAP_NAME ) ) //
|
||||
.setInstanceName( Long.toString( System.currentTimeMillis() ) );
|
||||
// start Hazelcast instance
|
||||
hazelcastInstance = Hazelcast.getOrCreateHazelcastInstance( config );
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopHazelcast()
|
||||
throws Exception
|
||||
{
|
||||
hazelcastInstance.shutdown();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
HazelcastSessionDataStoreFactory factory = new HazelcastSessionDataStoreFactory();
|
||||
factory.setOnlyClient( true );
|
||||
factory.setMapName( MAP_NAME );
|
||||
return factory;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.hazelcast.session.client;
|
||||
|
||||
import com.hazelcast.config.Config;
|
||||
import com.hazelcast.config.MapConfig;
|
||||
import com.hazelcast.core.Hazelcast;
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.hazelcast.session.HazelcastSessionDataStoreFactory;
|
||||
import org.eclipse.jetty.server.session.AbstractSessionInvalidateCreateScavengeTest;
|
||||
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
public class ClientSessionInvalidateCreateScavengeTest
|
||||
extends AbstractSessionInvalidateCreateScavengeTest
|
||||
{
|
||||
private static final String MAP_NAME = Long.toString( TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) );
|
||||
|
||||
private HazelcastInstance hazelcastInstance;
|
||||
|
||||
@Before
|
||||
public void startHazelcast()
|
||||
throws Exception
|
||||
{
|
||||
Config config = new Config().addMapConfig( new MapConfig().setName( MAP_NAME ) ) //
|
||||
.setInstanceName( Long.toString( System.currentTimeMillis() ) );
|
||||
// start Hazelcast instance
|
||||
hazelcastInstance = Hazelcast.getOrCreateHazelcastInstance( config );
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopHazelcast()
|
||||
throws Exception
|
||||
{
|
||||
hazelcastInstance.shutdown();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
HazelcastSessionDataStoreFactory factory = new HazelcastSessionDataStoreFactory();
|
||||
factory.setOnlyClient( true );
|
||||
factory.setMapName( MAP_NAME );
|
||||
return factory;
|
||||
}
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.hazelcast.session.client;
|
||||
|
||||
import com.hazelcast.config.Config;
|
||||
import com.hazelcast.config.MapConfig;
|
||||
import com.hazelcast.core.Hazelcast;
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.hazelcast.session.HazelcastSessionDataStoreFactory;
|
||||
import org.eclipse.jetty.server.session.AbstractClusteredSessionMigrationTest;
|
||||
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
/**
|
||||
* ClusteredSessionMigrationTest
|
||||
*/
|
||||
public class ClientSessionMigrationTest
|
||||
extends AbstractClusteredSessionMigrationTest
|
||||
{
|
||||
private static final String MAP_NAME = Long.toString( TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) );
|
||||
|
||||
private HazelcastInstance hazelcastInstance;
|
||||
|
||||
@Before
|
||||
public void startHazelcast()
|
||||
throws Exception
|
||||
{
|
||||
Config config = new Config().addMapConfig( new MapConfig().setName( MAP_NAME ) ) //
|
||||
.setInstanceName( Long.toString( System.currentTimeMillis() ) );
|
||||
// start Hazelcast instance
|
||||
hazelcastInstance = Hazelcast.getOrCreateHazelcastInstance( config );
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopHazelcast()
|
||||
throws Exception
|
||||
{
|
||||
hazelcastInstance.shutdown();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
HazelcastSessionDataStoreFactory factory = new HazelcastSessionDataStoreFactory();
|
||||
factory.setOnlyClient( true );
|
||||
factory.setMapName( MAP_NAME );
|
||||
return factory;
|
||||
}
|
||||
}
|
|
@ -27,6 +27,7 @@ import com.hazelcast.core.HazelcastInstance;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.hazelcast.session.HazelcastSessionDataStoreFactory;
|
||||
import org.eclipse.jetty.hazelcast.session.HazelcastTestHelper;
|
||||
import org.eclipse.jetty.server.session.AbstractClusteredSessionScavengingTest;
|
||||
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
|
||||
import org.junit.After;
|
||||
|
@ -36,37 +37,23 @@ public class ClientSessionScavengingTest
|
|||
extends AbstractClusteredSessionScavengingTest
|
||||
{
|
||||
|
||||
private static final String MAP_NAME = Long.toString( TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) );
|
||||
HazelcastTestHelper _testHelper;
|
||||
|
||||
private HazelcastInstance hazelcastInstance;
|
||||
|
||||
@Before
|
||||
public void startHazelcast()
|
||||
throws Exception
|
||||
{
|
||||
Config config = new Config().addMapConfig( new MapConfig().setName( MAP_NAME ) ) //
|
||||
.setInstanceName( Long.toString( System.currentTimeMillis() ) );
|
||||
// start Hazelcast instance
|
||||
hazelcastInstance = Hazelcast.getOrCreateHazelcastInstance( config );
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopHazelcast()
|
||||
throws Exception
|
||||
{
|
||||
hazelcastInstance.shutdown();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
HazelcastSessionDataStoreFactory factory = new HazelcastSessionDataStoreFactory();
|
||||
factory.setOnlyClient( true );
|
||||
factory.setMapName( MAP_NAME );
|
||||
return factory;
|
||||
return _testHelper.createSessionDataStoreFactory(true);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
_testHelper = new HazelcastTestHelper();
|
||||
}
|
||||
|
||||
@After
|
||||
public void shutdown()
|
||||
{
|
||||
_testHelper.tearDown();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.session.infinispan.InfinispanSessionDataStoreFactory;
|
||||
import org.eclipse.jetty.toolchain.test.JDK;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
public class ClusteredLastAccessTimeTest extends AbstractClusteredLastAccessTimeTest
|
||||
{
|
||||
public static InfinispanTestSupport __testSupport;
|
||||
|
||||
@BeforeClass
|
||||
public static void setup () throws Exception
|
||||
{
|
||||
__testSupport = new InfinispanTestSupport();
|
||||
__testSupport.setUseFileStore(true);
|
||||
__testSupport.setup();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void teardown () throws Exception
|
||||
{
|
||||
if (__testSupport != null)
|
||||
__testSupport.teardown();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void testLastAccessTime() throws Exception
|
||||
{
|
||||
super.testLastAccessTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
InfinispanSessionDataStoreFactory factory = new InfinispanSessionDataStoreFactory();
|
||||
factory.setCache(__testSupport.getCache());
|
||||
return factory;
|
||||
}
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.session.infinispan.InfinispanSessionDataStoreFactory;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
/**
|
||||
* ClusteredSessionMigrationTest
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ClusteredSessionMigrationTest extends AbstractClusteredSessionMigrationTest
|
||||
{
|
||||
|
||||
public static InfinispanTestSupport __testSupport;
|
||||
|
||||
|
||||
@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.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
InfinispanSessionDataStoreFactory factory = new InfinispanSessionDataStoreFactory();
|
||||
factory.setCache(__testSupport.getCache());
|
||||
return factory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testSessionMigration() throws Exception
|
||||
{
|
||||
super.testSessionMigration();
|
||||
}
|
||||
|
||||
}
|
|
@ -20,7 +20,6 @@
|
|||
package org.eclipse.jetty.server.session;
|
||||
|
||||
import org.eclipse.jetty.session.infinispan.InfinispanSessionDataStoreFactory;
|
||||
import org.eclipse.jetty.toolchain.test.JDK;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.fail;
|
||||
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.session.infinispan.InfinispanSessionDataStore;
|
||||
import org.eclipse.jetty.session.infinispan.InfinispanSessionDataStoreFactory;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
/**
|
||||
* InfinispanSessionDataStoreTest
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class InfinispanSessionDataStoreTest extends AbstractSessionDataStoreTest
|
||||
{
|
||||
|
||||
public InfinispanTestSupport __testSupport;
|
||||
|
||||
@Before
|
||||
public void setup () throws Exception
|
||||
{
|
||||
__testSupport = new InfinispanTestSupport();
|
||||
__testSupport.setup();
|
||||
}
|
||||
|
||||
@After
|
||||
public void teardown () throws Exception
|
||||
{
|
||||
__testSupport.teardown();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
InfinispanSessionDataStoreFactory factory = new InfinispanSessionDataStoreFactory();
|
||||
factory.setCache(__testSupport.getCache());
|
||||
return factory;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void persistSession(SessionData data) throws Exception
|
||||
{
|
||||
__testSupport.createSession(data);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void persistUnreadableSession(SessionData data) throws Exception
|
||||
{
|
||||
//Not used by testLoadSessionFails()
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean checkSessionExists(SessionData data) throws Exception
|
||||
{
|
||||
return __testSupport.checkSessionExists(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* This test deliberately sets the infinispan cache to null to
|
||||
* try and provoke an exception in the InfinispanSessionDataStore.load() method.
|
||||
*/
|
||||
@Override
|
||||
public void testLoadSessionFails() throws Exception
|
||||
{
|
||||
//create the SessionDataStore
|
||||
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
||||
context.setContextPath("/test");
|
||||
SessionDataStoreFactory factory = createSessionDataStoreFactory();
|
||||
((AbstractSessionDataStoreFactory)factory).setGracePeriodSec(GRACE_PERIOD_SEC);
|
||||
SessionDataStore store = factory.getSessionDataStore(context.getSessionHandler());
|
||||
SessionContext sessionContext = new SessionContext("foo", context.getServletContext());
|
||||
store.initialize(sessionContext);
|
||||
|
||||
|
||||
//persist a session
|
||||
long now = System.currentTimeMillis();
|
||||
SessionData data = store.newSessionData("222", 100, now, now-1, -1);
|
||||
data.setLastNode(sessionContext.getWorkerName());
|
||||
persistSession(data);
|
||||
|
||||
store.start();
|
||||
|
||||
((InfinispanSessionDataStore)store).setCache(null);
|
||||
|
||||
|
||||
//test that loading it fails
|
||||
try
|
||||
{
|
||||
store.load("222");
|
||||
fail("Session should be unreadable");
|
||||
}
|
||||
catch (UnreadableSessionDataException e)
|
||||
{
|
||||
//expected exception
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This test currently won't work for Infinispan - there is currently no
|
||||
* means to query it to find sessions that have expired.
|
||||
*
|
||||
* @see org.eclipse.jetty.server.session.AbstractSessionDataStoreTest#testGetExpiredPersistedAndExpiredOnly()
|
||||
*/
|
||||
@Override
|
||||
public void testGetExpiredPersistedAndExpiredOnly() throws Exception
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This test won't work for Infinispan - there is currently no
|
||||
* means to query infinispan to find other expired sessions.
|
||||
*/
|
||||
@Override
|
||||
public void testGetExpiredDifferentNode() throws Exception
|
||||
{
|
||||
//Ignore
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public boolean checkSessionPersisted(SessionData data) throws Exception
|
||||
{
|
||||
return __testSupport.checkSessionPersisted(data);
|
||||
}
|
||||
|
||||
}
|
|
@ -19,6 +19,9 @@
|
|||
|
||||
package org.eclipse.jetty.server.session;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.eclipse.jetty.util.IO;
|
||||
|
@ -104,6 +107,7 @@ public class InfinispanTestSupport
|
|||
|
||||
public void teardown () throws Exception
|
||||
{
|
||||
_cache.clear();
|
||||
_manager.removeCache(_name);
|
||||
if (_useFileStore)
|
||||
{
|
||||
|
@ -113,4 +117,62 @@ public class InfinispanTestSupport
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void createSession (SessionData data)
|
||||
throws Exception
|
||||
{
|
||||
_cache.put(data.getContextPath()+"_"+data.getVhost()+"_"+data.getId(), data);
|
||||
}
|
||||
|
||||
|
||||
public void createUnreadableSession (SessionData data)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
public boolean checkSessionExists (SessionData data)
|
||||
throws Exception
|
||||
{
|
||||
return (_cache.get(data.getContextPath()+"_"+data.getVhost()+"_"+data.getId()) != null);
|
||||
}
|
||||
|
||||
|
||||
public boolean checkSessionPersisted (SessionData data)
|
||||
throws Exception
|
||||
{
|
||||
Object obj = _cache.get(data.getContextPath()+"_"+data.getVhost()+"_"+data.getId());
|
||||
if (obj == null)
|
||||
return false;
|
||||
|
||||
SessionData saved = (SessionData)obj;
|
||||
|
||||
|
||||
//turn an Entity into a Session
|
||||
assertEquals(data.getId(), saved.getId());
|
||||
assertEquals(data.getContextPath(), saved.getContextPath());
|
||||
assertEquals(data.getVhost(), saved.getVhost());
|
||||
assertEquals(data.getAccessed(), saved.getAccessed());
|
||||
assertEquals(data.getLastAccessed(), saved.getLastAccessed());
|
||||
assertEquals(data.getCreated(), saved.getCreated());
|
||||
assertEquals(data.getCookieSet(), saved.getCookieSet());
|
||||
assertEquals(data.getLastNode(), saved.getLastNode());
|
||||
//don't test lastSaved, because that is set only on the SessionData after it returns from SessionDataStore.save()
|
||||
assertEquals(data.getExpiry(), saved.getExpiry());
|
||||
assertEquals(data.getMaxInactiveMs(), saved.getMaxInactiveMs());
|
||||
|
||||
//same number of attributes
|
||||
assertEquals(data.getAllAttributes().size(), saved.getAllAttributes().size());
|
||||
//same keys
|
||||
assertTrue(data.getKeys().equals(saved.getKeys()));
|
||||
//same values
|
||||
for (String name:data.getKeys())
|
||||
{
|
||||
assertTrue(data.getAttribute(name).equals(saved.getAttribute(name)));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.session.infinispan.InfinispanSessionDataStoreFactory;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
/**
|
||||
* ModifyMaxInactiveIntervalTest
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ModifyMaxInactiveIntervalTest extends AbstractModifyMaxInactiveIntervalTest
|
||||
{
|
||||
public static InfinispanTestSupport __testSupport;
|
||||
|
||||
|
||||
@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.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
InfinispanSessionDataStoreFactory factory = new InfinispanSessionDataStoreFactory();
|
||||
factory.setCache(__testSupport.getCache());
|
||||
return factory;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.fail;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
|
||||
|
||||
import org.eclipse.jetty.session.infinispan.InfinispanSessionDataStoreFactory;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
/**
|
||||
* NonClusteredSessionScavengingTest
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class NonClusteredSessionScavengingTest extends AbstractNonClusteredSessionScavengingTest
|
||||
{
|
||||
|
||||
public static InfinispanTestSupport __testSupport;
|
||||
|
||||
|
||||
@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.AbstractNonClusteredSessionScavengingTest#assertSession(java.lang.String, boolean)
|
||||
*/
|
||||
@Override
|
||||
public void assertSession(String id, boolean exists)
|
||||
{
|
||||
assertNotNull(_dataStore);
|
||||
|
||||
try
|
||||
{
|
||||
boolean inmap = _dataStore.exists(id);
|
||||
if (exists)
|
||||
assertTrue(inmap);
|
||||
else
|
||||
assertFalse(inmap);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
InfinispanSessionDataStoreFactory factory = new InfinispanSessionDataStoreFactory();
|
||||
factory.setCache(__testSupport.getCache());
|
||||
return factory;
|
||||
}
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.session.infinispan.InfinispanSessionDataStoreFactory;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SessionExpiryTest extends AbstractSessionExpiryTest
|
||||
{
|
||||
|
||||
public static InfinispanTestSupport __testSupport;
|
||||
|
||||
@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.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
InfinispanSessionDataStoreFactory factory = new InfinispanSessionDataStoreFactory();
|
||||
factory.setCache(__testSupport.getCache());
|
||||
return factory;
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testSessionNotExpired() throws Exception
|
||||
{
|
||||
super.testSessionNotExpired();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testSessionExpiry() throws Exception
|
||||
{
|
||||
super.testSessionExpiry();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void verifySessionDestroyed (TestHttpSessionListener listener, String sessionId)
|
||||
{
|
||||
//noop - sessions that expired when the InfinispanSessionManager was not running are not reloaded and do not have their listeners called on them.
|
||||
}
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2018 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.session.infinispan.InfinispanSessionDataStoreFactory;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
/**
|
||||
* SessionInvalidateCreateScavengeTest
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class SessionInvalidateCreateScavengeTest extends AbstractSessionInvalidateCreateScavengeTest
|
||||
{
|
||||
public static InfinispanTestSupport __testSupport;
|
||||
|
||||
|
||||
@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.AbstractTestBase#createSessionDataStoreFactory()
|
||||
*/
|
||||
@Override
|
||||
public SessionDataStoreFactory createSessionDataStoreFactory()
|
||||
{
|
||||
InfinispanSessionDataStoreFactory factory = new InfinispanSessionDataStoreFactory();
|
||||
factory.setCache(__testSupport.getCache());
|
||||
return factory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testSessionScavenge() throws Exception
|
||||
{
|
||||
super.testSessionScavenge();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue