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

This commit is contained in:
Jan Bartel 2018-03-29 17:36:29 +11:00
commit 67d887758d
159 changed files with 5636 additions and 6269 deletions

2
Jenkinsfile vendored
View File

@ -89,7 +89,7 @@ def getFullBuild(jdk, os) {
globalMavenSettingsConfig: 'oss-settings.xml', globalMavenSettingsConfig: 'oss-settings.xml',
mavenLocalRepo: "${env.JENKINS_HOME}/${env.EXECUTOR_NUMBER}") { 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.. // withMaven doesn't label..
// Report failures in the jenkins UI // Report failures in the jenkins UI

View File

@ -127,7 +127,7 @@ public abstract class AbstractConnectionPool implements ConnectionPool, Dumpable
{ {
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("Connection {}/{} creation succeeded {}", total+1, maxConnections, connection); LOG.debug("Connection {}/{} creation succeeded {}", total+1, maxConnections, connection);
connections.update(-1,0); connections.add(-1,0);
onCreated(connection); onCreated(connection);
proceed(); proceed();
} }
@ -137,7 +137,7 @@ public abstract class AbstractConnectionPool implements ConnectionPool, Dumpable
{ {
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("Connection " + (total+1) + "/" + maxConnections + " creation failed", x); LOG.debug("Connection " + (total+1) + "/" + maxConnections + " creation failed", x);
connections.update(-1,-1); connections.add(-1,-1);
requester.failed(x); requester.failed(x);
} }
}); });
@ -190,7 +190,7 @@ public abstract class AbstractConnectionPool implements ConnectionPool, Dumpable
protected void removed(Connection connection) protected void removed(Connection connection)
{ {
int pooled = connections.updateLo(-1); int pooled = connections.addAndGetLo(-1);
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("Connection removed {} - pooled: {}", connection, pooled); 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. 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.] 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.] 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.] 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 ==== Example Code

View File

@ -510,16 +510,22 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
{ {
if (LOG.isDebugEnabled()) LOG.debug("Loading session {} from DataStore", id); if (LOG.isDebugEnabled()) LOG.debug("Loading session {} from DataStore", id);
Entity entity = _datastore.get(makeKey(id, _context)); try
if (entity == null)
{ {
if (LOG.isDebugEnabled()) LOG.debug("No session {} in DataStore ", id); Entity entity = _datastore.get(makeKey(id, _context));
return null; 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); throw new UnreadableSessionDataException(id, _context, e);
return data;
} }
} }
@ -706,7 +712,10 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
Query<ProjectionEntity> query = Query.newProjectionEntityQueryBuilder() Query<ProjectionEntity> query = Query.newProjectionEntityQueryBuilder()
.setKind(_model.getKind()) .setKind(_model.getKind())
.setProjection(_model.getExpiry()) .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(); .build();
QueryResults<ProjectionEntity> presults; QueryResults<ProjectionEntity> presults;
@ -731,7 +740,10 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
{ {
Query<Entity> query = Query.newEntityQueryBuilder() Query<Entity> query = Query.newEntityQueryBuilder()
.setKind(_model.getKind()) .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(); .build();
QueryResults<Entity> results; QueryResults<Entity> results;
@ -912,8 +924,8 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
if (entity == null) if (entity == null)
return null; return null;
final AtomicReference<SessionData> reference = new AtomicReference<SessionData>(); final AtomicReference<SessionData> reference = new AtomicReference<>();
final AtomicReference<Exception> exception = new AtomicReference<Exception>(); final AtomicReference<Exception> exception = new AtomicReference<>();
Runnable load = new Runnable() Runnable load = new Runnable()
{ {
@Override @Override
@ -975,7 +987,9 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
_context.run(load); _context.run(load);
if (exception.get() != null) if (exception.get() != null)
{
throw exception.get(); throw exception.get();
}
return reference.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.SessionContext;
import org.eclipse.jetty.server.session.SessionData; import org.eclipse.jetty.server.session.SessionData;
import org.eclipse.jetty.server.session.SessionDataStore; 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.annotation.ManagedObject;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
@ -55,23 +56,22 @@ public class HazelcastSessionDataStore
throws Exception throws Exception
{ {
final AtomicReference<SessionData> reference = new AtomicReference<SessionData>(); final AtomicReference<SessionData> reference = new AtomicReference<>();
final AtomicReference<Exception> exception = new AtomicReference<Exception>(); final AtomicReference<Exception> exception = new AtomicReference<>();
//ensure the load runs in the context classloader scope //ensure the load runs in the context classloader scope
_context.run( () -> { _context.run( () -> {
try try
{ {
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
{
LOG.debug( "Loading session {} from hazelcast", id ); LOG.debug( "Loading session {} from hazelcast", id );
}
SessionData sd = sessionDataMap.get( getCacheKey( id ) ); SessionData sd = sessionDataMap.get( getCacheKey( id ) );
reference.set(sd); reference.set(sd);
} }
catch (Exception e) catch (Exception e)
{ {
exception.set(e); exception.set(new UnreadableSessionDataException(id, _context, e));
} }
} ); } );
@ -126,12 +126,13 @@ public class HazelcastSessionDataStore
{ {
return Collections.emptySet(); return Collections.emptySet();
} }
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
return candidates.stream().filter( candidate -> { return candidates.stream().filter( candidate -> {
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
{
LOG.debug( "Checking expiry for candidate {}", candidate ); LOG.debug( "Checking expiry for candidate {}", candidate );
}
try try
{ {
SessionData sd = load(candidate); SessionData sd = load(candidate);
@ -193,9 +194,17 @@ public class HazelcastSessionDataStore
@Override @Override
public boolean exists( String id ) 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 ) public String getCacheKey( String id )

View File

@ -18,7 +18,56 @@
package org.eclipse.jetty.http2; 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 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.http2.parser.Parser;
import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.AtomicBiInteger;
import org.eclipse.jetty.util.Atomics; import org.eclipse.jetty.util.Atomics;
import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.CountingCallback; 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 streamIds = new AtomicInteger();
private final AtomicInteger lastStreamId = new AtomicInteger(); private final AtomicInteger lastStreamId = new AtomicInteger();
private final AtomicInteger localStreamCount = 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 sendWindow = new AtomicInteger();
private final AtomicInteger recvWindow = new AtomicInteger(); private final AtomicInteger recvWindow = new AtomicInteger();
private final AtomicReference<CloseState> closed = new AtomicReference<>(CloseState.NOT_CLOSED); 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. // SPEC: exceeding max concurrent streams is treated as stream error.
while (true) while (true)
{ {
int remoteCount = remoteStreamCount.get(); long encoded = remoteStreamCount.get();
int remoteCount = AtomicBiInteger.getHi(encoded);
int remoteClosing = AtomicBiInteger.getLo(encoded);
int maxCount = getMaxRemoteStreams(); 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); reset(new ResetFrame(streamId, ErrorCode.REFUSED_STREAM_ERROR.code), Callback.NOOP);
return null; return null;
} }
if (remoteStreamCount.compareAndSet(remoteCount, remoteCount + 1)) if (remoteStreamCount.compareAndSet(encoded, remoteCount + 1, remoteClosing))
break; 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) protected IStream newStream(int streamId, boolean local)
{ {
return new HTTP2Stream(scheduler, this, streamId, 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()); IStream removed = streams.remove(stream.getId());
if (removed != null) if (removed != null)
{ {
boolean local = stream.isLocal();
if (local)
localStreamCount.decrementAndGet();
else
remoteStreamCount.decrementAndGet();
onStreamClosed(stream); onStreamClosed(stream);
flowControl.onStreamDestroyed(stream); flowControl.onStreamDestroyed(stream);
if (LOG.isDebugEnabled()) 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); bytes = frameBytes = generator.control(lease, frame);
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("Generated {}", frame); LOG.debug("Generated {}", frame);
prepare(); beforeSend();
return true; 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 * sender, the action may have not been performed yet, causing the larger
* data to be rejected, when it should have been accepted.</p> * data to be rejected, when it should have been accepted.</p>
*/ */
private void prepare() private void beforeSend()
{ {
switch (frame.getType()) switch (frame.getType())
{ {
case HEADERS:
{
HeadersFrame headersFrame = (HeadersFrame)frame;
stream.updateClose(headersFrame.isEndStream(), CloseState.Event.BEFORE_SEND);
break;
}
case SETTINGS: case SETTINGS:
{ {
SettingsFrame settingsFrame = (SettingsFrame)frame; SettingsFrame settingsFrame = (SettingsFrame)frame;
@ -1213,7 +1222,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
{ {
onStreamOpened(stream); onStreamOpened(stream);
HeadersFrame headersFrame = (HeadersFrame)frame; HeadersFrame headersFrame = (HeadersFrame)frame;
if (stream.updateClose(headersFrame.isEndStream(), true)) if (stream.updateClose(headersFrame.isEndStream(), CloseState.Event.AFTER_SEND))
removeStream(stream); removeStream(stream);
break; break;
} }
@ -1230,7 +1239,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
{ {
// Pushed streams are implicitly remotely closed. // Pushed streams are implicitly remotely closed.
// They are closed when sending an end-stream DATA frame. // They are closed when sending an end-stream DATA frame.
stream.updateClose(true, false); stream.updateClose(true, CloseState.Event.RECEIVED);
break; break;
} }
case GO_AWAY: case GO_AWAY:
@ -1317,15 +1326,17 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
int length = Math.min(dataBytes, window); int length = Math.min(dataBytes, window);
// Only one DATA frame is generated. // 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; int written = bytes - Frame.HEADER_LENGTH;
if (LOG.isDebugEnabled()) 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.dataWritten = written;
this.dataBytes -= written; this.dataBytes -= written;
flowControl.onDataSending(stream, written); flowControl.onDataSending(stream, written);
stream.updateClose(dataFrame.isEndStream(), CloseState.Event.BEFORE_SEND);
return true; return true;
} }
@ -1342,7 +1353,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
{ {
// Only now we can update the close state // Only now we can update the close state
// and eventually remove the stream. // and eventually remove the stream.
if (stream.updateClose(dataFrame.isEndStream(), true)) if (stream.updateClose(dataFrame.isEndStream(), CloseState.Event.AFTER_SEND))
removeStream(stream); removeStream(stream);
super.succeeded(); super.succeeded();
} }

View File

@ -264,7 +264,7 @@ public class HTTP2Stream extends IdleTimeout implements IStream, Callback, Dumpa
private void onHeaders(HeadersFrame frame, Callback callback) private void onHeaders(HeadersFrame frame, Callback callback)
{ {
if (updateClose(frame.isEndStream(), false)) if (updateClose(frame.isEndStream(), CloseState.Event.RECEIVED))
session.removeStream(this); session.removeStream(this);
callback.succeeded(); callback.succeeded();
} }
@ -295,7 +295,7 @@ public class HTTP2Stream extends IdleTimeout implements IStream, Callback, Dumpa
return; return;
} }
if (updateClose(frame.isEndStream(), false)) if (updateClose(frame.isEndStream(), CloseState.Event.RECEIVED))
session.removeStream(this); session.removeStream(this);
notifyData(this, frame, callback); notifyData(this, frame, callback);
} }
@ -312,7 +312,7 @@ public class HTTP2Stream extends IdleTimeout implements IStream, Callback, Dumpa
{ {
// Pushed streams are implicitly locally closed. // Pushed streams are implicitly locally closed.
// They are closed when receiving an end-stream DATA frame. // They are closed when receiving an end-stream DATA frame.
updateClose(true, true); updateClose(true, CloseState.Event.AFTER_SEND);
callback.succeeded(); callback.succeeded();
} }
@ -322,14 +322,29 @@ public class HTTP2Stream extends IdleTimeout implements IStream, Callback, Dumpa
} }
@Override @Override
public boolean updateClose(boolean update, boolean local) public boolean updateClose(boolean update, CloseState.Event event)
{ {
if (LOG.isDebugEnabled()) 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) if (!update)
return false; 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) while (true)
{ {
CloseState current = closeState.get(); CloseState current = closeState.get();
@ -337,22 +352,79 @@ public class HTTP2Stream extends IdleTimeout implements IStream, Callback, Dumpa
{ {
case NOT_CLOSED: case NOT_CLOSED:
{ {
CloseState newValue = local ? CloseState.LOCALLY_CLOSED : CloseState.REMOTELY_CLOSED; if (closeState.compareAndSet(current, CloseState.REMOTELY_CLOSED))
if (closeState.compareAndSet(current, newValue))
return false; return false;
break; break;
} }
case LOCALLY_CLOSING:
{
if (closeState.compareAndSet(current, CloseState.CLOSING))
{
updateStreamCount(0, 1);
return false;
}
break;
}
case LOCALLY_CLOSED: case LOCALLY_CLOSED:
{ {
if (local)
return false;
close(); close();
return true; 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: case REMOTELY_CLOSED:
{ {
if (!local) if (closeState.compareAndSet(current, CloseState.CLOSING))
{
updateStreamCount(0, 1);
return false; 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(); close();
return true; return true;
} }
@ -389,8 +461,18 @@ public class HTTP2Stream extends IdleTimeout implements IStream, Callback, Dumpa
@Override @Override
public void close() 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(); onClose();
}
}
private void updateStreamCount(int deltaStream, int deltaClosing)
{
((HTTP2Session)session).updateStreamCount(isLocal(), deltaStream, deltaClosing);
} }
@Override @Override

View File

@ -76,12 +76,10 @@ public interface IStream extends Stream, Closeable
* <p>Updates the close state of this stream.</p> * <p>Updates the close state of this stream.</p>
* *
* @param update whether to update the close state * @param update whether to update the close state
* @param local whether the update comes from a local operation * @param event the event that caused the close state update
* (such as sending a frame that ends the stream)
* or a remote operation (such as receiving a frame
* @return whether the stream has been fully closed by this invocation * @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> * <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 javax.servlet.ServletException;
import org.eclipse.jetty.server.session.SessionDataStoreFactory; import javax.servlet.http.HttpServletRequest;
import org.junit.After; import javax.servlet.http.HttpServletResponse;
/** import org.eclipse.jetty.server.Request;
* ModifyMaxInactiveIntervalTest import org.eclipse.jetty.server.handler.AbstractHandler;
*
* public class EmptyServerHandler extends AbstractHandler.ErrorDispatchHandler
*/
public class ModifyMaxInactiveIntervalTest extends AbstractModifyMaxInactiveIntervalTest
{ {
@After
public void teardown () throws Exception
{
GCloudTestSuite.__testSupport.deleteSessions();
}
/**
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
*/
@Override @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; package org.eclipse.jetty.http2.client.http;
import java.io.IOException;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; 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.Handler;
import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
@ -53,12 +51,11 @@ public class MaxConcurrentStreamsTest extends AbstractTest
public void testOneConcurrentStream() throws Exception public void testOneConcurrentStream() throws Exception
{ {
long sleep = 1000; long sleep = 1000;
start(1, new AbstractHandler() start(1, new EmptyServerHandler()
{ {
@Override @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 a bit to allow the second request to be queued.
sleep(sleep); sleep(sleep);
} }
@ -91,17 +88,42 @@ public class MaxConcurrentStreamsTest extends AbstractTest
Assert.assertTrue(latch.await(5 * sleep, TimeUnit.MILLISECONDS)); 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 @Test
public void testTwoConcurrentStreamsThirdWaits() throws Exception public void testTwoConcurrentStreamsThirdWaits() throws Exception
{ {
int maxStreams = 2; int maxStreams = 2;
long sleep = 1000; long sleep = 1000;
start(maxStreams, new AbstractHandler() start(maxStreams, new EmptyServerHandler()
{ {
@Override @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); sleep(sleep);
} }
}); });
@ -140,12 +162,11 @@ public class MaxConcurrentStreamsTest extends AbstractTest
public void testAbortedWhileQueued() throws Exception public void testAbortedWhileQueued() throws Exception
{ {
long sleep = 1000; long sleep = 1000;
start(1, new AbstractHandler() start(1, new EmptyServerHandler()
{ {
@Override @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); sleep(sleep);
} }
}); });
@ -170,12 +191,11 @@ public class MaxConcurrentStreamsTest extends AbstractTest
{ {
int maxConcurrent = 10; int maxConcurrent = 10;
long sleep = 500; long sleep = 500;
start(maxConcurrent, new AbstractHandler() start(maxConcurrent, new EmptyServerHandler()
{ {
@Override @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); sleep(sleep);
} }
}); });

View File

@ -24,9 +24,9 @@ import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference; 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.AbstractSessionDataStore;
import org.eclipse.jetty.server.session.SessionData; 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.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject; import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
@ -84,8 +84,8 @@ public class InfinispanSessionDataStore extends AbstractSessionDataStore
@Override @Override
public SessionData load(String id) throws Exception public SessionData load(String id) throws Exception
{ {
final AtomicReference<SessionData> reference = new AtomicReference<SessionData>(); final AtomicReference<SessionData> reference = new AtomicReference<>();
final AtomicReference<Exception> exception = new AtomicReference<Exception>(); final AtomicReference<Exception> exception = new AtomicReference<>();
Runnable load = new Runnable() Runnable load = new Runnable()
{ {
@ -103,7 +103,7 @@ public class InfinispanSessionDataStore extends AbstractSessionDataStore
} }
catch (Exception e) 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(); 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 //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) for (String candidate:candidates)
{ {
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
@ -205,8 +204,6 @@ public class InfinispanSessionDataStore extends AbstractSessionDataStore
@Override @Override
public void doStore(String id, SessionData data, long lastSaveTime) throws Exception 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 - //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 //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. //scavenges the session before this timeout occurs, the session will be removed.
@ -218,10 +215,6 @@ public class InfinispanSessionDataStore extends AbstractSessionDataStore
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("Session {} saved to infinispan, expires {} ", id, data.getExpiry()); 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 // TODO find a better way to do this that does not pull into memory the
// whole session object // whole session object
final AtomicReference<Boolean> reference = new AtomicReference<Boolean>(); final AtomicReference<Boolean> reference = new AtomicReference<>();
final AtomicReference<Exception> exception = new AtomicReference<Exception>(); final AtomicReference<Exception> exception = new AtomicReference<>();
Runnable load = new Runnable() Runnable load = new Runnable()
{ {

View File

@ -92,35 +92,6 @@
<artifactId>ant</artifactId> <artifactId>ant</artifactId>
<version>1.8.4</version> <version>1.8.4</version>
</dependency> </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> </dependencies>
<reporting> <reporting>
<plugins> <plugins>

View File

@ -149,24 +149,6 @@
<artifactId>javax.transaction-api</artifactId> <artifactId>javax.transaction-api</artifactId>
<scope>compile</scope> <scope>compile</scope>
</dependency> </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> <dependency>
<groupId>org.eclipse.jetty</groupId> <groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-home</artifactId> <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; package org.eclipse.jetty.its.jetty_run_mojo_it;
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;
/** /**
* ClusteredLastAccessTimeTest *
*/ */
public class ClusteredLastAccessTimeTest extends AbstractClusteredLastAccessTimeTest @WebServlet("/hello")
public class HelloServlet
extends HttpServlet
{ {
/**
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
*/
@Override @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 javax.servlet.ServletException;
import org.junit.Test; 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 @Override
public SessionDataStoreFactory createSessionDataStoreFactory() protected void doGet( HttpServletRequest req, HttpServletResponse resp )
throws ServletException, IOException
{ {
return JdbcTestHelper.newSessionDataStoreFactory(); String who = req.getParameter( "name" );
}
@Test resp.getWriter().write( "pong " + (who == null ? "unknown" : who) );
@Override
public void testSessionScavenge() throws Exception
{
super.testSessionScavenge();
} }
@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.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -288,19 +289,32 @@ public abstract class AbstractJettyMojo extends AbstractMojo
* @parameter default-value="false" * @parameter default-value="false"
*/ */
protected boolean nonBlocking = 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 restartWebApp(boolean reconfigureScanner) throws Exception;
public abstract void checkPomConfiguration() throws MojoExecutionException; 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; nonBlocking = daemon;
super.execute(); 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 @Override

View File

@ -24,6 +24,7 @@ import java.net.URL;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
@ -164,7 +165,6 @@ public class JettyRunMojo extends AbstractJettyMojo
protected Resource originalBaseResource; protected Resource originalBaseResource;
@Parameter(defaultValue = "${reactorProjects}", readonly = true, required = true) @Parameter(defaultValue = "${reactorProjects}", readonly = true, required = true)
private List<MavenProject> reactorProjects; private List<MavenProject> reactorProjects;
@ -178,21 +178,6 @@ public class JettyRunMojo extends AbstractJettyMojo
warPluginInfo = new WarPluginInfo(project); warPluginInfo = new WarPluginInfo(project);
super.execute(); 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. * Verify the configuration given in the pom.

View File

@ -19,6 +19,7 @@
package org.eclipse.jetty.maven.plugin; package org.eclipse.jetty.maven.plugin;
import java.io.File; import java.io.File;
import java.util.Collections;
import java.util.List; import java.util.List;
import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoExecutionException;
@ -57,10 +58,6 @@ public class JettyRunWarExplodedMojo extends AbstractJettyMojo
*/ */
private File war; private File war;
/** /**
* @see org.eclipse.jetty.maven.plugin.AbstractJettyMojo#execute() * @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 server.setStopAtShutdown(true); //as we will normally be stopped with a cntrl-c, ensure server stopped
super.finishConfigurationBeforeStart(); 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; package org.eclipse.jetty.maven.plugin;
import java.io.File; import java.io.File;
import java.util.Collections;
import java.util.List; import java.util.List;
import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoExecutionException;
@ -55,7 +56,6 @@ public class JettyRunWarMojo extends AbstractJettyMojo
*/ */
private File war; private File war;
/** /**
* @see org.apache.maven.plugin.Mojo#execute() * @see org.apache.maven.plugin.Mojo#execute()
*/ */
@ -95,20 +95,6 @@ public class JettyRunWarMojo extends AbstractJettyMojo
return; 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() * @see AbstractJettyMojo#configureScanner()
*/ */

View File

@ -48,15 +48,6 @@ public class JettyStartMojo extends JettyRunMojo
super.execute(); 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 @Override
public void finishConfigurationBeforeStart() throws Exception public void finishConfigurationBeforeStart() throws Exception
{ {

View File

@ -37,12 +37,13 @@ public abstract class NoSqlSessionDataStore extends AbstractSessionDataStore
public class NoSqlSessionData extends SessionData public class NoSqlSessionData extends SessionData
{ {
private Object _version; 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) public NoSqlSessionData(String id, String cpath, String vhost, long created, long accessed, long lastAccessed, long maxInactiveMs)
{ {
super(id, cpath, vhost, created, accessed, lastAccessed, maxInactiveMs); super(id, cpath, vhost, created, accessed, lastAccessed, maxInactiveMs);
setVersion (new Long(0));
} }
public void setVersion (Object v) public void setVersion (Object v)

View File

@ -19,6 +19,20 @@
package org.eclipse.jetty.nosql.mongodb; 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.BasicDBList;
import com.mongodb.BasicDBObject; import com.mongodb.BasicDBObject;
import com.mongodb.BasicDBObjectBuilder; import com.mongodb.BasicDBObjectBuilder;
@ -29,26 +43,6 @@ import com.mongodb.MongoException;
import com.mongodb.WriteConcern; import com.mongodb.WriteConcern;
import com.mongodb.WriteResult; 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 * MongoSessionDataStore
* *
@ -108,12 +102,12 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
/** /**
* Special attribute for a session that is context-specific * 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 * 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 * 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 __ACCESSED = "accessed";
public final static String __LAST_ACCESSED = "lastAccessed";
/** /**
* Time this session will expire, based on last access time and maxIdle * 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 * Time of session creation
*/ */
private final static String __CREATED = "created"; public final static String __CREATED = "created";
/** /**
* Whether or not session is valid * Whether or not session is valid
@ -188,8 +185,8 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
@Override @Override
public SessionData load(String id) throws Exception public SessionData load(String id) throws Exception
{ {
final AtomicReference<SessionData> reference = new AtomicReference<SessionData>(); final AtomicReference<SessionData> reference = new AtomicReference<>();
final AtomicReference<Exception> exception = new AtomicReference<Exception>(); final AtomicReference<Exception> exception = new AtomicReference<>();
Runnable r = new Runnable() Runnable r = new Runnable()
{ {
@Override @Override
@ -212,19 +209,20 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
if (valid == null || !valid) if (valid == null || !valid)
return; return;
Object version = getNestedValue(sessionDocument, getContextSubfield(__VERSION)); Object version = MongoUtils.getNestedValue(sessionDocument, getContextSubfield(__VERSION));
Long lastSaved = (Long)getNestedValue(sessionDocument, getContextSubfield(__LASTSAVED)); Long lastSaved = (Long)MongoUtils.getNestedValue(sessionDocument, getContextSubfield(__LASTSAVED));
String lastNode = (String)getNestedValue(sessionDocument, getContextSubfield(__LASTNODE)); String lastNode = (String)MongoUtils.getNestedValue(sessionDocument, getContextSubfield(__LASTNODE));
Long created = (Long)sessionDocument.get(__CREATED); Long created = (Long)sessionDocument.get(__CREATED);
Long accessed = (Long)sessionDocument.get(__ACCESSED); Long accessed = (Long)sessionDocument.get(__ACCESSED);
Long lastAccessed = (Long)sessionDocument.get(__LAST_ACCESSED);
Long maxInactive = (Long)sessionDocument.get(__MAX_IDLE); Long maxInactive = (Long)sessionDocument.get(__MAX_IDLE);
Long expiry = (Long)sessionDocument.get(__EXPIRY); Long expiry = (Long)sessionDocument.get(__EXPIRY);
NoSqlSessionData data = null; NoSqlSessionData data = null;
// get the session for the context // 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); if (LOG.isDebugEnabled()) LOG.debug("attrs {}", sessionSubDocumentForContext);
@ -234,7 +232,7 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
LOG.debug("Session {} present for context {}", id, _context); LOG.debug("Session {} present for context {}", id, _context);
//only load a session if it exists for this 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.setVersion(version);
data.setExpiry(expiry); data.setExpiry(expiry);
data.setContextPath(_context.getCanonicalContextPath()); 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 //skip special metadata attribute which is not one of the actual session attributes
if ( __METADATA.equals(name) ) if ( __METADATA.equals(name) )
continue; continue;
String attr = decodeName(name); String attr = MongoUtils.decodeName(name);
Object value = decodeValue(sessionSubDocumentForContext.get(name)); Object value = MongoUtils.decodeValue(sessionSubDocumentForContext.get(name));
attributes.put(attr,value); attributes.put(attr,value);
} }
@ -265,7 +263,7 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
} }
catch (Exception e) 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) if (sessionDocument != null)
{ {
DBObject c = (DBObject)getNestedValue(sessionDocument, __CONTEXT); DBObject c = (DBObject)MongoUtils.getNestedValue(sessionDocument, __CONTEXT);
if (c == null) if (c == null)
{ {
//delete whole doc //delete whole doc
@ -326,7 +324,7 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
BasicDBObject unsets = new BasicDBObject(); BasicDBObject unsets = new BasicDBObject();
unsets.put(getContextField(),1); unsets.put(getContextField(),1);
remove.put("$unset",unsets); remove.put("$unset",unsets);
WriteResult result = _dbSessions.update(mongoKey,remove,false,false,WriteConcern.SAFE); _dbSessions.update(mongoKey,remove,false,false,WriteConcern.SAFE);
return true; return true;
} }
else else
@ -347,6 +345,7 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
DBObject fields = new BasicDBObject(); DBObject fields = new BasicDBObject();
fields.put(__EXPIRY, 1); fields.put(__EXPIRY, 1);
fields.put(__VALID, 1); fields.put(__VALID, 1);
fields.put(getContextSubfield(__VERSION), 1);
DBObject sessionDocument = _dbSessions.findOne(new BasicDBObject(__ID, id), fields); DBObject sessionDocument = _dbSessions.findOne(new BasicDBObject(__ID, id), fields);
@ -359,9 +358,16 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
Long expiry = (Long)sessionDocument.get(__EXPIRY); Long expiry = (Long)sessionDocument.get(__EXPIRY);
if (expiry.longValue() <= 0) //expired?
return true; //never expires, its good if (expiry.longValue() > 0 && expiry.longValue() < System.currentTimeMillis())
return (expiry.longValue() > System.currentTimeMillis()); //expires later 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)); if (LOG.isDebugEnabled()) LOG.debug("{} Mongo found old expired session {}", _context, id+" exp="+session.get(__EXPIRY));
expiredSessions.add(id); expiredSessions.add(id);
} }
} }
finally 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; 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) * @see org.eclipse.jetty.server.session.AbstractSessionDataStore#doStore(String, SessionData, long)
*/ */
@Override @Override
public void doStore(String id, SessionData data, long lastSaveTime) throws Exception public void doStore(String id, SessionData data, long lastSaveTime) throws Exception
{ {
NoSqlSessionData nsqd = (NoSqlSessionData)data;
// Form query for upsert // Form query for upsert
BasicDBObject key = new BasicDBObject(__ID, id); BasicDBObject key = new BasicDBObject(__ID, id);
@ -459,21 +492,21 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
{ {
upsert = true; upsert = true;
version = new Long(1); version = new Long(1);
sets.put(__CREATED,nsqd.getCreated()); sets.put(__CREATED,data.getCreated());
sets.put(__VALID,true); sets.put(__VALID,true);
sets.put(getContextSubfield(__VERSION),version); sets.put(getContextSubfield(__VERSION),version);
sets.put(getContextSubfield(__LASTSAVED), data.getLastSaved()); sets.put(getContextSubfield(__LASTSAVED), data.getLastSaved());
sets.put(getContextSubfield(__LASTNODE), data.getLastNode()); sets.put(getContextSubfield(__LASTNODE), data.getLastNode());
sets.put(__MAX_IDLE, nsqd.getMaxInactiveMs()); sets.put(__MAX_IDLE, data.getMaxInactiveMs());
sets.put(__EXPIRY, nsqd.getExpiry()); sets.put(__EXPIRY, data.getExpiry());
nsqd.setVersion(version); ((NoSqlSessionData)data).setVersion(version);
} }
else else
{ {
sets.put(getContextSubfield(__LASTSAVED), data.getLastSaved()); sets.put(getContextSubfield(__LASTSAVED), data.getLastSaved());
sets.put(getContextSubfield(__LASTNODE), data.getLastNode()); sets.put(getContextSubfield(__LASTNODE), data.getLastNode());
version = new Long(((Number)version).longValue() + 1); version = new Long(((Number)version).longValue() + 1);
nsqd.setVersion(version); ((NoSqlSessionData)data).setVersion(version);
update.put("$inc",_version_1); 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 //if max idle time and/or expiry is smaller for this context, then choose that for the whole session doc
BasicDBObject fields = new BasicDBObject(); BasicDBObject fields = new BasicDBObject();
@ -487,23 +520,24 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
tmpLong = (Long)o.get(__EXPIRY); tmpLong = (Long)o.get(__EXPIRY);
long currentExpiry = (tmpLong == null? 0 : tmpLong.longValue()); long currentExpiry = (tmpLong == null? 0 : tmpLong.longValue());
if (currentMaxIdle != nsqd.getMaxInactiveMs()) if (currentMaxIdle != data.getMaxInactiveMs())
sets.put(__MAX_IDLE, nsqd.getMaxInactiveMs()); sets.put(__MAX_IDLE, data.getMaxInactiveMs());
if (currentExpiry != nsqd.getExpiry()) if (currentExpiry != data.getExpiry())
sets.put(__EXPIRY, nsqd.getExpiry()); sets.put(__EXPIRY, data.getExpiry());
} }
else else
LOG.warn("Session {} not found, can't update", id); 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) 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); Object value = data.getAttribute(name);
if (value == null) if (value == null)
unsets.put(getContextField() + "." + encodeName(name),1); unsets.put(getContextField() + "." + MongoUtils.encodeName(name),1);
else else
sets.put(getContextField() + "." + encodeName(name),encodeName(value)); sets.put(getContextField() + "." + MongoUtils.encodeName(name), MongoUtils.encodeName(value));
} }
// Do the upsert // Do the upsert
@ -521,37 +555,16 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
update.put("$set",sets); update.put("$set",sets);
if (!unsets.isEmpty()) if (!unsets.isEmpty())
update.put("$unset",unsets); update.put("$unset",unsets);
WriteResult res = _dbSessions.update(key,update,upsert,false,WriteConcern.SAFE); WriteResult res = _dbSessions.update(key,update,upsert,false,WriteConcern.SAFE);
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("Save:db.sessions.update( {}, {},{} )", key, update, res); 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 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, _dbSessions.createIndex(idKey,
BasicDBObjectBuilder.start() BasicDBObjectBuilder.start()
.add("name", "id_1") .add("name", "id_1")
@ -560,16 +573,19 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
.add("unique", true) .add("unique", true)
.get()); .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() _dbSessions.createIndex(versionKey, BasicDBObjectBuilder.start()
.add("name", "id_1_version_1") .add("name", "id_1_version_1")
.add("ns", _dbSessions.getFullName()) .add("ns", _dbSessions.getFullName())
.add("sparse", false) .add("sparse", false)
.add("unique", true) .add("unique", true)
.get()); .get());
LOG.debug( "done ensure Mongodb indexes existing" );
//TODO perhaps index on expiry time? //TODO perhaps index on expiry time?
} }
/*------------------------------------------------------------ */ /*------------------------------------------------------------ */
private String getContextField () 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() * @see org.eclipse.jetty.server.session.SessionDataStore#isPassivating()
*/ */

View File

@ -149,4 +149,6 @@ public class MongoSessionDataStoreFactory extends AbstractSessionDataStoreFactor
return store; 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 public abstract class NegotiatingServerConnectionFactory extends AbstractConnectionFactory
{ {
private final List<String> negotiatedProtocols; private final List<String> negotiatedProtocols;
private String defaultProtocol; private String defaultProtocol;
@ -47,7 +46,7 @@ public abstract class NegotiatingServerConnectionFactory extends AbstractConnect
{ {
p = p.trim(); p = p.trim();
if (!p.isEmpty()) 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; List<String> negotiated = this.negotiatedProtocols;
if (negotiated.isEmpty()) if (negotiated.isEmpty())
{ {
// Generate list of protocols that we can negotiate // Generate list of protocols that we can negotiate.
negotiated = connector.getProtocols().stream() negotiated = connector.getProtocols().stream()
.filter(p-> .filter(p ->
{ {
ConnectionFactory f=connector.getConnectionFactory(p); ConnectionFactory f = connector.getConnectionFactory(p);
return !(f instanceof SslConnectionFactory)&&!(f instanceof NegotiatingServerConnectionFactory); return !(f instanceof SslConnectionFactory) && !(f instanceof NegotiatingServerConnectionFactory);
}) })
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
// if default protocol is not set, then it is either HTTP/1.1 or // If default protocol is not set, then it is
// the first protocol given // either HTTP/1.1 or the first protocol given.
String dft = defaultProtocol; String dft = defaultProtocol;
if (dft == null && !negotiated.isEmpty()) if (dft == null && !negotiated.isEmpty())
{ {
if (negotiated.contains(HttpVersion.HTTP_1_1.asString())) dft = negotiated.stream()
dft = HttpVersion.HTTP_1_1.asString(); .filter(HttpVersion.HTTP_1_1::is)
else .findFirst()
dft = negotiated.get(0); .orElse(negotiated.get(0));
} }
SSLEngine engine = null; SSLEngine engine = null;

View File

@ -397,6 +397,10 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
super.doStart(); super.doStart();
} }
/**
* @deprecated feature will be removed in Jetty 10.x, with no replacement.
*/
@Deprecated
public int getCompressionLevel() public int getCompressionLevel()
{ {
return _compressionLevel; return _compressionLevel;
@ -753,6 +757,8 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
} }
/** /**
* @deprecated feature will be removed in Jetty 10.x, with no replacement.
@Deprecated
* Set the Compression level that {@link Deflater} uses. * Set the Compression level that {@link Deflater} uses.
* *
* @param compressionLevel The compression level to use to initialize {@link Deflater#setLevel(int)} * @param compressionLevel The compression level to use to initialize {@link Deflater#setLevel(int)}

View File

@ -25,7 +25,6 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.util.annotation.ManagedAttribute; import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject; 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.component.ContainerLifeCycle;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;

View File

@ -44,7 +44,7 @@ public class DefaultSessionCache extends AbstractSessionCache
/** /**
* The cache of sessions in a hashmap * 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(); 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.Handler;
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.SessionIdManager; import org.eclipse.jetty.server.SessionIdManager;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.annotation.ManagedAttribute; import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject; import org.eclipse.jetty.util.annotation.ManagedObject;

View File

@ -30,9 +30,7 @@ import java.io.ObjectOutputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.file.FileVisitOption; import java.nio.file.FileVisitOption;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.attribute.FileTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -264,12 +262,19 @@ public class FileSessionDataStore extends AbstractSessionDataStore
if (p == null) if (p == null)
return; return;
long expiry = getExpiryFromFilename(p.getFileName().toString()); try
//files with 0 expiry never expire
if (expiry >0 && ((now - expiry) >= (5*TimeUnit.SECONDS.toMillis(_gracePeriodSec))))
{ {
Files.deleteIfExists(p); long expiry = getExpiryFromFilename(p.getFileName().toString());
if (LOG.isDebugEnabled()) LOG.debug("Sweep deleted {}", p.getFileName()); //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 (filename == null)
{ {
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("Unknown file {}",filename); LOG.debug("Unknown file {}",idWithContext);
return; return;
} }
File file = new File (_storeDir, filename); File file = new File (_storeDir, filename);
@ -542,7 +547,7 @@ public class FileSessionDataStore extends AbstractSessionDataStore
* @param id identity of session * @param id identity of session
* @return the session id plus context * @return the session id plus context
*/ */
private String getIdWithContext (String id) protected String getIdWithContext (String id)
{ {
return _contextString+"_"+id; return _contextString+"_"+id;
} }
@ -552,13 +557,13 @@ public class FileSessionDataStore extends AbstractSessionDataStore
* @param data * @param data
* @return the session id plus context and expiry * @return the session id plus context and expiry
*/ */
private String getIdWithContextAndExpiry (SessionData data) protected String getIdWithContextAndExpiry (SessionData data)
{ {
return ""+data.getExpiry()+"_"+getIdWithContext(data.getId()); return ""+data.getExpiry()+"_"+getIdWithContext(data.getId());
} }
private String getIdFromFilename (String filename) protected String getIdFromFilename (String filename)
{ {
if (filename == null) if (filename == null)
return 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) if (StringUtil.isBlank(filename) || filename.indexOf("_") < 0)
throw new IllegalStateException ("Invalid or missing filename"); 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)) if (StringUtil.isBlank(filename))
return null; return null;
@ -593,7 +598,7 @@ public class FileSessionDataStore extends AbstractSessionDataStore
* @param filename the name of the file to use * @param filename the name of the file to use
* @return the session id plus context * @return the session id plus context
*/ */
private String getIdWithContextFromFilename (String filename) protected String getIdWithContextFromFilename (String filename)
{ {
if (StringUtil.isBlank(filename) || filename.indexOf('_') < 0) if (StringUtil.isBlank(filename) || filename.indexOf('_') < 0)
return null; return null;
@ -607,7 +612,7 @@ public class FileSessionDataStore extends AbstractSessionDataStore
* @param filename the filename to check * @param filename the filename to check
* @return true if the filename has the correct filename format * @return true if the filename has the correct filename format
*/ */
private boolean isSessionFilename (String filename) protected boolean isSessionFilename (String filename)
{ {
if (StringUtil.isBlank(filename)) if (StringUtil.isBlank(filename))
return false; return false;
@ -626,7 +631,7 @@ public class FileSessionDataStore extends AbstractSessionDataStore
* @param filename the filename to check * @param filename the filename to check
* @return true if the filename has the correct filename format and is for this context * @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)) if (StringUtil.isBlank(filename))
return false; return false;

View File

@ -146,7 +146,7 @@ public class HouseKeeper extends AbstractLifeCycle
_task.cancel(); _task.cancel();
if (_runner == null) if (_runner == null)
_runner = new Runner(); _runner = new Runner();
LOG.info("Scavenging every {}ms", _intervalMs); LOG.info("{} Scavenging every {}ms", _sessionIdManager.getWorkerName(), _intervalMs);
_task = _scheduler.schedule(_runner,_intervalMs,TimeUnit.MILLISECONDS); _task = _scheduler.schedule(_runner,_intervalMs,TimeUnit.MILLISECONDS);
} }
} }
@ -164,7 +164,7 @@ public class HouseKeeper extends AbstractLifeCycle
if (_task!=null) if (_task!=null)
{ {
_task.cancel(); _task.cancel();
LOG.info("Stopped scavenging"); LOG.info("{} Stopped scavenging", _sessionIdManager.getWorkerName());
} }
_task = null; _task = null;
if (_ownScheduler) if (_ownScheduler)
@ -204,13 +204,13 @@ public class HouseKeeper extends AbstractLifeCycle
if (sec <= 0) if (sec <= 0)
{ {
_intervalMs = 0L; _intervalMs = 0L;
LOG.info("Scavenging disabled"); LOG.info("{} Scavenging disabled", _sessionIdManager.getWorkerName());
stopScavenging(); stopScavenging();
} }
else else
{ {
if (sec < 10) 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; _intervalMs=sec*1000L;
@ -261,7 +261,7 @@ public class HouseKeeper extends AbstractLifeCycle
return; return;
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("{} scavenging sessions", this); LOG.debug("{} scavenging sessions", _sessionIdManager.getWorkerName());
//find the session managers //find the session managers
for (SessionHandler manager:_sessionIdManager.getSessionHandlers()) for (SessionHandler manager:_sessionIdManager.getSessionHandlers())

View File

@ -816,7 +816,7 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
public Set<String> doGetExpired(Set<String> candidates) public Set<String> doGetExpired(Set<String> candidates)
{ {
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("Getting expired sessions "+System.currentTimeMillis()); LOG.debug("Getting expired sessions at time {}", System.currentTimeMillis());
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
@ -830,7 +830,7 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
*/ */
long upperBound = now; long upperBound = now;
if (LOG.isDebugEnabled()) 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)) try (PreparedStatement statement = _sessionTableSchema.getExpiredSessionsStatement(connection, _context.getCanonicalContextPath(), _context.getVhost(), upperBound))
{ {
@ -905,7 +905,7 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
} }
catch (Exception e) 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); return (getExpiry() <= time);
} }
/**
* @see java.lang.Object#toString()
*/
@Override @Override
public String toString() public String toString()
{ {

View File

@ -21,8 +21,6 @@ package org.eclipse.jetty.server.session;
import java.util.Set; import java.util.Set;
import org.eclipse.jetty.util.component.LifeCycle;
/** /**
* SessionDataStore * SessionDataStore
* *
@ -68,10 +66,10 @@ public interface SessionDataStore extends SessionDataMap
/** /**
* Test if data exists for a given session id. * 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 * @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; public boolean exists (String id) throws Exception;

View File

@ -222,9 +222,9 @@ public class SessionHandler extends ScopedHandler
protected boolean _secureCookies=false; protected boolean _secureCookies=false;
protected boolean _secureRequestOnly=true; protected boolean _secureRequestOnly=true;
protected final List<HttpSessionAttributeListener> _sessionAttributeListeners = new CopyOnWriteArrayList<HttpSessionAttributeListener>(); protected final List<HttpSessionAttributeListener> _sessionAttributeListeners = new CopyOnWriteArrayList<>();
protected final List<HttpSessionListener> _sessionListeners= new CopyOnWriteArrayList<HttpSessionListener>(); protected final List<HttpSessionListener> _sessionListeners= new CopyOnWriteArrayList<>();
protected final List<HttpSessionIdListener> _sessionIdListeners = new CopyOnWriteArrayList<HttpSessionIdListener>(); protected final List<HttpSessionIdListener> _sessionIdListeners = new CopyOnWriteArrayList<>();
protected ClassLoader _loader; protected ClassLoader _loader;
protected ContextHandler.Context _context; 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); super(manager);
} }
/**
* @see org.eclipse.jetty.server.session.SessionCache#shutdown()
*/
@Override @Override
public void shutdown() public void shutdown()
{ {
// TODO Auto-generated method stub
} }
/**
* @see org.eclipse.jetty.server.session.AbstractSessionCache#newSession(org.eclipse.jetty.server.session.SessionData)
*/
@Override @Override
public Session newSession(SessionData data) public Session newSession(SessionData data)
{ {
// TODO Auto-generated method stub
return null; return null;
} }
/**
* @see org.eclipse.jetty.server.session.AbstractSessionCache#doGet(String)
*/
@Override @Override
public Session doGet(String key) public Session doGet(String key)
{ {
// TODO Auto-generated method stub
return null; return null;
} }
/**
* @see org.eclipse.jetty.server.session.AbstractSessionCache#doPutIfAbsent(String, Session)
*/
@Override @Override
public Session doPutIfAbsent(String key, Session session) public Session doPutIfAbsent(String key, Session session)
{ {
return null; return null;
} }
/**
* @see org.eclipse.jetty.server.session.AbstractSessionCache#doDelete(String)
*/
@Override @Override
public Session doDelete(String key) public Session doDelete(String key)
{ {
return null; 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 @Override
public boolean doReplace(String id, Session oldValue, Session newValue) public boolean doReplace(String id, Session oldValue, Session newValue)
{ {
// TODO Auto-generated method stub
return false; return false;
} }
/**
* @see org.eclipse.jetty.server.session.AbstractSessionCache#newSession(javax.servlet.http.HttpServletRequest, org.eclipse.jetty.server.session.SessionData)
*/
@Override @Override
public Session newSession(HttpServletRequest request, SessionData data) public Session newSession(HttpServletRequest request, SessionData data)
{ {
// TODO Auto-generated method stub
return null; return null;
} }
} }
@ -131,18 +100,12 @@ public class SessionCookieTest
super(server); super(server);
} }
/**
* @see org.eclipse.jetty.server.SessionIdManager#isIdInUse(java.lang.String)
*/
@Override @Override
public boolean isIdInUse(String id) public boolean isIdInUse(String id)
{ {
return false; return false;
} }
/**
* @see org.eclipse.jetty.server.SessionIdManager#expireAll(java.lang.String)
*/
@Override @Override
public void expireAll(String id) 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 is not secure: not on secured requests and request is secure
cookie = mgr.getSessionCookie(session, "/foo", true); cookie = mgr.getSessionCookie(session, "/foo", true);
assertFalse(cookie.isSecure()); assertFalse(cookie.isSecure());
} }
} }

View File

@ -21,13 +21,12 @@ package org.eclipse.jetty.util;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
/** /**
* An AtomicLong with additional methods to treat it has * An AtomicLong with additional methods to treat it as two hi/lo integers.
* two hi/lo integers.
*/ */
public class AtomicBiInteger extends AtomicLong public class AtomicBiInteger extends AtomicLong
{ {
/** /**
* @return the hi integer value * @return the hi value
*/ */
public int getHi() public int getHi()
{ {
@ -35,7 +34,7 @@ public class AtomicBiInteger extends AtomicLong
} }
/** /**
* @return the lo integer value * @return the lo value
*/ */
public int getLo() public int getLo()
{ {
@ -43,12 +42,12 @@ public class AtomicBiInteger extends AtomicLong
} }
/** /**
* Atomically set the hi integer value without changing * Atomically sets the hi value without changing the lo value.
* the lo value. *
* @param hi the new hi 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) while(true)
{ {
@ -60,11 +59,12 @@ public class AtomicBiInteger extends AtomicLong
} }
/** /**
* Atomically set the lo integer value without changing * Atomically sets the lo value without changing the hi value.
* the hi value. *
* @param lo the new lo value * @param lo the new lo value
* @return the previous lo value
*/ */
public int setLo(int lo) public int getAndSetLo(int lo)
{ {
while(true) 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 hi the new hi value
* @param lo the new lo 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 * <p>Atomically sets the hi value to the given updated value
* only if the current value {@code ==} the expected value. * only if the current value {@code ==} the expected value.</p>
* Concurrent changes to the lo value result in a retry. * <p>Concurrent changes to the lo value result in a retry.</p>
* @param expect the expected value *
* @param hi the new value * @param expectHi the expected hi value
* @param hi the new hi value
* @return {@code true} if successful. False return indicates that * @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) while(true)
{ {
long encoded = get(); long encoded = get();
if (getHi(encoded)!=expect) if (getHi(encoded)!=expectHi)
return false; return false;
long update = encodeHi(encoded,hi); long update = encodeHi(encoded,hi);
if (compareAndSet(encoded,update)) if (compareAndSet(encoded,update))
@ -108,20 +110,21 @@ public class AtomicBiInteger extends AtomicLong
} }
/** /**
* Atomically sets the lo int value to the given updated value * <p>Atomically sets the lo value to the given updated value
* only if the current value {@code ==} the expected value. * only if the current value {@code ==} the expected value.</p>
* Concurrent changes to the hi value result in a retry. * <p>Concurrent changes to the hi value result in a retry.</p>
* @param expect the expected value *
* @param lo the new value * @param expectLo the expected lo value
* @param lo the new lo value
* @return {@code true} if successful. False return indicates that * @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) while(true)
{ {
long encoded = get(); long encoded = get();
if (getLo(encoded)!=expect) if (getLo(encoded)!=expectLo)
return false; return false;
long update = encodeLo(encoded,lo); long update = encodeLo(encoded,lo);
if (compareAndSet(encoded,update)) if (compareAndSet(encoded,update))
@ -130,30 +133,31 @@ public class AtomicBiInteger extends AtomicLong
} }
/** /**
* Atomically sets the values to the given updated values * Atomically sets the values to the given updated values only if
* only if the current encoded value {@code ==} the expected value. * the current encoded value {@code ==} the expected encoded value.
* @param expect the expected encoded values *
* @param encoded the expected encoded value
* @param hi the new hi value * @param hi the new hi value
* @param lo the new lo value * @param lo the new lo value
* @return {@code true} if successful. False return indicates that * @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); long update = encode(hi,lo);
return compareAndSet(encoded,update); return compareAndSet(encoded,update);
} }
/** /**
* Atomically sets the values to the given updated values * Atomically sets the hi and lo values to the given updated values only if
* only if the current encoded value {@code ==} the expected value. * the current hi and lo values {@code ==} the expected hi and lo values.
* @param expectHi the expected hi values *
* @param expectHi the expected hi value
* @param hi the new 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 * @param lo the new lo value
* @return {@code true} if successful. False return indicates that * @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) 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 * Atomically adds the given delta to the current hi value, returning the updated hi value.
* applying the given delta, returning the updated value.
* *
* @param delta the delta to apply * @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) while(true)
{ {
@ -182,13 +185,12 @@ public class AtomicBiInteger extends AtomicLong
} }
/** /**
* Atomically updates the current lo value with the results of * Atomically adds the given delta to the current lo value, returning the updated lo value.
* applying the given delta, returning the updated value.
* *
* @param delta the delta to apply * @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) while(true)
{ {
@ -201,13 +203,12 @@ public class AtomicBiInteger extends AtomicLong
} }
/** /**
* Atomically updates the current values with the results of * Atomically adds the given deltas to the current hi and lo values.
* applying the given deltas.
* *
* @param deltaHi the delta to apply to the hi value * @param deltaHi the delta to apply to the hi value
* @param deltaLo the delta to apply to the lo 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) 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 * @param encoded the encoded value
* @return the hi int value * @return the hi value
*/ */
public static int getHi(long encoded) 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 * @param encoded the encoded value
* @return the lo int value * @return the lo value
*/ */
public static int getLo(long encoded) 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 * Encodes hi and lo values into a long.
* @param hi the hi int value *
* @param lo the lo int value * @param hi the hi value
* @param lo the lo value
* @return the encoded value * @return the encoded value
*
*/ */
public static long encode(int hi, int lo) public static long encode(int hi, int lo)
{ {
long h = ((long)hi)&0xFFFF_FFFFl; long h = ((long)hi)&0xFFFF_FFFFL;
long l = ((long)lo)&0xFFFF_FFFFl; long l = ((long)lo)&0xFFFF_FFFFL;
long encoded = (h<<32)+l; return (h<<32)+l;
return encoded;
} }
/** /**
* Encode hi int values into an already encoded long * Sets the hi value into the given encoded value.
*
* @param encoded the encoded value * @param encoded the encoded value
* @param hi the hi int value * @param hi the hi value
* @return the encoded value * @return the new encoded value
*
*/ */
public static long encodeHi(long encoded, int hi) public static long encodeHi(long encoded, int hi)
{ {
long h = ((long)hi)&0xFFFF_FFFFl; long h = ((long)hi)&0xFFFF_FFFFL;
long l = encoded&0xFFFF_FFFFl; long l = encoded&0xFFFF_FFFFL;
encoded = (h<<32)+l; return (h<<32)+l;
return encoded;
} }
/** /**
* Encode lo int values into an already encoded long * Sets the lo value into the given encoded value.
*
* @param encoded the encoded value * @param encoded the encoded value
* @param lo the lo int value * @param lo the lo value
* @return the encoded value * @return the new encoded value
*
*/ */
public static long encodeLo(long encoded, int lo) public static long encodeLo(long encoded, int lo)
{ {
long h = (encoded>>32)&0xFFFF_FFFFl; long h = (encoded>>32)&0xFFFF_FFFFL;
long l = ((long)lo)&0xFFFF_FFFFl; long l = ((long)lo)&0xFFFF_FFFFL;
encoded = (h<<32)+l; return (h<<32)+l;
return encoded;
} }
} }

View File

@ -18,11 +18,13 @@
package org.eclipse.jetty.util; package org.eclipse.jetty.util;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.*;
import org.junit.Test; 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 public class AtomicBiIntegerTest
{ {
@ -75,11 +77,11 @@ public class AtomicBiIntegerTest
assertThat(abi.getHi(),is(0)); assertThat(abi.getHi(),is(0));
assertThat(abi.getLo(),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.getHi(),is(Integer.MAX_VALUE));
assertThat(abi.getLo(),is(0)); assertThat(abi.getLo(),is(0));
abi.setLo(Integer.MIN_VALUE); abi.getAndSetLo(Integer.MIN_VALUE);
assertThat(abi.getHi(),is(Integer.MAX_VALUE)); assertThat(abi.getHi(),is(Integer.MAX_VALUE));
assertThat(abi.getLo(),is(Integer.MIN_VALUE)); assertThat(abi.getLo(),is(Integer.MIN_VALUE));
} }

View File

@ -32,10 +32,8 @@ import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction; import java.security.PrivilegedExceptionAction;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -47,7 +45,6 @@ import java.util.Properties;
import java.util.Queue; import java.util.Queue;
import java.util.ServiceLoader; import java.util.ServiceLoader;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jetty.util.LazyList; import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.Loader; import org.eclipse.jetty.util.Loader;
@ -1516,22 +1513,6 @@ public class XmlConfiguration
{ {
Properties properties = null; Properties properties = null;
// Look for properties from start.jar
try
{
Class<?> config = XmlConfiguration.class.getClassLoader().loadClass("org.eclipse.jetty.start.Config");
properties = (Properties)config.getMethod("getProperties").invoke(null);
LOG.debug("org.eclipse.jetty.start.Config properties = {}",properties);
}
catch (NoClassDefFoundError | ClassNotFoundException e)
{
LOG.ignore(e);
}
catch (Exception e)
{
LOG.warn(e);
}
// If no start.config properties, use clean slate // If no start.config properties, use clean slate
if (properties == null) if (properties == null)
{ {
@ -1571,7 +1552,7 @@ public class XmlConfiguration
} }
configuration.getProperties().putAll(props); configuration.getProperties().putAll(props);
} }
Object obj = configuration.configure(); Object obj = configuration.configure();
if (obj!=null && !objects.contains(obj)) if (obj!=null && !objects.contains(obj))
objects.add(obj); objects.add(obj);
@ -1581,7 +1562,7 @@ public class XmlConfiguration
// For all objects created by XmlConfigurations, start them if they are lifecycles. // For all objects created by XmlConfigurations, start them if they are lifecycles.
for (Object obj : objects) for (Object obj : objects)
{ {
if (obj instanceof LifeCycle) if (obj instanceof LifeCycle)
{ {
LifeCycle lc = (LifeCycle)obj; LifeCycle lc = (LifeCycle)obj;

36
pom.xml
View File

@ -449,7 +449,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-invoker-plugin</artifactId> <artifactId>maven-invoker-plugin</artifactId>
<version>3.0.1</version> <version>3.0.2-SNAPSHOT</version>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
@ -1064,16 +1064,6 @@
<enabled>true</enabled> <enabled>true</enabled>
</snapshots> </snapshots>
</pluginRepository> </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> </pluginRepositories>
</profile> </profile>
<profile> <profile>
@ -1810,6 +1800,30 @@
</repository> </repository>
</repositories> </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> <distributionManagement>
<repository> <repository>

View File

@ -14,7 +14,6 @@
</build> </build>
<modules> <modules>
<module>test-sessions-common</module> <module>test-sessions-common</module>
<module>test-hash-sessions</module>
<module>test-file-sessions</module> <module>test-file-sessions</module>
<module>test-jdbc-sessions</module> <module>test-jdbc-sessions</module>
<module>test-mongodb-sessions</module> <module>test-mongodb-sessions</module>

View File

@ -19,19 +19,16 @@
package org.eclipse.jetty.server.session; package org.eclipse.jetty.server.session;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test;
/** /**
* ProxySerializationTest * FileSessionDataStoreTest
* *
* *
*/ */
public class ProxySerializationTest extends AbstractProxySerializationTest public class FileSessionDataStoreTest extends AbstractSessionDataStoreTest
{ {
@Before @Before
public void before() throws Exception public void before() throws Exception
{ {
@ -43,35 +40,44 @@ public class ProxySerializationTest extends AbstractProxySerializationTest
{ {
FileTestHelper.teardown(); FileTestHelper.teardown();
} }
/**
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
*/
@Override @Override
public SessionDataStoreFactory createSessionDataStoreFactory() public SessionDataStoreFactory createSessionDataStoreFactory()
{ {
return FileTestHelper.newSessionDataStoreFactory(); return FileTestHelper.newSessionDataStoreFactory();
} }
@Test
@Override @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 @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.assertNotNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.ObjectOutputStream;
import java.nio.file.Files; 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; 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) public static void deleteFile (String sessionId)
{ {
assertNotNull(_tmpDir); 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.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException; import org.eclipse.jetty.servlet.ServletContextHandler;
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.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -60,205 +53,396 @@ public class TestFileSessions extends AbstractTestBase
} }
/**
* @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
*/
@Override @Override
public SessionDataStoreFactory createSessionDataStoreFactory() public SessionDataStoreFactory createSessionDataStoreFactory()
{ {
return FileTestHelper.newSessionDataStoreFactory(); 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 @Test
public void testSweep () throws Exception public void testFilenamesWithContext() throws Exception
{ {
int scavengePeriod = 2; //create the SessionDataStore
String contextPath = "/test"; ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
String servletMapping = "/server"; context.setContextPath("/test");
int inactivePeriod = 5; SessionDataStoreFactory factory = createSessionDataStoreFactory();
int gracePeriod = 10; ((AbstractSessionDataStoreFactory)factory).setGracePeriodSec(10);
DefaultSessionCacheFactory cacheFactory = new DefaultSessionCacheFactory(); FileSessionDataStore store = (FileSessionDataStore)factory.getSessionDataStore(context.getSessionHandler());
cacheFactory.setEvictionPolicy(SessionCache.NEVER_EVICT); SessionContext sessionContext = new SessionContext("foo", context.getServletContext());
FileSessionDataStoreFactory storeFactory = (FileSessionDataStoreFactory)createSessionDataStoreFactory(); store.initialize(sessionContext);
storeFactory.setGracePeriodSec(gracePeriod);
TestServer server1 = new TestServer(0, inactivePeriod, scavengePeriod, cacheFactory, storeFactory); String s = store.getIdWithContext("1234");
server1.addContext(contextPath).addServlet(TestServlet.class, servletMapping); 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 try
{ {
server1.start(); long ll = store.getExpiryFromFilename("nonnumber__test_0.0.0.0_1234");
fail ("Should be non numeric");
//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);
} }
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 try
{ {
server1.start(); long ll = store.getExpiryFromFilename(null);
int port1 = server1.getPort(); fail("Should throw ISE");
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();
}
} }
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 //create the SessionDataStore
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 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"); long ll = store.getExpiryFromFilename("nonnumber__0.0.0.0_1234");
if ("init".equals(action)) fail ("Should be non numeric");
{
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();}
}
} }
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()); 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.assertEquals;
import static org.junit.Assert.assertNotNull; 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.ArrayList;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; 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.SessionDataStore;
import org.eclipse.jetty.server.session.SessionHandler; import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.util.ClassLoadingObjectInputStream;
import org.threeten.bp.Duration; 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.Datastore;
import com.google.cloud.datastore.DatastoreOptions; import com.google.cloud.datastore.DatastoreOptions;
import com.google.cloud.datastore.Entity; import com.google.cloud.datastore.Entity;
import com.google.cloud.datastore.GqlQuery; import com.google.cloud.datastore.GqlQuery;
import com.google.cloud.datastore.Key; import com.google.cloud.datastore.Key;
import com.google.cloud.datastore.KeyFactory;
import com.google.cloud.datastore.Query; import com.google.cloud.datastore.Query;
import com.google.cloud.datastore.Query.ResultType; import com.google.cloud.datastore.Query.ResultType;
import com.google.cloud.datastore.QueryResults; import com.google.cloud.datastore.QueryResults;
import com.google.cloud.datastore.StructuredQuery.PropertyFilter;
import com.google.cloud.datastore.testing.LocalDatastoreHelper; import com.google.cloud.datastore.testing.LocalDatastoreHelper;
/** /**
@ -50,6 +62,7 @@ public class GCloudSessionTestSupport
{ {
LocalDatastoreHelper _helper = LocalDatastoreHelper.create(1.0); LocalDatastoreHelper _helper = LocalDatastoreHelper.create(1.0);
Datastore _ds; Datastore _ds;
KeyFactory _keyFactory;
public static class TestGCloudSessionDataStoreFactory extends GCloudSessionDataStoreFactory public static class TestGCloudSessionDataStoreFactory extends GCloudSessionDataStoreFactory
@ -82,6 +95,7 @@ public class GCloudSessionTestSupport
{ {
DatastoreOptions options = _helper.getOptions(); DatastoreOptions options = _helper.getOptions();
_ds = options.getService(); _ds = options.getService();
_keyFactory =_ds.newKeyFactory().setKind(EntityDataModel.KIND);
} }
@ -111,6 +125,103 @@ public class GCloudSessionTestSupport
_helper.reset(); _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 public Set<String> getSessionIds () throws Exception
{ {

View File

@ -31,15 +31,10 @@ import org.junit.runners.Suite;
*/ */
@RunWith(Suite.class) @RunWith(Suite.class)
@Suite.SuiteClasses({ @Suite.SuiteClasses({
GCloudSessionDataStoreTest.class,
InvalidationSessionTest.class, InvalidationSessionTest.class,
ClusteredLastAccessTimeTest.class,
ClusteredSessionScavengingTest.class, ClusteredSessionScavengingTest.class,
NonClusteredSessionScavengingTest.class, ClusteredOrphanedSessionTest.class
ClusteredOrphanedSessionTest.class,
SessionExpiryTest.class,
SessionInvalidateCreateScavengeTest.class,
ClusteredSessionMigrationTest.class,
ModifyMaxInactiveIntervalTest.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>10.0.0-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.AbstractClusteredOrphanedSessionTest;
import org.eclipse.jetty.server.session.SessionDataStoreFactory; import org.eclipse.jetty.server.session.SessionDataStoreFactory;
import org.junit.After; import org.junit.After;
import org.junit.Before;
/** /**
* ClusteredOrphanedSessionTest * ClusteredOrphanedSessionTest
@ -34,20 +35,26 @@ public class ClusteredOrphanedSessionTest
HazelcastSessionDataStoreFactory factory; 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() * @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
*/ */
@Override @Override
public SessionDataStoreFactory createSessionDataStoreFactory() public SessionDataStoreFactory createSessionDataStoreFactory()
{ {
factory = new HazelcastSessionDataStoreFactory(); return _testHelper.createSessionDataStoreFactory(false);
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.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.AbstractClusteredSessionScavengingTest;
import org.eclipse.jetty.server.session.SessionDataStoreFactory; import org.eclipse.jetty.server.session.SessionDataStoreFactory;
import org.junit.After; import org.junit.After;
import org.junit.Before;
/** /**
* ClusteredSessionScavengingTest * ClusteredSessionScavengingTest
@ -34,20 +35,27 @@ public class ClusteredSessionScavengingTest
HazelcastSessionDataStoreFactory factory; 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() * @see org.eclipse.jetty.server.session.AbstractTestBase#createSessionDataStoreFactory()
*/ */
@Override @Override
public SessionDataStoreFactory createSessionDataStoreFactory() public SessionDataStoreFactory createSessionDataStoreFactory()
{ {
factory = new HazelcastSessionDataStoreFactory(); return _testHelper.createSessionDataStoreFactory(false);
factory.setMapName( Long.toString( TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) ) );
return factory;
} }
@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 java.util.concurrent.TimeUnit;
import org.eclipse.jetty.hazelcast.session.HazelcastSessionDataStoreFactory; 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.AbstractClusteredOrphanedSessionTest;
import org.eclipse.jetty.server.session.SessionDataStoreFactory; import org.eclipse.jetty.server.session.SessionDataStoreFactory;
import org.junit.After; import org.junit.After;
@ -36,37 +37,24 @@ public class ClientOrphanedSessionTest
extends AbstractClusteredOrphanedSessionTest 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 @Override
public SessionDataStoreFactory createSessionDataStoreFactory() public SessionDataStoreFactory createSessionDataStoreFactory()
{ {
HazelcastSessionDataStoreFactory factory = new HazelcastSessionDataStoreFactory(); return _testHelper.createSessionDataStoreFactory(true);
factory.setOnlyClient( true ); }
factory.setMapName( MAP_NAME );
return factory; @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 java.util.concurrent.TimeUnit;
import org.eclipse.jetty.hazelcast.session.HazelcastSessionDataStoreFactory; 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.AbstractClusteredSessionScavengingTest;
import org.eclipse.jetty.server.session.SessionDataStoreFactory; import org.eclipse.jetty.server.session.SessionDataStoreFactory;
import org.junit.After; import org.junit.After;
@ -36,37 +37,23 @@ public class ClientSessionScavengingTest
extends AbstractClusteredSessionScavengingTest 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 @Override
public SessionDataStoreFactory createSessionDataStoreFactory() public SessionDataStoreFactory createSessionDataStoreFactory()
{ {
HazelcastSessionDataStoreFactory factory = new HazelcastSessionDataStoreFactory(); return _testHelper.createSessionDataStoreFactory(true);
factory.setOnlyClient( true ); }
factory.setMapName( MAP_NAME );
return factory; @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; package org.eclipse.jetty.server.session;
import org.eclipse.jetty.session.infinispan.InfinispanSessionDataStoreFactory; import org.eclipse.jetty.session.infinispan.InfinispanSessionDataStoreFactory;
import org.eclipse.jetty.toolchain.test.JDK;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.BeforeClass; 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; package org.eclipse.jetty.server.session;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.File; import java.io.File;
import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.IO;
@ -104,6 +107,7 @@ public class InfinispanTestSupport
public void teardown () throws Exception public void teardown () throws Exception
{ {
_cache.clear();
_manager.removeCache(_name); _manager.removeCache(_name);
if (_useFileStore) 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();
}
}

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.remote;
import org.eclipse.jetty.server.session.AbstractModifyMaxInactiveIntervalTest;
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
import org.eclipse.jetty.session.infinispan.InfinispanSessionDataStoreFactory;
import org.junit.AfterClass;
import org.junit.BeforeClass;
/**
* ModifyMaxInactiveIntervalTest
*
*
*/
public class ModifyMaxInactiveIntervalTest extends AbstractModifyMaxInactiveIntervalTest
{
public static RemoteInfinispanTestSupport __testSupport;
@BeforeClass
public static void setup () throws Exception
{
__testSupport = new RemoteInfinispanTestSupport("remote-session-test");
__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,94 +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.remote;
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.server.session.AbstractNonClusteredSessionScavengingTest;
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
import org.eclipse.jetty.session.infinispan.InfinispanSessionDataStoreFactory;
import org.junit.AfterClass;
import org.junit.BeforeClass;
/**
* NonClusteredSessionScavengingTest
*
*
*/
public class NonClusteredSessionScavengingTest extends AbstractNonClusteredSessionScavengingTest
{
public static RemoteInfinispanTestSupport __testSupport;
@BeforeClass
public static void setup () throws Exception
{
__testSupport = new RemoteInfinispanTestSupport("remote-session-test");
__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,65 +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.remote;
import org.eclipse.jetty.server.session.AbstractClusteredLastAccessTimeTest;
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
import org.eclipse.jetty.session.infinispan.InfinispanSessionDataStoreFactory;
import org.junit.AfterClass;
import org.junit.BeforeClass;
public class RemoteClusteredLastAccessTimeTest extends AbstractClusteredLastAccessTimeTest
{
public static RemoteInfinispanTestSupport __testSupport;
@BeforeClass
public static void setup () throws Exception
{
__testSupport = new RemoteInfinispanTestSupport("remote-session-test");
__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 testLastAccessTime() throws Exception
{
super.testLastAccessTime();
}
}

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.server.session.remote;
import org.eclipse.jetty.server.session.AbstractClusteredSessionMigrationTest;
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
import org.eclipse.jetty.session.infinispan.InfinispanSessionDataStoreFactory;
import org.junit.AfterClass;
import org.junit.BeforeClass;
/**
* RemoteClusteredSessionMigrationTest
*
*
*/
public class RemoteClusteredSessionMigrationTest extends AbstractClusteredSessionMigrationTest
{
public static RemoteInfinispanTestSupport __testSupport;
@BeforeClass
public static void setup () throws Exception
{
__testSupport = new RemoteInfinispanTestSupport("remote-session-test");
__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

@ -0,0 +1,169 @@
//
// ========================================================================
// 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.remote;
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.eclipse.jetty.session.infinispan.InfinispanSessionDataStore;
import org.eclipse.jetty.session.infinispan.InfinispanSessionDataStoreFactory;
import org.junit.After;
import org.junit.Before;
/**
* RemoteInfinispanSessionDataStoreTest
*
*
*/
public class RemoteInfinispanSessionDataStoreTest extends AbstractSessionDataStoreTest
{
public static RemoteInfinispanTestSupport __testSupport;
@Before
public void setup () throws Exception
{
__testSupport = new RemoteInfinispanTestSupport("remote-session-test");
__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);
}
@Override
public boolean checkSessionPersisted(SessionData data) throws Exception
{
return __testSupport.checkSessionPersisted(data);
}
/**
* 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
}
/**
* 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
}
}
}

Some files were not shown because too many files have changed in this diff Show More