Merge remote-tracking branch 'eclipse/jetty-9.4.x' into jetty-9.4.x-1027-Multipart

This commit is contained in:
Lachlan Roberts 2018-04-03 12:36:54 +10:00
commit be2d6ebb29
164 changed files with 5727 additions and 6300 deletions

2
Jenkinsfile vendored
View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}
----

View File

@ -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();
}

View File

@ -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 )

View File

@ -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();

View File

@ -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 ---------------&gt; REMOTELY_CLOSED
* | |
* gen| |gen
* hc| |hc
* | |
* v rcv hc v
* LOCALLY_CLOSING --------------&gt; CLOSING
* | |
* snd| |gen
* hc| |hc
* | |
* v rcv hc v
* LOCALLY_CLOSED ----------------&gt; 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
}
}

View File

@ -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();
}

View File

@ -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

View File

@ -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>

View File

@ -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());
}
}

View File

@ -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);
}
});

View File

@ -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);
}

View File

@ -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()
{

View File

@ -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)

View File

@ -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>

View File

@ -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>

View File

@ -0,0 +1,2 @@
invoker.goals = verify -V
#test-compile failsafe:integration-test

View File

@ -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>

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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;
}
}

View File

@ -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>

View File

@ -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;
}
}
/**

View File

@ -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

View File

@ -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.

View File

@ -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");
}
/**
*

View File

@ -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()
*/

View File

@ -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
{

View File

@ -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)

View File

@ -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()
*/

View File

@ -149,4 +149,6 @@ public class MongoSessionDataStoreFactory extends AbstractSessionDataStoreFactor
return store;
}
}

View File

@ -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]);
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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())

View File

@ -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);
}
}

View File

@ -372,9 +372,7 @@ public class SessionData implements Serializable
return (getExpiry() <= time);
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{

View File

@ -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;

View File

@ -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;

View File

@ -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();
}
}
}

View File

@ -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());
}
}

View File

@ -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>

View File

@ -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;
}
}

View File

@ -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));
}

View File

@ -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
View File

@ -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>

View File

@ -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>

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -48,12 +48,5 @@ public class ClusteredSessionScavengingTest extends AbstractClusteredSessionScav
return GCloudSessionTestSupport.newSessionDataStoreFactory(GCloudTestSuite.__testSupport.getDatastore());
}
@Test
@Override
public void testLocalSessionsScavenging() throws Exception
{
super.testLocalSessionsScavenging();
}
}

View File

@ -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);
}
}

View File

@ -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
{

View File

@ -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
})

View File

@ -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());
}
}

View File

@ -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());}
}
}

View File

@ -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();
}
}

View File

@ -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>

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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.
}
}

View File

@ -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