Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Bartel2015-04-02 01:20:12 +0000
committerJan Bartel2015-04-02 01:20:12 +0000
commit7375ba2cc3b5f156bbba4afff23bb2dd444fe923 (patch)
treedba3753b27eeae9925531fc7be311bdd978f9e09
parentabb74087a5b19267af09d9d4314321dbc1d1e301 (diff)
downloadorg.eclipse.jetty.project-7375ba2cc3b5f156bbba4afff23bb2dd444fe923.tar.gz
org.eclipse.jetty.project-7375ba2cc3b5f156bbba4afff23bb2dd444fe923.tar.xz
org.eclipse.jetty.project-7375ba2cc3b5f156bbba4afff23bb2dd444fe923.zip
Alpha impl for infinispan session manager.
Conflicts: tests/test-sessions/pom.xml Conflicts: tests/test-sessions/pom.xml tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SessionExpiryTest.java
-rw-r--r--jetty-infinispan/pom.xml83
-rw-r--r--jetty-infinispan/src/main/java/org/eclipse/jetty/session/infinispan/InfinispanSessionIdManager.java316
-rw-r--r--jetty-infinispan/src/main/java/org/eclipse/jetty/session/infinispan/InfinispanSessionManager.java1188
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java6
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java27
-rw-r--r--pom.xml3
-rw-r--r--tests/test-sessions/pom.xml2
-rw-r--r--tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/HashTestServer.java2
-rw-r--r--tests/test-sessions/test-infinispan-sessions/pom.xml136
-rw-r--r--tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/ClientCrossContextSessionTest.java60
-rw-r--r--tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/ImmortalSessionTest.java71
-rw-r--r--tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/InfinispanTestSessionServer.java79
-rw-r--r--tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/InfinispanTestSupport.java114
-rw-r--r--tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/InvalidationSessionTest.java116
-rw-r--r--tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/LastAccessTimeTest.java65
-rw-r--r--tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/LocalSessionScavengingTest.java59
-rw-r--r--tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/NewSessionTest.java66
-rw-r--r--tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/ReentrantRequestSessionTest.java64
-rw-r--r--tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/RemoveSessionTest.java58
-rw-r--r--tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/SessionExpiryTest.java70
-rw-r--r--tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/SessionInvalidateAndCreateTest.java66
-rw-r--r--tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/SessionMigrationTest.java64
-rw-r--r--tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/SessionRenewTest.java67
-rw-r--r--tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/JdbcTestServer.java4
-rw-r--r--tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SessionExpiryTest.java114
-rw-r--r--tests/test-sessions/test-mongodb-sessions/src/test/java/org/eclipse/jetty/nosql/mongodb/MongoTestServer.java2
-rw-r--r--tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractRemoveSessionTest.java3
-rw-r--r--tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionCookieTest.java2
-rw-r--r--tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionExpiryTest.java58
-rw-r--r--tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionValueSavingTest.java2
-rw-r--r--tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractTestServer.java27
31 files changed, 2845 insertions, 149 deletions
diff --git a/jetty-infinispan/pom.xml b/jetty-infinispan/pom.xml
new file mode 100644
index 0000000000..ed5c2ca9ce
--- /dev/null
+++ b/jetty-infinispan/pom.xml
@@ -0,0 +1,83 @@
+<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">
+ <parent>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-project</artifactId>
+ <version>9.1.6-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>jetty-infinispan</artifactId>
+ <name>Jetty :: Infinispan Session Managers</name>
+ <url>http://www.eclipse.org/jetty</url>
+ <properties>
+ <bundle-symbolic-name>${project.groupId}.infinispan</bundle-symbolic-name>
+ <infinispan.version>7.1.1.Final</infinispan.version>
+ </properties>
+ <build>
+ <defaultGoal>install</defaultGoal>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <configuration>
+ <descriptorRefs>
+ <descriptorRef>config</descriptorRef>
+ </descriptorRefs>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Import-Package>javax.servlet.*;version="[2.6.0,3.2)",org.eclipse.jetty.server.session.jmx;version="9.1";resolution:=optional,,org.eclipse.jetty.*;version="9.1",*</Import-Package>
+ </instructions>
+ </configuration>
+ <extensions>true</extensions>
+ <executions>
+ <execution>
+ <goals>
+ <goal>manifest</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>artifact-jar</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <archive>
+ <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+ </archive>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.infinispan</groupId>
+ <artifactId>infinispan-core</artifactId>
+ <version>${infinispan.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/jetty-infinispan/src/main/java/org/eclipse/jetty/session/infinispan/InfinispanSessionIdManager.java b/jetty-infinispan/src/main/java/org/eclipse/jetty/session/infinispan/InfinispanSessionIdManager.java
new file mode 100644
index 0000000000..ceb0d1c760
--- /dev/null
+++ b/jetty-infinispan/src/main/java/org/eclipse/jetty/session/infinispan/InfinispanSessionIdManager.java
@@ -0,0 +1,316 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2015 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.session.infinispan;
+
+import java.util.Random;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.SessionManager;
+import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.server.session.AbstractSession;
+import org.eclipse.jetty.server.session.AbstractSessionIdManager;
+import org.eclipse.jetty.server.session.SessionHandler;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.infinispan.Cache;
+
+
+
+/**
+ * InfinispanSessionIdManager
+ *
+ * Maintain a set of in-use session ids. This session id manager does NOT locally store
+ * a list of in-use sesssion ids, but rather stores them in the cluster cache. Thus,
+ * all operations to this session manager involve interaction with a possibly remote
+ * cache.
+ *
+ * For each session id that is in-use, an entry of the following form is put into
+ * the cluster cache:
+ * <pre>
+ * ("__o.e.j.s.infinispanIdMgr__"+[id], [id])
+ * </pre>
+ * where [id] is the id of the session.
+ *
+ * Having one entry per in-use session id means that there is no contention on
+ * cache entries (as would be the case if a single entry was kept containing a
+ * list of in-use session ids).
+ *
+ * TODO synchronization
+ */
+public class InfinispanSessionIdManager extends AbstractSessionIdManager
+{
+ private final static Logger LOG = Log.getLogger("org.eclipse.jetty.server.session");
+ protected final static String ID_KEY = "__o.e.j.s.infinispanIdMgr__";
+ protected Cache<String,Object> _cache;
+ private Server _server;
+
+
+
+
+
+ /**
+ * @param server
+ */
+ public InfinispanSessionIdManager(Server server)
+ {
+ super();
+ _server = server;
+ }
+
+ /**
+ * @param server
+ * @param random
+ */
+ public InfinispanSessionIdManager(Server server, Random random)
+ {
+ super(random);
+ _server = server;
+ }
+
+
+
+ /**
+ * Start the id manager.
+ * @see org.eclipse.jetty.server.session.AbstractSessionIdManager#doStart()
+ */
+ @Override
+ protected void doStart() throws Exception
+ {
+ super.doStart();
+ }
+
+
+
+ /**
+ * Stop the id manager
+ * @see org.eclipse.jetty.server.session.AbstractSessionIdManager#doStop()
+ */
+ @Override
+ protected void doStop() throws Exception
+ {
+ super.doStop();
+ }
+
+
+
+
+
+ /**
+ * Check to see if the given session id is being
+ * used by a session in any context.
+ *
+ * This method will consult the cluster.
+ *
+ * @see org.eclipse.jetty.server.SessionIdManager#idInUse(java.lang.String)
+ */
+ @Override
+ public boolean idInUse(String id)
+ {
+ if (id == null)
+ return false;
+
+ String clusterId = getClusterId(id);
+
+ //ask the cluster
+ try
+ {
+ return exists(clusterId);
+ }
+ catch (Exception e)
+ {
+ LOG.warn("Problem checking inUse for id="+clusterId, e);
+ return false;
+ }
+
+ }
+
+ /**
+ * Remember a new in-use session id.
+ *
+ * This will save the in-use session id to the cluster.
+ *
+ * @see org.eclipse.jetty.server.SessionIdManager#addSession(javax.servlet.http.HttpSession)
+ */
+ @Override
+ public void addSession(HttpSession session)
+ {
+ if (session == null)
+ return;
+
+ //insert into the cache
+ insert (((AbstractSession)session).getClusterId());
+ }
+
+ /**
+ * Remove a session id from the list of in-use ids.
+ *
+ * This will remvove the corresponding session id from the cluster.
+ *
+ * @see org.eclipse.jetty.server.SessionIdManager#removeSession(javax.servlet.http.HttpSession)
+ */
+ @Override
+ public void removeSession(HttpSession session)
+ {
+ if (session == null)
+ return;
+
+ //delete from the cache
+ delete (((AbstractSession)session).getClusterId());
+ }
+
+ /**
+ * Remove a session id. This compels all other contexts who have a session
+ * with the same id to also remove it.
+ *
+ * @see org.eclipse.jetty.server.SessionIdManager#invalidateAll(java.lang.String)
+ */
+ @Override
+ public void invalidateAll(String id)
+ {
+ //delete the session id from list of in-use sessions
+ delete (id);
+
+
+ //tell all contexts that may have a session object with this id to
+ //get rid of them
+ Handler[] contexts = _server.getChildHandlersByClass(ContextHandler.class);
+ for (int i=0; contexts!=null && i<contexts.length; i++)
+ {
+ SessionHandler sessionHandler = ((ContextHandler)contexts[i]).getChildHandlerByClass(SessionHandler.class);
+ if (sessionHandler != null)
+ {
+ SessionManager manager = sessionHandler.getSessionManager();
+
+ if (manager != null && manager instanceof InfinispanSessionManager)
+ {
+ ((InfinispanSessionManager)manager).invalidateSession(id);
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Change a session id.
+ *
+ * Typically this occurs when a previously existing session has passed through authentication.
+ *
+ * @see org.eclipse.jetty.server.session.AbstractSessionIdManager#renewSessionId(java.lang.String, java.lang.String, javax.servlet.http.HttpServletRequest)
+ */
+ @Override
+ public void renewSessionId(String oldClusterId, String oldNodeId, HttpServletRequest request)
+ {
+ //generate a new id
+ String newClusterId = newSessionId(request.hashCode());
+
+ delete(oldClusterId);
+ insert(newClusterId);
+
+
+ //tell all contexts to update the id
+ Handler[] contexts = _server.getChildHandlersByClass(ContextHandler.class);
+ for (int i=0; contexts!=null && i<contexts.length; i++)
+ {
+ SessionHandler sessionHandler = ((ContextHandler)contexts[i]).getChildHandlerByClass(SessionHandler.class);
+ if (sessionHandler != null)
+ {
+ SessionManager manager = sessionHandler.getSessionManager();
+
+ if (manager != null && manager instanceof InfinispanSessionManager)
+ {
+ ((InfinispanSessionManager)manager).renewSessionId(oldClusterId, oldNodeId, newClusterId, getNodeId(newClusterId, request));
+ }
+ }
+ }
+
+ }
+
+ public Cache<String,Object> getCache()
+ {
+ return _cache;
+ }
+
+ public void setCache(Cache<String,Object> cache)
+ {
+ this._cache = cache;
+ }
+
+ /**
+ * Ask the cluster if a particular id exists.
+ *
+ * @param id
+ * @return
+ */
+ protected boolean exists (String id)
+ {
+ if (_cache == null)
+ throw new IllegalStateException ("No cache");
+
+ Object key =_cache.get(makeKey(id));
+ if (key == null)
+ return false;
+ return true;
+ }
+
+
+ /**
+ * Put a session id into the cluster.
+ *
+ * @param id
+ */
+ protected void insert (String id)
+ {
+ if (_cache == null)
+ throw new IllegalStateException ("No cache");
+
+ _cache.putIfAbsent(makeKey(id), id);
+ }
+
+
+
+ /**
+ * Remove a session id from the cluster.
+ *
+ * @param id
+ */
+ protected void delete (String id)
+ {
+ if (_cache == null)
+ throw new IllegalStateException ("No cache");
+
+ _cache.remove(makeKey(id));
+ }
+
+
+
+ /**
+ * Generate a unique cache key from the session id.
+ *
+ * @param id
+ * @return
+ */
+ protected String makeKey (String id)
+ {
+ return ID_KEY+id;
+ }
+}
diff --git a/jetty-infinispan/src/main/java/org/eclipse/jetty/session/infinispan/InfinispanSessionManager.java b/jetty-infinispan/src/main/java/org/eclipse/jetty/session/infinispan/InfinispanSessionManager.java
new file mode 100644
index 0000000000..ca4d80899d
--- /dev/null
+++ b/jetty-infinispan/src/main/java/org/eclipse/jetty/session/infinispan/InfinispanSessionManager.java
@@ -0,0 +1,1188 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2015 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.session.infinispan;
+
+import java.io.IOException;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.ReentrantLock;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.server.handler.ContextHandler.Context;
+import org.eclipse.jetty.server.session.AbstractSession;
+import org.eclipse.jetty.server.session.AbstractSessionManager;
+import org.eclipse.jetty.server.session.MemSession;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
+import org.eclipse.jetty.util.thread.Scheduler;
+import org.infinispan.Cache;
+
+/**
+ * InfinispanSessionManager
+ *
+ * The data for a session relevant to a particular context is stored in an Infinispan (clustered) cache:
+ * <pre>
+ * Key: is the id of the session + the context path + the vhost for the context
+ * Value: is the data of the session
+ * </pre>
+ *
+ * The key is necessarily complex because the same session id can be in-use by more than one
+ * context. In this case, the contents of the session will strictly be different for each
+ * context, although the id will be the same.
+ *
+ * Sessions are also kept in local memory when they are used by this session manager. This allows
+ * multiple different request threads in the same context to call Request.getSession() and
+ * obtain the same object.
+ *
+ * This session manager support scavenging, which is only done over the set of sessions in its
+ * local memory. This can result in some sessions being "stranded" in the cluster cache if no
+ * session manager is currently managing it (eg the node managing the session crashed and it
+ * was never requested on another node).
+ *
+ */
+public class InfinispanSessionManager extends AbstractSessionManager
+{
+ private final static Logger LOG = Log.getLogger("org.eclipse.jetty.server.session");
+
+ /**
+ * Clustered cache of sessions
+ */
+ private Cache<String, Object> _cache;
+
+
+ /**
+ * Sessions known to this node held in memory
+ */
+ private ConcurrentHashMap<String, InfinispanSessionManager.Session> _sessions;
+
+
+ /**
+ * The length of time a session can be in memory without being checked against
+ * the cluster. A value of 0 indicates that the session is never checked against
+ * the cluster - the current node is considered to be the master for the session.
+ *
+ */
+ private long _staleIntervalSec = 0;
+
+ protected Scheduler.Task _task; //scavenge task
+ protected Scheduler _scheduler;
+ protected Scavenger _scavenger;
+ protected long _scavengeIntervalMs = 1000L * 60 * 10; //10mins
+ protected boolean _ownScheduler;
+
+
+
+ /**
+ * Scavenger
+ *
+ */
+ protected class Scavenger implements Runnable
+ {
+
+ @Override
+ public void run()
+ {
+ try
+ {
+ scavenge();
+ }
+ finally
+ {
+ if (_scheduler != null && _scheduler.isRunning())
+ _task = _scheduler.schedule(this, _scavengeIntervalMs, TimeUnit.MILLISECONDS);
+ }
+ }
+ }
+
+
+ /*
+ * Every time a Session is put into the cache one of these objects
+ * is created to copy the data out of the in-memory session, and
+ * every time an object is read from the cache one of these objects
+ * a fresh Session object is created based on the data held by this
+ * object.
+ */
+ public class SerializableSessionData implements Serializable
+ {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -7779120106058533486L;
+ String clusterId;
+ String contextPath;
+ String vhost;
+ long accessed;
+ long lastAccessed;
+ long createTime;
+ long cookieSetTime;
+ String lastNode;
+ long expiry;
+ long maxInactive;
+ Map<String, Object> attributes;
+
+ public SerializableSessionData()
+ {
+
+ }
+
+
+ public SerializableSessionData(Session s)
+ {
+ clusterId = s.getClusterId();
+ contextPath = s.getContextPath();
+ vhost = s.getVHost();
+ accessed = s.getAccessed();
+ lastAccessed = s.getLastAccessedTime();
+ createTime = s.getCreationTime();
+ cookieSetTime = s.getCookieSetTime();
+ lastNode = s.getLastNode();
+ expiry = s.getExpiry();
+ maxInactive = s.getMaxInactiveInterval();
+ attributes = s.getAttributeMap(); // TODO pointer, not a copy
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws IOException
+ {
+ out.writeUTF(clusterId); //session id
+ out.writeUTF(contextPath); //context path
+ out.writeUTF(vhost); //first vhost
+
+ out.writeLong(accessed);//accessTime
+ out.writeLong(lastAccessed); //lastAccessTime
+ out.writeLong(createTime); //time created
+ out.writeLong(cookieSetTime);//time cookie was set
+ out.writeUTF(lastNode); //name of last node managing
+
+ out.writeLong(expiry);
+ out.writeLong(maxInactive);
+ out.writeObject(attributes);
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException
+ {
+ clusterId = in.readUTF();
+ contextPath = in.readUTF();
+ vhost = in.readUTF();
+
+ accessed = in.readLong();//accessTime
+ lastAccessed = in.readLong(); //lastAccessTime
+ createTime = in.readLong(); //time created
+ cookieSetTime = in.readLong();//time cookie was set
+ lastNode = in.readUTF(); //last managing node
+ expiry = in.readLong();
+ maxInactive = in.readLong();
+ HashMap<String,Object> attributes = (HashMap<String,Object>)in.readObject();
+ }
+
+ }
+
+
+
+
+ /**
+ * SerializableSession
+ *
+ * Helper class that is responsible for de/serialization of the non-serializable session object.
+ */
+ public class SerializableSession implements Serializable
+ {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -7603529353470249059L;
+ private transient Session _session;
+
+
+ public SerializableSession ()
+ {
+
+ }
+
+ public SerializableSession (Session session)
+ {
+ setSession(session);
+ }
+
+ /**
+ * Existing session
+ * @param session
+ */
+ public void setSession (Session session)
+ {
+ _session = session;
+ }
+
+ public Session getSession ()
+ {
+ return _session;
+ }
+
+
+ private void writeObject(java.io.ObjectOutputStream out) throws IOException
+ {
+ if (_session == null)
+ throw new IOException ("No session to serialize");
+
+ out.writeUTF(_session.getClusterId()); //session id
+ out.writeUTF(_session.getContextPath()); //context path
+ out.writeUTF(_session.getVHost()); //first vhost
+
+ out.writeLong(_session.getAccessed());//accessTime
+ out.writeLong(_session.getLastAccessedTime()); //lastAccessTime
+ out.writeLong(_session.getCreationTime()); //time created
+ out.writeLong(_session.getCookieSetTime());//time cookie was set
+ out.writeUTF(_session.getLastNode()); //name of last node managing
+
+ out.writeLong(_session.getExpiry());
+ out.writeLong(_session.getMaxInactiveInterval());
+ out.writeObject(_session.getAttributeMap());
+ }
+
+
+ private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException
+ {
+ String clusterId = in.readUTF();
+ String context = in.readUTF();
+ String vhost = in.readUTF();
+
+ Long accessed = in.readLong();//accessTime
+ Long lastAccessed = in.readLong(); //lastAccessTime
+ Long created = in.readLong(); //time created
+ Long cookieSet = in.readLong();//time cookie was set
+ String lastNode = in.readUTF(); //last managing node
+ Long expiry = in.readLong();
+ Long maxIdle = in.readLong();
+ HashMap<String,Object> attributes = (HashMap<String,Object>)in.readObject();
+ Session session = new Session(clusterId, created, accessed, maxIdle);
+ session.setCookieSetTime(cookieSet);
+ session.setLastAccessedTime(lastAccessed);
+ session.setLastNode(lastNode);
+ session.setContextPath(context);
+ session.setVHost(vhost);
+ session.setExpiry(expiry);
+ session.addAttributes(attributes);
+ setSession(session);
+ }
+
+
+ private void readObjectNoData() throws ObjectStreamException
+ {
+ setSession(null);
+ }
+
+
+ }
+
+
+ /**
+ * Session
+ *
+ * Representation of a session in local memory.
+ */
+ public class Session extends MemSession
+ {
+
+ private ReentrantLock _lock = new ReentrantLock();
+
+ /**
+ * The (canonical) context path for with which this session is associated
+ */
+ private String _contextPath;
+
+
+ /**
+ * The number of currently active request threads in this session
+ */
+ private AtomicInteger _activeThreads = new AtomicInteger(0);
+
+
+ /**
+ * The time in msec since the epoch at which this session should expire
+ */
+ private long _expiryTime;
+
+
+ /**
+ * Time in msec since the epoch at which this session was last read from cluster
+ */
+ private long _lastSyncTime;
+
+
+ /**
+ * The workername of last node known to be managing the session
+ */
+ private String _lastNode;
+
+
+
+
+ /**
+ * Any virtual hosts for the context with which this session is associated
+ */
+ private String _vhost;
+
+
+
+
+ /**
+ * A new session.
+ *
+ * @param request
+ */
+ protected Session (HttpServletRequest request)
+ {
+ super(InfinispanSessionManager.this,request);
+ long maxInterval = getMaxInactiveInterval();
+ _expiryTime = (maxInterval <= 0 ? 0 : (System.currentTimeMillis() + maxInterval*1000L));
+ _lastNode = getSessionIdManager().getWorkerName();
+ setVHost(InfinispanSessionManager.getVirtualHost(_context));
+ setContextPath(InfinispanSessionManager.getContextPath(_context));
+ }
+
+
+ protected Session (SerializableSessionData sd)
+ {
+ super(InfinispanSessionManager.this, sd.createTime, sd.accessed, sd.clusterId);
+ _expiryTime = (sd.maxInactive <= 0 ? 0 : (System.currentTimeMillis() + sd.maxInactive*1000L));
+ setLastNode(sd.lastNode);
+ setContextPath(sd.contextPath);
+ setVHost(sd.vhost);
+ addAttributes(sd.attributes);
+ }
+
+
+ /**
+ * A restored session.
+ *
+ * @param sessionId
+ * @param created
+ * @param accessed
+ * @param maxInterval
+ */
+ protected Session (String sessionId, long created, long accessed, long maxInterval)
+ {
+ super(InfinispanSessionManager.this, created, accessed, sessionId);
+ _expiryTime = (maxInterval <= 0 ? 0 : (System.currentTimeMillis() + maxInterval*1000L));
+ }
+
+ /**
+ * Called on entry to the session.
+ *
+ * @see org.eclipse.jetty.server.session.AbstractSession#access(long)
+ */
+ @Override
+ protected boolean access(long time)
+ {
+ if (LOG.isDebugEnabled())
+ LOG.debug("Access session({}) for context {} on worker {}", getId(), getContextPath(), getSessionIdManager().getWorkerName());
+ try
+ {
+ _lock.lock();
+
+ //a request thread is entering
+ if (_activeThreads.incrementAndGet() == 1)
+ {
+ long now = System.currentTimeMillis();
+
+ //if the first thread, check that the session in memory is not stale, if we're checking for stale sessions
+ if (getStaleIntervalSec() > 0 && (now - getLastSyncTime()) >= (getStaleIntervalSec() * 1000L))
+ {
+ if (LOG.isDebugEnabled())
+ LOG.debug("Acess session({}) for context {} on worker {} stale session. Reloading.", getId(), getContextPath(), getSessionIdManager().getWorkerName());
+ refresh();
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ LOG.warn(e);
+ }
+ finally
+ {
+ _lock.unlock();
+ }
+
+ if (super.access(time))
+ {
+ int maxInterval=getMaxInactiveInterval();
+ _expiryTime = (maxInterval <= 0 ? 0 : (time + maxInterval*1000L));
+ return true;
+ }
+ return false;
+ }
+
+
+ /**
+ * Exit from session
+ * @see org.eclipse.jetty.server.session.AbstractSession#complete()
+ */
+ @Override
+ protected void complete()
+ {
+ super.complete();
+
+ //if this is the last request thread to be in the session
+ if (_activeThreads.decrementAndGet() == 0)
+ {
+ try
+ {
+ //an invalid session will already have been removed from the
+ //local session map and deleted from the cluster. If its valid save
+ //it to the cluster.
+ //TODO consider doing only periodic saves if only the last access
+ //time to the session changes
+ if (isValid())
+ {
+ willPassivate();
+ save(this);
+ didActivate();
+ }
+ }
+ catch (Exception e)
+ {
+ LOG.warn("Problem saving session({})",getId(), e);
+ }
+ }
+ }
+
+ /**
+ * Expire the session.
+ *
+ * @see org.eclipse.jetty.server.session.AbstractSession#timeout()
+ */
+ @Override
+ protected void timeout()
+ {
+ super.timeout();
+ }
+
+ /**
+ * Reload the session from the cluster. If the node that
+ * last managed the session from the cluster is ourself,
+ * then the session does not need refreshing.
+ * NOTE: this method MUST be called with sufficient locks
+ * in place to prevent 2 or more concurrent threads from
+ * simultaneously updating the session.
+ */
+ private void refresh ()
+ {
+ //get fresh copy from the cluster
+ Session fresh = load(getId());
+
+ //if the session no longer exists, invalidate
+ if (fresh == null)
+ {
+ invalidate();
+ return;
+ }
+
+ //cluster copy assumed to be the same as we were the last
+ //node to manage it
+ if (fresh.getLastNode().equals(getLastNode()))
+ return;
+
+ setLastNode(getSessionIdManager().getWorkerName());
+
+ //prepare for refresh
+ willPassivate();
+
+ //if fresh has no attributes, remove them
+ if (fresh.getAttributes() == 0)
+ this.clearAttributes();
+ else
+ {
+ //reconcile attributes
+ for (String key:fresh.getAttributeMap().keySet())
+ {
+ Object freshvalue = fresh.getAttribute(key);
+
+ //session does not already contain this attribute, so bind it
+ if (getAttribute(key) == null)
+ {
+ doPutOrRemove(key,freshvalue);
+ bindValue(key,freshvalue);
+ }
+ else //session already contains this attribute, update its value
+ {
+ doPutOrRemove(key,freshvalue);
+ }
+
+ }
+ // cleanup, remove values from session, that don't exist in data anymore:
+ for (String key : getNames())
+ {
+ if (fresh.getAttribute(key) == null)
+ {
+ Object oldvalue = getAttribute(key);
+ doPutOrRemove(key,null);
+ unbindValue(key,oldvalue);
+ }
+ }
+ }
+ //finish refresh
+ didActivate();
+ }
+
+
+ public void setExpiry (long expiry)
+ {
+ _expiryTime = expiry;
+ }
+
+
+ public long getExpiry ()
+ {
+ return _expiryTime;
+ }
+
+ public void swapId (String newId, String newNodeId)
+ {
+ _lock.lock();
+ setClusterId(newId);
+ setNodeId(newNodeId);
+ _lock.unlock();
+ }
+
+ @Override
+ public void setAttribute (String name, Object value)
+ {
+ Object old = changeAttribute(name, value);
+ if (value == null && old == null)
+ return; //if same as remove attribute but attribute was already removed, no change
+
+ //TODO _dirty = true;
+ }
+
+
+ public String getContextPath()
+ {
+ return _contextPath;
+ }
+
+
+ public void setContextPath(String contextPath)
+ {
+ this._contextPath = contextPath;
+ }
+
+
+ public String getVHost()
+ {
+ return _vhost;
+ }
+
+
+ public void setVHost(String vhost)
+ {
+ this._vhost = vhost;
+ }
+
+ public String getLastNode()
+ {
+ return _lastNode;
+ }
+
+
+ public void setLastNode(String lastNode)
+ {
+ _lastNode = lastNode;
+ }
+
+
+ public long getLastSyncTime()
+ {
+ return _lastSyncTime;
+ }
+
+
+ public void setLastSyncTime(long lastSyncTime)
+ {
+ _lastSyncTime = lastSyncTime;
+ }
+
+ }
+
+
+
+
+ /**
+ * Start the session manager.
+ *
+ * @see org.eclipse.jetty.server.session.AbstractSessionManager#doStart()
+ */
+ @Override
+ public void doStart() throws Exception
+ {
+ if (_sessionIdManager == null)
+ throw new IllegalStateException("No session id manager defined");
+
+ if (_cache == null)
+ throw new IllegalStateException("No session cache defined");
+
+ _sessions = new ConcurrentHashMap<String, Session>();
+
+ //try and use a common scheduler, fallback to own
+ _scheduler = getSessionHandler().getServer().getBean(Scheduler.class);
+ if (_scheduler == null)
+ {
+ _scheduler = new ScheduledExecutorScheduler();
+ _ownScheduler = true;
+ _scheduler.start();
+ }
+ else if (!_scheduler.isStarted())
+ throw new IllegalStateException("Shared scheduler not started");
+
+ setScavengeInterval(getScavengeInterval());
+
+ super.doStart();
+ }
+
+
+ /**
+ * Stop the session manager.
+ *
+ * @see org.eclipse.jetty.server.session.AbstractSessionManager#doStop()
+ */
+ @Override
+ public void doStop() throws Exception
+ {
+ super.doStop();
+
+ if (_task!=null)
+ _task.cancel();
+ _task=null;
+ if (_ownScheduler && _scheduler !=null)
+ _scheduler.stop();
+ _scheduler = null;
+
+ _sessions.clear();
+ _sessions = null;
+ }
+
+
+
+ /**
+ * Look for sessions in local memory that have expired.
+ */
+ /**
+ *
+ */
+ public void scavenge ()
+ {
+ Set<String> candidateIds = new HashSet<String>();
+ long now = System.currentTimeMillis();
+
+ LOG.info("SessionManager for context {} scavenging at {} ", getContextPath(getContext()), now);
+ synchronized (_sessions)
+ {
+ for (Map.Entry<String, Session> entry:_sessions.entrySet())
+ {
+ long expiry = entry.getValue().getExpiry();
+ if (expiry > 0 && expiry < now)
+ candidateIds.add(entry.getKey());
+ }
+ }
+
+ for (String candidateId:candidateIds)
+ {
+ if (LOG.isDebugEnabled())
+ LOG.debug("Session {} expired ", candidateId);
+
+ Session candidateSession = _sessions.get(candidateId);
+ if (candidateSession != null)
+ {
+ //double check the state of the session in the cache, as the
+ //session may have migrated to another node
+ Session cachedSession = load(makeKey(candidateId, _context));
+ if (cachedSession == null)
+ {
+ if (LOG.isDebugEnabled()) LOG.debug("Locally expired session({}) does not exist in cluster ",candidateId);
+ //the session no longer exists, do a full invalidation
+ candidateSession.timeout();
+ }
+ else if (getSessionIdManager().getWorkerName().equals(cachedSession.getLastNode()))
+ {
+ if (LOG.isDebugEnabled()) LOG.debug("Expiring session({}) local to session manager",candidateId);
+ //if I am the master of the session then it can be timed out
+ candidateSession.timeout();
+ }
+ else
+ {
+ //some other node is the master of the session, simply remove it from my memory
+ if (LOG.isDebugEnabled()) LOG.debug("Session({}) not local to this session manager, removing from local memory", candidateId);
+ candidateSession.willPassivate();
+ _sessions.remove(candidateSession.getClusterId());
+ }
+
+ }
+ }
+ }
+
+
+
+ public long getScavengeInterval ()
+ {
+ return _scavengeIntervalMs/1000;
+ }
+
+
+
+ /**
+ * Set the interval between runs of the scavenger. As this will be a costly
+ * exercise (need to iterate over all cache entries) it should not be run too
+ * often.
+ *
+ *
+ * @param sec
+ */
+ public void setScavengeInterval (long sec)
+ {
+ if (sec<=0)
+ sec=60;
+
+ long old_period=_scavengeIntervalMs;
+ long period=sec*1000L;
+
+ _scavengeIntervalMs=period;
+
+ //add a bit of variability into the scavenge time so that not all
+ //nodes with the same scavenge time sync up
+ long tenPercent = _scavengeIntervalMs/10;
+ if ((System.currentTimeMillis()%2) == 0)
+ _scavengeIntervalMs += tenPercent;
+
+ if (LOG.isDebugEnabled())
+ LOG.debug("Scavenging every "+_scavengeIntervalMs+" ms");
+
+ synchronized (this)
+ {
+ if (_scheduler != null && (period!=old_period || _task==null))
+ {
+ if (_task!=null)
+ _task.cancel();
+ if (_scavenger == null)
+ _scavenger = new Scavenger();
+
+ _task = _scheduler.schedule(_scavenger,_scavengeIntervalMs,TimeUnit.MILLISECONDS);
+ }
+ }
+ }
+
+
+
+
+ /**
+ * Get the clustered cache instance.
+ *
+ * @return
+ */
+ public Cache<String, Object> getCache()
+ {
+ return _cache;
+ }
+
+
+
+ /**
+ * Set the clustered cache instance.
+ *
+ * @param cache
+ */
+ public void setCache (Cache<String, Object> cache)
+ {
+ this._cache = cache;
+ }
+
+
+
+
+
+ public long getStaleIntervalSec()
+ {
+ return _staleIntervalSec;
+ }
+
+
+ public void setStaleIntervalSec(long staleIntervalSec)
+ {
+ _staleIntervalSec = staleIntervalSec;
+ }
+
+
+ /**
+ * Add a new session for the context related to this session manager
+ *
+ * @see org.eclipse.jetty.server.session.AbstractSessionManager#addSession(org.eclipse.jetty.server.session.AbstractSession)
+ */
+ @Override
+ protected void addSession(AbstractSession session)
+ {
+ if (session==null)
+ return;
+
+ if (LOG.isDebugEnabled()) LOG.debug("Adding session({}) to session manager for context {} on worker {}",session.getClusterId(), getContextPath(getContext()),getSessionIdManager().getWorkerName() + " with lastnode="+((Session)session).getLastNode());
+ _sessions.put(session.getClusterId(), (Session)session);
+
+ try
+ {
+ session.willPassivate();
+ save(((InfinispanSessionManager.Session)session));
+ session.didActivate();
+
+ }
+ catch (Exception e)
+ {
+ LOG.warn("Unable to store new session id="+session.getId() , e);
+ }
+ }
+
+ /**
+ * Ask the cluster for the session.
+ *
+ * @see org.eclipse.jetty.server.session.AbstractSessionManager#getSession(java.lang.String)
+ */
+ @Override
+ public AbstractSession getSession(String idInCluster)
+ {
+ Session session = null;
+
+
+ //try and find the session in this node's memory
+ Session memSession = (Session)_sessions.get(idInCluster);
+
+ if (LOG.isDebugEnabled())
+ LOG.debug("getSession({}) {} in session map",idInCluster,(memSession==null?"not":""));
+
+ long now = System.currentTimeMillis();
+ try
+ {
+ //if the session is not in this node's memory, then load it from the cluster cache
+ if (memSession == null)
+ {
+ if (LOG.isDebugEnabled())
+ LOG.debug("getSession({}): loading session data from cluster", idInCluster);
+
+ session = load(makeKey(idInCluster, _context));
+ if (session != null)
+ {
+ //We retrieved a session with the same key from the database
+
+ //Check that it wasn't expired
+ if (session.getExpiry() > 0 && session.getExpiry() <= now)
+ {
+ if (LOG.isDebugEnabled()) LOG.debug("getSession ({}): Session expired", idInCluster);
+ //ensure that the session id for the expired session is deleted so that a new session with the
+ //same id cannot be created (because the idInUse() test would succeed)
+ ((InfinispanSessionIdManager)getSessionIdManager()).removeSession(session);
+ return null;
+ }
+
+ //Update the last worker node to me
+ session.setLastNode(getSessionIdManager().getWorkerName());
+ //TODO consider saving session here if lastNode was not this node
+
+ //Check that another thread hasn't loaded the same session
+ Session existingSession = _sessions.putIfAbsent(idInCluster, session);
+ if (existingSession != null)
+ {
+ //use the one that the other thread inserted
+ session = existingSession;
+ LOG.debug("getSession({}): using session loaded by another request thread ", idInCluster);
+ }
+ else
+ {
+ //indicate that the session was reinflated
+ session.didActivate();
+ LOG.debug("getSession({}): loaded session from cluster", idInCluster);
+ }
+ return session;
+ }
+ else
+ {
+ //The requested session does not exist anywhere in the cluster
+ LOG.debug("getSession({}): No session in cluster matching",idInCluster);
+ return null;
+ }
+ }
+ else
+ {
+ //The session exists in this node's memory
+ LOG.debug("getSession({}): returning session from local memory ", memSession.getClusterId());
+ return memSession;
+ }
+ }
+ catch (Exception e)
+ {
+ LOG.warn("Unable to load session {}", idInCluster, e);
+ return null;
+ }
+ }
+
+
+
+ /**
+ * The session manager is stopping.
+ *
+ * @see org.eclipse.jetty.server.session.AbstractSessionManager#shutdownSessions()
+ */
+ @Override
+ protected void shutdownSessions() throws Exception
+ {
+ //TODO if implementing period saves, if we might have un-saved changes,
+ //then we need to write them back to the clustered cache
+ }
+
+
+ @Override
+ protected AbstractSession newSession(HttpServletRequest request)
+ {
+ return new Session(request);
+ }
+
+ /**
+ * Remove a session from local memory, and delete it from
+ * the cluster cache.
+ *
+ * @see org.eclipse.jetty.server.session.AbstractSessionManager#removeSession(java.lang.String)
+ */
+ @Override
+ protected boolean removeSession(String idInCluster)
+ {
+ Session session = (Session)_sessions.remove(idInCluster);
+ try
+ {
+ if (session != null)
+ delete(session);
+ }
+ catch (Exception e)
+ {
+ LOG.warn("Problem deleting session id="+idInCluster, e);
+ }
+ return session!=null;
+ }
+
+
+
+
+ @Override
+ public void renewSessionId(String oldClusterId, String oldNodeId, String newClusterId, String newNodeId)
+ {
+ Session session = null;
+ try
+ {
+ //take the session with that id out of our managed list
+ session = (Session)_sessions.remove(oldClusterId);
+ if (session != null)
+ {
+ //TODO consider transactionality and ramifications if the session is live on another node
+ delete(session); //delete the old session from the cluster
+ session.swapId(newClusterId, newNodeId); //update the session
+ _sessions.put(newClusterId, session); //put it into managed list under new key
+ save(session); //put the session under the new id into the cluster
+ }
+ }
+ catch (Exception e)
+ {
+ LOG.warn(e);
+ }
+
+ super.renewSessionId(oldClusterId, oldNodeId, newClusterId, newNodeId);
+ }
+
+
+ /**
+ * Load a session from the clustered cache.
+ *
+ * @param key
+ * @return
+ */
+ protected Session load (String key)
+ {
+ if (_cache == null)
+ throw new IllegalStateException("No cache");
+
+ if (LOG.isDebugEnabled()) LOG.debug("Loading session {} from cluster", key);
+ //SerializableSession storableSession = (SerializableSession)_cache.get(key);
+ SerializableSessionData storableSession = (SerializableSessionData)_cache.get(key);
+ if (storableSession == null)
+ {
+ if (LOG.isDebugEnabled()) LOG.debug("No session {} in cluster ",key);
+ return null;
+ }
+ else
+ {
+ //Session session = storableSession.getSession();
+ Session session = new Session (storableSession);
+ session.setLastSyncTime(System.currentTimeMillis());
+ return session;
+ }
+ }
+
+
+
+ /**
+ * Save or update the session to the cluster cache
+ *
+ * @param session
+ * @throws Exception
+ */
+ protected void save (InfinispanSessionManager.Session session)
+ throws Exception
+ {
+ if (_cache == null)
+ throw new IllegalStateException("No cache");
+
+ if (LOG.isDebugEnabled()) LOG.debug("Writing session {} to cluster", session.getId());
+
+ SerializableSessionData storableSession = new SerializableSessionData(session);
+ _cache.put(makeKey(session, _context), storableSession);
+ session.setLastSyncTime(System.currentTimeMillis());
+ }
+
+
+
+ /**
+ * Remove the session from the cluster cache.
+ *
+ * @param session
+ */
+ protected void delete (InfinispanSessionManager.Session session)
+ {
+ if (_cache == null)
+ throw new IllegalStateException("No cache");
+ if (LOG.isDebugEnabled()) LOG.debug("Removing session {} from cluster", session.getId());
+ _cache.remove(makeKey(session, _context));
+ }
+
+
+ /**
+ * Invalidate a session for this context with the given id
+ *
+ * @param idInCluster
+ */
+ public void invalidateSession (String idInCluster)
+ {
+ Session session = (Session)_sessions.get(idInCluster);
+
+ if (session != null)
+ {
+ session.invalidate();
+ }
+ }
+
+
+ /**
+ * Make a unique key for this session.
+ * As the same session id can be used across multiple contexts, to
+ * make it unique, the key must be composed of:
+ * <ol>
+ * <li>the id</li>
+ * <li>the context path</li>
+ * <li>the virtual hosts</li>
+ * </ol>
+ *
+ *TODO consider the difference between getClusterId and getId
+ * @param session
+ * @return
+ */
+ private String makeKey (Session session, Context context)
+ {
+ return makeKey(session.getId(), context);
+ }
+
+ /**
+ * Make a unique key for this session.
+ * As the same session id can be used across multiple contexts, to
+ * make it unique, the key must be composed of:
+ * <ol>
+ * <li>the id</li>
+ * <li>the context path</li>
+ * <li>the virtual hosts</li>
+ * </ol>
+ *
+ *TODO consider the difference between getClusterId and getId
+ * @param session
+ * @return
+ */
+ private String makeKey (String id, Context context)
+ {
+ String key = getContextPath(context);
+ key = key + "_" + getVirtualHost(context);
+ key = key+"_"+id;
+ return key;
+ }
+
+ /**
+ * Turn the context path into an acceptable string
+ *
+ * @param context
+ * @return
+ */
+ private static String getContextPath (ContextHandler.Context context)
+ {
+ return canonicalize (context.getContextPath());
+ }
+
+ /**
+ * Get the first virtual host for the context.
+ *
+ * Used to help identify the exact session/contextPath.
+ *
+ * @return 0.0.0.0 if no virtual host is defined
+ */
+ private static String getVirtualHost (ContextHandler.Context context)
+ {
+ String vhost = "0.0.0.0";
+
+ if (context==null)
+ return vhost;
+
+ String [] vhosts = context.getContextHandler().getVirtualHosts();
+ if (vhosts==null || vhosts.length==0 || vhosts[0]==null)
+ return vhost;
+
+ return vhosts[0];
+ }
+
+ /**
+ * Make an acceptable name from a context path.
+ *
+ * @param path
+ * @return
+ */
+ private static String canonicalize (String path)
+ {
+ if (path==null)
+ return "";
+
+ return path.replace('/', '_').replace('.','_').replace('\\','_');
+ }
+
+}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java
index 5c6e8bfe37..c6e4b2b49d 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java
@@ -155,6 +155,12 @@ public abstract class AbstractSession implements AbstractSessionManager.SessionI
{
return _cookieSet;
}
+
+ /* ------------------------------------------------------------- */
+ public void setCookieSetTime(long time)
+ {
+ _cookieSet = time;
+ }
/* ------------------------------------------------------------- */
@Override
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java
index 9aafc00599..be3c55a99c 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java
@@ -98,10 +98,7 @@ public class JDBCSessionManager extends AbstractSessionManager
protected boolean _dirty=false;
- /**
- * Time in msec since the epoch that a session cookie was set for this session
- */
- protected long _cookieSet;
+
/**
@@ -223,16 +220,7 @@ public class JDBCSessionManager extends AbstractSessionManager
return _canonicalContext;
}
- public void setCookieSet (long ms)
- {
- _cookieSet = ms;
- }
-
- public synchronized long getCookieSet ()
- {
- return _cookieSet;
- }
-
+
public synchronized void setLastNode (String node)
{
_lastNode=node;
@@ -261,11 +249,6 @@ public class JDBCSessionManager extends AbstractSessionManager
_dirty=true;
}
- @Override
- protected void cookieSet()
- {
- _cookieSet = getAccessed();
- }
/**
* Entry to session.
@@ -400,7 +383,7 @@ public class JDBCSessionManager extends AbstractSessionManager
{
return "Session rowId="+_rowId+",id="+getId()+",lastNode="+_lastNode+
",created="+getCreationTime()+",accessed="+getAccessed()+
- ",lastAccessed="+getLastAccessedTime()+",cookieSet="+_cookieSet+
+ ",lastAccessed="+getLastAccessedTime()+",cookieSet="+getCookieSetTime()+
",maxInterval="+getMaxInactiveInterval()+",lastSaved="+_lastSaved+",expiry="+_expiryTime;
}
}
@@ -925,7 +908,7 @@ public class JDBCSessionManager extends AbstractSessionManager
result.getLong(_sessionTableSchema.getCreateTimeColumn()),
result.getLong(_sessionTableSchema.getAccessTimeColumn()),
maxInterval);
- session.setCookieSet(result.getLong(_sessionTableSchema.getCookieTimeColumn()));
+ session.setCookieSetTime(result.getLong(_sessionTableSchema.getCookieTimeColumn()));
session.setLastAccessedTime(result.getLong(_sessionTableSchema.getLastAccessTimeColumn()));
session.setLastNode(result.getString(_sessionTableSchema.getLastNodeColumn()));
session.setLastSaved(result.getLong(_sessionTableSchema.getLastSavedTimeColumn()));
@@ -999,7 +982,7 @@ public class JDBCSessionManager extends AbstractSessionManager
statement.setLong(6, session.getAccessed());//accessTime
statement.setLong(7, session.getLastAccessedTime()); //lastAccessTime
statement.setLong(8, session.getCreationTime()); //time created
- statement.setLong(9, session.getCookieSet());//time cookie was set
+ statement.setLong(9, session.getCookieSetTime());//time cookie was set
statement.setLong(10, now); //last saved time
statement.setLong(11, session.getExpiryTime());
statement.setLong(12, session.getMaxInactiveInterval());
diff --git a/pom.xml b/pom.xml
index 8d5acb38d6..bc1359a8b9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -224,6 +224,8 @@
<exclude>jetty-policy/src/main/java/org/eclipse/jetty/policy/loader/DefaultPolicyLoader.java</exclude>
<exclude>jetty-policy/src/main/java/org/eclipse/jetty/policy/loader/PolicyFileScanner.java</exclude>
<exclude>jetty-ant/**</exclude>
+ <exclude>jetty-infinispan/**</exclude>
+ <exclude>tests/test-sessions/test-infinispan-sessions/**</exclude>
</excludes>
</configuration>
<executions>
@@ -484,6 +486,7 @@
<module>jetty-jaspi</module>
<module>jetty-rewrite</module>
<module>jetty-nosql</module>
+ <module>jetty-infinispan</module>
<module>tests</module>
<module>examples</module>
<module>jetty-quickstart</module>
diff --git a/tests/test-sessions/pom.xml b/tests/test-sessions/pom.xml
index dc15b9181d..288ebdf72d 100644
--- a/tests/test-sessions/pom.xml
+++ b/tests/test-sessions/pom.xml
@@ -33,7 +33,7 @@
<module>test-sessions-common</module>
<module>test-hash-sessions</module>
<module>test-jdbc-sessions</module>
- <!-- Requires mongodb server running -->
<module>test-mongodb-sessions</module>
+ <module>test-infinispan-sessions</module>
</modules>
</project>
diff --git a/tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/HashTestServer.java b/tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/HashTestServer.java
index d4d6b283b1..3393d8ea2f 100644
--- a/tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/HashTestServer.java
+++ b/tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/HashTestServer.java
@@ -38,7 +38,7 @@ public class HashTestServer extends AbstractTestServer
}
- public SessionIdManager newSessionIdManager(String config)
+ public SessionIdManager newSessionIdManager(Object config)
{
return new HashSessionIdManager();
}
diff --git a/tests/test-sessions/test-infinispan-sessions/pom.xml b/tests/test-sessions/test-infinispan-sessions/pom.xml
new file mode 100644
index 0000000000..c94a6e18ab
--- /dev/null
+++ b/tests/test-sessions/test-infinispan-sessions/pom.xml
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+// ========================================================================
+// Copyright (c) Webtide LLC
+//
+// 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.apache.org/licenses/LICENSE-2.0.txt
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.eclipse.jetty.tests</groupId>
+ <artifactId>test-sessions-parent</artifactId>
+ <version>9.1.6-SNAPSHOT</version>
+ </parent>
+ <artifactId>test-infinispan-sessions</artifactId>
+ <name>Jetty Tests :: Sessions :: Infinispan</name>
+ <url>http://www.eclipse.org/jetty</url>
+ <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>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skipTests>false</skipTests>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>unpack</id>
+ <phase>generate-test-resources</phase>
+ <goals>
+ <goal>unpack</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.eclipse.jetty.toolchain</groupId>
+ <artifactId>jetty-test-policy</artifactId>
+ <version>${jetty-test-policy-version}</version>
+ <type>jar</type>
+ <overWrite>true</overWrite>
+ <includes>**/*.keystore,**/*.pem</includes>
+ <outputDirectory>${jetty.test.policy.loc}</outputDirectory>
+ </artifactItem>
+ </artifactItems>
+ </configuration>
+ </execution>
+ </executions>
+ </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</groupId>
+ <artifactId>jetty-infinispan</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-jmx</artifactId>
+ <version>${project.version}</version>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.toolchain</groupId>
+ <artifactId>jetty-test-helper</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+<!--
+ <profiles>
+ <profile>
+ <id>mongodb</id>
+ <activation>
+ <property>
+ <name>mongodb.enabled</name>
+ <value>true</value>
+ </property>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skipTests>false</skipTests>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+-->
+</project>
diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/ClientCrossContextSessionTest.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/ClientCrossContextSessionTest.java
new file mode 100644
index 0000000000..22beec61a8
--- /dev/null
+++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/ClientCrossContextSessionTest.java
@@ -0,0 +1,60 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+
+package org.eclipse.jetty.server.session;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class ClientCrossContextSessionTest extends AbstractClientCrossContextSessionTest
+{
+
+ 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();
+ }
+
+
+ @Override
+ public AbstractTestServer createServer(int port)
+ {
+ InfinispanTestSessionServer server = new InfinispanTestSessionServer(port, __testSupport.getCache());
+ return server;
+ }
+
+ @Test
+ public void testCrossContextDispatch() throws Exception
+ {
+ super.testCrossContextDispatch();
+ }
+
+}
diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/ImmortalSessionTest.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/ImmortalSessionTest.java
new file mode 100644
index 0000000000..f021a70d62
--- /dev/null
+++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/ImmortalSessionTest.java
@@ -0,0 +1,71 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2015 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.infinispan.Cache;
+import org.infinispan.configuration.cache.ConfigurationBuilder;
+import org.infinispan.manager.DefaultCacheManager;
+import org.infinispan.manager.EmbeddedCacheManager;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+/**
+ * ImmortalSessionTest
+ *
+ *
+ */
+public class ImmortalSessionTest extends AbstractImmortalSessionTest
+{
+
+
+ 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.AbstractImmortalSessionTest#createServer(int, int, int)
+ */
+ @Override
+ public AbstractTestServer createServer(int port, int maxInactiveMs, int scavengeMs)
+ {
+ return new InfinispanTestSessionServer(port, maxInactiveMs, scavengeMs, __testSupport.getCache());
+ }
+
+ @Override
+ public void testImmortalSession() throws Exception
+ {
+ super.testImmortalSession();
+ }
+
+
+}
diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/InfinispanTestSessionServer.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/InfinispanTestSessionServer.java
new file mode 100644
index 0000000000..2edcbd34c2
--- /dev/null
+++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/InfinispanTestSessionServer.java
@@ -0,0 +1,79 @@
+package org.eclipse.jetty.server.session;
+
+import org.eclipse.jetty.server.SessionIdManager;
+import org.eclipse.jetty.server.SessionManager;
+import org.eclipse.jetty.session.infinispan.InfinispanSessionIdManager;
+import org.eclipse.jetty.session.infinispan.InfinispanSessionManager;
+import org.infinispan.Cache;
+import org.infinispan.commons.util.CloseableIteratorSet;
+
+public class InfinispanTestSessionServer extends AbstractTestServer
+{
+ static int __workers=0;
+
+
+
+
+
+ public InfinispanTestSessionServer(int port, Cache config)
+ {
+ this(port, 30, 10, config);
+ }
+
+
+
+ public InfinispanTestSessionServer(int port, int maxInactivePeriod, int scavengePeriod, Cache config)
+ {
+ super(port, maxInactivePeriod, scavengePeriod, config);
+ }
+
+
+
+ @Override
+ public SessionIdManager newSessionIdManager(Object config)
+ {
+ InfinispanSessionIdManager idManager = new InfinispanSessionIdManager(getServer());
+ idManager.setWorkerName("w"+(__workers++));
+ idManager.setCache((Cache)config);
+ return idManager;
+ }
+
+ @Override
+ public SessionManager newSessionManager()
+ {
+ InfinispanSessionManager sessionManager = new InfinispanSessionManager();
+ sessionManager.setSessionIdManager((InfinispanSessionIdManager)_sessionIdManager);
+ sessionManager.setCache(((InfinispanSessionIdManager)_sessionIdManager).getCache());
+ sessionManager.setStaleIntervalSec(1);
+ sessionManager.setScavengeInterval(_scavengePeriod);
+
+ return sessionManager;
+ }
+
+ @Override
+ public SessionHandler newSessionHandler(SessionManager sessionManager)
+ {
+ return new SessionHandler(sessionManager);
+ }
+
+
+ public void dumpCache ()
+ {
+ Cache cache = ((InfinispanSessionIdManager)_sessionIdManager).getCache();
+ if (cache != null)
+ {
+ System.err.println(cache.getName()+" contains "+cache.size()+" entries");
+ CloseableIteratorSet<String> keys = cache.keySet();
+ for (String key:keys)
+ System.err.println(key + " "+cache.get(key));
+ }
+ }
+
+ public void clearCache ()
+ {
+ Cache cache = ((InfinispanSessionIdManager)_sessionIdManager).getCache();
+ if (cache != null)
+ cache.clear();
+ }
+
+}
diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/InfinispanTestSupport.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/InfinispanTestSupport.java
new file mode 100644
index 0000000000..a3b61bd122
--- /dev/null
+++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/InfinispanTestSupport.java
@@ -0,0 +1,114 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2015 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 org.eclipse.jetty.util.IO;
+import org.infinispan.Cache;
+import org.infinispan.configuration.cache.Configuration;
+import org.infinispan.configuration.cache.ConfigurationBuilder;
+import org.infinispan.configuration.global.GlobalConfigurationBuilder;
+import org.infinispan.manager.DefaultCacheManager;
+import org.infinispan.manager.EmbeddedCacheManager;
+
+/**
+ * InfinispanTestSupport
+ *
+ *
+ */
+public class InfinispanTestSupport
+{
+ public static final String DEFAULT_CACHE_NAME = "session_test_cache";
+ public Cache _cache;
+
+ public ConfigurationBuilder _builder;
+ private File _tmpdir;
+ private boolean _useFileStore;
+ private String _name;
+ public static EmbeddedCacheManager _manager;
+
+ static
+ {
+ try
+ {
+ _manager = new DefaultCacheManager(new GlobalConfigurationBuilder().globalJmxStatistics().allowDuplicateDomains(true).build());
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ public InfinispanTestSupport ()
+ {
+ this (null);
+ }
+
+ public InfinispanTestSupport(String cacheName)
+ {
+ if (cacheName == null)
+ cacheName = DEFAULT_CACHE_NAME+System.currentTimeMillis();
+
+ _name = cacheName;
+ _builder = new ConfigurationBuilder();
+ }
+
+ public void setUseFileStore (boolean useFileStore)
+ {
+ _useFileStore = useFileStore;
+ }
+
+ public Cache getCache ()
+ {
+ return _cache;
+ }
+
+ public void setup () throws Exception
+ {
+ if (_useFileStore)
+ {
+ _tmpdir = File.createTempFile("infini", "span");
+ _tmpdir.delete();
+ _tmpdir.mkdir();
+ System.err.println("Temp file: "+_tmpdir);
+ Configuration config = _builder.persistence().addSingleFileStore().location(_tmpdir.getAbsolutePath()).storeAsBinary().build();
+ _manager.defineConfiguration(_name, config);
+ }
+ else
+ {
+ _manager.defineConfiguration(_name, _builder.build());
+ }
+ _cache = _manager.getCache(_name);
+ }
+
+
+ public void teardown () throws Exception
+ {
+ _manager.removeCache(_name);
+ if (_useFileStore)
+ {
+ if (_tmpdir != null)
+ {
+ IO.delete(_tmpdir);
+ }
+ }
+ }
+}
diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/InvalidationSessionTest.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/InvalidationSessionTest.java
new file mode 100644
index 0000000000..44123a590d
--- /dev/null
+++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/InvalidationSessionTest.java
@@ -0,0 +1,116 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2015 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 org.eclipse.jetty.server.SessionManager;
+import org.eclipse.jetty.session.infinispan.InfinispanSessionIdManager;
+import org.eclipse.jetty.session.infinispan.InfinispanSessionManager;
+import org.eclipse.jetty.util.IO;
+import org.infinispan.Cache;
+import org.infinispan.configuration.cache.Configuration;
+import org.infinispan.configuration.cache.ConfigurationBuilder;
+import org.infinispan.manager.DefaultCacheManager;
+import org.infinispan.manager.EmbeddedCacheManager;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+/**
+ * InvalidationSessionTest
+ *
+ *
+ */
+public class InvalidationSessionTest extends AbstractInvalidationSessionTest
+{
+
+ public static InfinispanTestSupport __testSupport;
+ public static long __staleSec = 3L;
+
+
+
+ @BeforeClass
+ public static void setup () throws Exception
+ {
+ __testSupport = new InfinispanTestSupport();
+ __testSupport.setup();
+ }
+
+ @AfterClass
+ public static void teardown () throws Exception
+ {
+ __testSupport.teardown();
+ }
+
+ /**
+ * @see org.eclipse.jetty.server.session.AbstractInvalidationSessionTest#createServer(int)
+ */
+ @Override
+ public AbstractTestServer createServer(int port)
+ {
+ return new InfinispanTestSessionServer(port, __testSupport.getCache());
+
+// return new InfinispanTestSessionServer(port, __cache)
+// {
+//
+// @Override
+// public SessionManager newSessionManager()
+// {
+// InfinispanSessionManager sessionManager = new InfinispanSessionManager();
+// sessionManager.setSessionIdManager((InfinispanSessionIdManager)_sessionIdManager);
+// sessionManager.setStaleIntervalSec(__staleSec);
+// sessionManager.setCache(((InfinispanSessionIdManager)_sessionIdManager).getCache());
+// return sessionManager;
+// }
+// };
+ }
+
+
+
+
+ @Override
+ public void testInvalidation() throws Exception
+ {
+ super.testInvalidation();
+ }
+
+ /**
+ * @see org.eclipse.jetty.server.session.AbstractInvalidationSessionTest#pause()
+ */
+ @Override
+ public void pause()
+ {
+ //This test moves a session from node 1 to node 2, then invalidates the session back on node1. This
+ //should never happen with a decent load balancer.
+ //The infinispan session manager on node 2 will hold the session in local memory for a specific (configurable)
+ //amount of time. We've set the stale session time to 3 sec, so we need to pause for at least this long before making
+ //another request to node2
+
+ //that the node will re-load the session from the database and discover that it has gone.
+ try
+ {
+ Thread.sleep(2 * __staleSec * 1000);
+ }
+ catch (InterruptedException e)
+ {
+ }
+ }
+
+}
diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/LastAccessTimeTest.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/LastAccessTimeTest.java
new file mode 100644
index 0000000000..25c0ad2308
--- /dev/null
+++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/LastAccessTimeTest.java
@@ -0,0 +1,65 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2015 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 org.eclipse.jetty.util.IO;
+import org.infinispan.Cache;
+import org.infinispan.configuration.cache.Configuration;
+import org.infinispan.configuration.cache.ConfigurationBuilder;
+import org.infinispan.manager.DefaultCacheManager;
+import org.infinispan.manager.EmbeddedCacheManager;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+public class LastAccessTimeTest extends AbstractLastAccessTimeTest
+{
+ 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
+ {
+ __testSupport.teardown();
+ }
+
+
+ @Override
+ public AbstractTestServer createServer(int port, int max, int scavenge)
+ {
+ return new InfinispanTestSessionServer(port, max, scavenge, __testSupport.getCache());
+ }
+
+ @Override
+ public void testLastAccessTime() throws Exception
+ {
+ super.testLastAccessTime();
+ }
+
+
+}
diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/LocalSessionScavengingTest.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/LocalSessionScavengingTest.java
new file mode 100644
index 0000000000..58e17de60c
--- /dev/null
+++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/LocalSessionScavengingTest.java
@@ -0,0 +1,59 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+
+package org.eclipse.jetty.server.session;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+/**
+ * LocalSessionScavengingTest
+ *
+ *
+ */
+public class LocalSessionScavengingTest extends AbstractLocalSessionScavengingTest
+{
+
+ 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
+ {
+ __testSupport.teardown();
+ }
+
+
+ /**
+ * @see org.eclipse.jetty.server.session.AbstractLocalSessionScavengingTest#createServer(int, int, int)
+ */
+ @Override
+ public AbstractTestServer createServer(int port, int max, int scavenge)
+ {
+ return new InfinispanTestSessionServer(port, max, scavenge, __testSupport.getCache());
+ }
+
+}
diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/NewSessionTest.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/NewSessionTest.java
new file mode 100644
index 0000000000..afdfe667a1
--- /dev/null
+++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/NewSessionTest.java
@@ -0,0 +1,66 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+
+package org.eclipse.jetty.server.session;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+/**
+ * NewSessionTest
+ *
+ *
+ */
+public class NewSessionTest extends AbstractNewSessionTest
+{
+
+ 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.AbstractNewSessionTest#createServer(int, int, int)
+ */
+ @Override
+ public AbstractTestServer createServer(int port, int max, int scavenge)
+ {
+ return new InfinispanTestSessionServer(port, max, scavenge, __testSupport.getCache());
+ }
+
+
+ @Override
+ public void testNewSession() throws Exception
+ {
+ super.testNewSession();
+ }
+
+
+}
diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/ReentrantRequestSessionTest.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/ReentrantRequestSessionTest.java
new file mode 100644
index 0000000000..3edd429cf5
--- /dev/null
+++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/ReentrantRequestSessionTest.java
@@ -0,0 +1,64 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+
+package org.eclipse.jetty.server.session;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+/**
+ * ReentrantRequestSessionTest
+ *
+ *
+ */
+public class ReentrantRequestSessionTest extends AbstractReentrantRequestSessionTest
+{
+ 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.AbstractReentrantRequestSessionTest#createServer(int)
+ */
+ @Override
+ public AbstractTestServer createServer(int port)
+ {
+ return new InfinispanTestSessionServer(port, __testSupport.getCache());
+ }
+
+ @Override
+ public void testReentrantRequestSession() throws Exception
+ {
+ super.testReentrantRequestSession();
+ }
+
+
+}
diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/RemoveSessionTest.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/RemoveSessionTest.java
new file mode 100644
index 0000000000..ebb534c27f
--- /dev/null
+++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/RemoveSessionTest.java
@@ -0,0 +1,58 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.server.session;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class RemoveSessionTest extends AbstractRemoveSessionTest
+{
+
+ 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();
+ }
+
+
+ @Override
+ public AbstractTestServer createServer(int port, int max, int scavenge)
+ {
+ InfinispanTestSessionServer s = new InfinispanTestSessionServer(port, max, scavenge, __testSupport.getCache());
+ return s;
+ }
+
+ @Test
+ public void testRemoveSession() throws Exception
+ {
+ super.testRemoveSession();
+ }
+
+}
diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/SessionExpiryTest.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/SessionExpiryTest.java
new file mode 100644
index 0000000000..56f6fe5ac1
--- /dev/null
+++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/SessionExpiryTest.java
@@ -0,0 +1,70 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+
+package org.eclipse.jetty.server.session;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+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();
+ }
+
+ @Override
+ public AbstractTestServer createServer(int port, int max, int scavenge)
+ {
+ InfinispanTestSessionServer server = new InfinispanTestSessionServer(port, max, scavenge, __testSupport.getCache());
+ return server;
+ }
+
+ @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.
+ }
+}
diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/SessionInvalidateAndCreateTest.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/SessionInvalidateAndCreateTest.java
new file mode 100644
index 0000000000..766d964d6b
--- /dev/null
+++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/SessionInvalidateAndCreateTest.java
@@ -0,0 +1,66 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+
+package org.eclipse.jetty.server.session;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+/**
+ * SessionInvalidateAndCreateTest
+ *
+ *
+ */
+public class SessionInvalidateAndCreateTest extends AbstractSessionInvalidateAndCreateTest
+{
+ 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.AbstractSessionInvalidateAndCreateTest#createServer(int, int, int)
+ */
+ @Override
+ public AbstractTestServer createServer(int port, int max, int scavenge)
+ {
+ return new InfinispanTestSessionServer(port, max, scavenge, __testSupport.getCache());
+ }
+
+ @Override
+ public void testSessionScavenge() throws Exception
+ {
+ super.testSessionScavenge();
+ }
+
+
+
+}
diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/SessionMigrationTest.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/SessionMigrationTest.java
new file mode 100644
index 0000000000..b327c4c7e5
--- /dev/null
+++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/SessionMigrationTest.java
@@ -0,0 +1,64 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+
+package org.eclipse.jetty.server.session;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+/**
+ * SessionMigrationTest
+ *
+ *
+ */
+public class SessionMigrationTest extends AbstractSessionMigrationTest
+{
+
+ 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.AbstractSessionMigrationTest#createServer(int)
+ */
+ @Override
+ public AbstractTestServer createServer(int port)
+ {
+ return new InfinispanTestSessionServer(port, __testSupport.getCache());
+ }
+
+ @Override
+ public void testSessionMigration() throws Exception
+ {
+ super.testSessionMigration();
+ }
+
+}
diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/SessionRenewTest.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/SessionRenewTest.java
new file mode 100644
index 0000000000..36de28037a
--- /dev/null
+++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/SessionRenewTest.java
@@ -0,0 +1,67 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+
+package org.eclipse.jetty.server.session;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * SessionRenewTest
+ *
+ *
+ */
+public class SessionRenewTest extends AbstractSessionRenewTest
+{
+
+ 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.AbstractSessionRenewTest#createServer(int, int, int)
+ */
+ @Override
+ public AbstractTestServer createServer(int port, int max, int scavenge)
+ {
+ return new InfinispanTestSessionServer(port, max, scavenge, __testSupport.getCache());
+ }
+
+ @Test
+ public void testSessionRenewal() throws Exception
+ {
+ super.testSessionRenewal();
+ }
+
+
+}
diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/JdbcTestServer.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/JdbcTestServer.java
index ad0a6921fa..5b55861707 100644
--- a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/JdbcTestServer.java
+++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/JdbcTestServer.java
@@ -76,14 +76,14 @@ public class JdbcTestServer extends AbstractTestServer
* @see org.eclipse.jetty.server.session.AbstractTestServer#newSessionIdManager(String)
*/
@Override
- public SessionIdManager newSessionIdManager(String config)
+ public SessionIdManager newSessionIdManager(Object config)
{
synchronized(JdbcTestServer.class)
{
JDBCSessionIdManager idManager = new JDBCSessionIdManager(_server);
idManager.setScavengeInterval(_scavengePeriod);
idManager.setWorkerName("w"+(__workers++));
- idManager.setDriverInfo(DRIVER_CLASS, (config==null?DEFAULT_CONNECTION_URL:config));
+ idManager.setDriverInfo(DRIVER_CLASS, (config==null?DEFAULT_CONNECTION_URL:(String)config));
JDBCSessionIdManager.SessionIdTableSchema idTableSchema = new JDBCSessionIdManager.SessionIdTableSchema();
idTableSchema.setTableName("mysessionids");
idTableSchema.setIdColumn("myid");
diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SessionExpiryTest.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SessionExpiryTest.java
index 49f4d72ae2..5177b93987 100644
--- a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SessionExpiryTest.java
+++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SessionExpiryTest.java
@@ -18,23 +18,9 @@
package org.eclipse.jetty.server.session;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
import java.sql.DriverManager;
import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSessionEvent;
-import javax.servlet.http.HttpSessionListener;
-import org.eclipse.jetty.client.HttpClient;
-import org.eclipse.jetty.client.api.ContentResponse;
-import org.eclipse.jetty.client.api.Request;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.After;
import org.junit.Test;
@@ -47,22 +33,6 @@ import org.junit.Test;
public class SessionExpiryTest extends AbstractSessionExpiryTest
{
- public class TestHttpSessionListener implements HttpSessionListener
- {
- public List<String> createdSessions = new ArrayList<String>();
- public List<String> destroyedSessions = new ArrayList<String>();
-
- public void sessionDestroyed(HttpSessionEvent se)
- {
- destroyedSessions.add(se.getSession().getId());
- }
-
- public void sessionCreated(HttpSessionEvent se)
- {
- createdSessions.add(se.getSession().getId());
- }
- };
-
/**
* @see org.eclipse.jetty.server.session.AbstractSessionExpiryTest#createServer(int, int, int)
*/
@@ -75,70 +45,9 @@ public class SessionExpiryTest extends AbstractSessionExpiryTest
@Test
public void testSessionExpiry() throws Exception
{
-
-
- String contextPath = "";
- String servletMapping = "/server";
- int inactivePeriod = 2;
- int scavengePeriod = 1;
- AbstractTestServer server1 = createServer(0, inactivePeriod, scavengePeriod);
- TestServlet servlet = new TestServlet();
- ServletHolder holder = new ServletHolder(servlet);
- ServletContextHandler context = server1.addContext(contextPath);
- context.addServlet(holder, servletMapping);
- TestHttpSessionListener listener = new TestHttpSessionListener();
-
- context.getSessionHandler().addEventListener(listener);
-
- server1.start();
- int port1 = server1.getPort();
-
- try
- {
- HttpClient client = new HttpClient();
- client.start();
- String url = "http://localhost:" + port1 + contextPath + servletMapping;
-
- //make a request to set up a session on the server
- ContentResponse response1 = client.GET(url + "?action=init");
- assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
- String sessionCookie = response1.getHeaders().get("Set-Cookie");
- assertTrue(sessionCookie != null);
- // Mangle the cookie, replacing Path with $Path, etc.
- sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
-
- String sessionId = extractSessionId(sessionCookie);
-
- assertTrue(listener.createdSessions.contains(sessionId));
- //now stop the server
- server1.stop();
-
- //and wait until the expiry time has passed
- pause(inactivePeriod);
-
- //restart the server
- server1.start();
-
- port1 = server1.getPort();
- url = "http://localhost:" + port1 + contextPath + servletMapping;
-
- //make another request, the session should have expired
- Request request = client.newRequest(url + "?action=test");
- request.getHeaders().add("Cookie", sessionCookie);
- ContentResponse response2 = request.send();
- assertEquals(HttpServletResponse.SC_OK,response2.getStatus());
-
- //and wait until the expiry time has passed
- pause(inactivePeriod);
-
- assertTrue(listener.destroyedSessions.contains(sessionId));
- }
- finally
- {
- server1.stop();
- }
+ super.testSessionExpiry();
}
-
+
@@ -149,24 +58,7 @@ public class SessionExpiryTest extends AbstractSessionExpiryTest
super.testSessionNotExpired();
}
-
-
- public String extractSessionId (String sessionCookie)
- {
- if (sessionCookie == null)
- return null;
- sessionCookie = sessionCookie.trim();
- int i = sessionCookie.indexOf(';');
- if (i >= 0)
- sessionCookie = sessionCookie.substring(0,i);
- if (sessionCookie.startsWith("JSESSIONID"))
- sessionCookie = sessionCookie.substring("JSESSIONID=".length());
- i = sessionCookie.indexOf('.');
- if (i >=0)
- sessionCookie = sessionCookie.substring(0,i);
- return sessionCookie;
- }
-
+
@After
diff --git a/tests/test-sessions/test-mongodb-sessions/src/test/java/org/eclipse/jetty/nosql/mongodb/MongoTestServer.java b/tests/test-sessions/test-mongodb-sessions/src/test/java/org/eclipse/jetty/nosql/mongodb/MongoTestServer.java
index 4ef587c257..ead992ca73 100644
--- a/tests/test-sessions/test-mongodb-sessions/src/test/java/org/eclipse/jetty/nosql/mongodb/MongoTestServer.java
+++ b/tests/test-sessions/test-mongodb-sessions/src/test/java/org/eclipse/jetty/nosql/mongodb/MongoTestServer.java
@@ -50,7 +50,7 @@ public class MongoTestServer extends AbstractTestServer
_saveAllAttributes = saveAllAttributes;
}
- public SessionIdManager newSessionIdManager(String config)
+ public SessionIdManager newSessionIdManager(Object config)
{
try
{
diff --git a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractRemoveSessionTest.java b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractRemoveSessionTest.java
index f83a8cc3e3..c344d72530 100644
--- a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractRemoveSessionTest.java
+++ b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractRemoveSessionTest.java
@@ -82,8 +82,7 @@ public abstract class AbstractRemoveSessionTest
assertTrue(testListener.isDestroyed());
- // The session is not there anymore, but we present an old cookie
- // The server creates a new session, we must ensure we released all locks
+ // The session is not there anymore, even if we present an old cookie
request = client.newRequest("http://localhost:" + port + contextPath + servletMapping + "?action=check");
request.header("Cookie", sessionCookie);
response = request.send();
diff --git a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionCookieTest.java b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionCookieTest.java
index e04e15cef2..b79a0a33ac 100644
--- a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionCookieTest.java
+++ b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionCookieTest.java
@@ -39,7 +39,7 @@ import org.junit.Ignore;
import org.junit.Test;
/**
- * AbstractNewSessionTest
+ * AbstractSessionCookieTest
*/
public abstract class AbstractSessionCookieTest
{
diff --git a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionExpiryTest.java b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionExpiryTest.java
index 8f5353e2a1..5c11f8b35c 100644
--- a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionExpiryTest.java
+++ b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionExpiryTest.java
@@ -22,16 +22,21 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpSessionEvent;
+import javax.servlet.http.HttpSessionListener;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request;
+import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.Test;
@@ -50,6 +55,23 @@ public abstract class AbstractSessionExpiryTest
e.printStackTrace();
}
}
+
+ public class TestHttpSessionListener implements HttpSessionListener
+ {
+ public List<String> createdSessions = new ArrayList<String>();
+ public List<String> destroyedSessions = new ArrayList<String>();
+
+ public void sessionDestroyed(HttpSessionEvent se)
+ {
+ destroyedSessions.add(se.getSession().getId());
+ }
+
+ public void sessionCreated(HttpSessionEvent se)
+ {
+ createdSessions.add(se.getSession().getId());
+ }
+ };
+
@Test
public void testSessionNotExpired() throws Exception
@@ -101,18 +123,26 @@ public abstract class AbstractSessionExpiryTest
server1.stop();
}
}
+
@Test
public void testSessionExpiry() throws Exception
{
+
+
String contextPath = "";
String servletMapping = "/server";
int inactivePeriod = 2;
- int scavengePeriod = 10;
+ int scavengePeriod = 1;
AbstractTestServer server1 = createServer(0, inactivePeriod, scavengePeriod);
TestServlet servlet = new TestServlet();
ServletHolder holder = new ServletHolder(servlet);
- server1.addContext(contextPath).addServlet(holder, servletMapping);
+ ServletContextHandler context = server1.addContext(contextPath);
+ context.addServlet(holder, servletMapping);
+ TestHttpSessionListener listener = new TestHttpSessionListener();
+
+ context.getSessionHandler().addEventListener(listener);
+
server1.start();
int port1 = server1.getPort();
@@ -129,7 +159,11 @@ public abstract class AbstractSessionExpiryTest
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
-
+
+ String sessionId = AbstractTestServer.extractSessionId(sessionCookie);
+
+ verifySessionCreated(listener,sessionId);
+
//now stop the server
server1.stop();
@@ -138,6 +172,7 @@ public abstract class AbstractSessionExpiryTest
//restart the server
server1.start();
+
port1 = server1.getPort();
url = "http://localhost:" + port1 + contextPath + servletMapping;
@@ -146,12 +181,27 @@ public abstract class AbstractSessionExpiryTest
request.getHeaders().add("Cookie", sessionCookie);
ContentResponse response2 = request.send();
assertEquals(HttpServletResponse.SC_OK,response2.getStatus());
+
+ //and wait until the expiry time has passed
+ pause(inactivePeriod);
+
+ verifySessionDestroyed (listener, sessionId);
}
finally
{
server1.stop();
- }
+ }
+ }
+ public void verifySessionCreated (TestHttpSessionListener listener, String sessionId)
+ {
+ assertTrue(listener.createdSessions.contains(sessionId));
}
+ public void verifySessionDestroyed (TestHttpSessionListener listener, String sessionId)
+ {
+ assertTrue (listener.destroyedSessions.contains(sessionId));
+ }
+
+
public static class TestServlet extends HttpServlet
{
diff --git a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionValueSavingTest.java b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionValueSavingTest.java
index d62e3f7e92..8b0851b00c 100644
--- a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionValueSavingTest.java
+++ b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionValueSavingTest.java
@@ -37,7 +37,7 @@ import org.junit.Test;
/**
- * AbstractLastAccessTimeTest
+ * AbstractSessionValueSavingTest
*/
public abstract class AbstractSessionValueSavingTest
{
diff --git a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractTestServer.java b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractTestServer.java
index 329d6b8fa5..789f6b28d1 100644
--- a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractTestServer.java
+++ b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractTestServer.java
@@ -34,17 +34,38 @@ import org.eclipse.jetty.webapp.WebAppContext;
*/
public abstract class AbstractTestServer
{
+ public static int DEFAULT_MAX_INACTIVE = 30;
+ public static int DEFAULT_SCAVENGE = 10;
+
protected final Server _server;
protected final int _maxInactivePeriod;
protected final int _scavengePeriod;
protected final ContextHandlerCollection _contexts;
protected SessionIdManager _sessionIdManager;
+
+
+ public static String extractSessionId (String sessionCookie)
+ {
+ if (sessionCookie == null)
+ return null;
+ sessionCookie = sessionCookie.trim();
+ int i = sessionCookie.indexOf(';');
+ if (i >= 0)
+ sessionCookie = sessionCookie.substring(0,i);
+ if (sessionCookie.startsWith("JSESSIONID"))
+ sessionCookie = sessionCookie.substring("JSESSIONID=".length());
+ i = sessionCookie.indexOf('.');
+ if (i >=0)
+ sessionCookie = sessionCookie.substring(0,i);
+ return sessionCookie;
+ }
+
public AbstractTestServer(int port)
{
- this(port, 30, 10);
+ this(port, DEFAULT_MAX_INACTIVE, DEFAULT_SCAVENGE);
}
public AbstractTestServer(int port, int maxInactivePeriod, int scavengePeriod)
@@ -52,7 +73,7 @@ public abstract class AbstractTestServer
this (port, maxInactivePeriod, scavengePeriod, null);
}
- public AbstractTestServer(int port, int maxInactivePeriod, int scavengePeriod, String sessionIdMgrConfig)
+ public AbstractTestServer(int port, int maxInactivePeriod, int scavengePeriod, Object sessionIdMgrConfig)
{
_server = new Server(port);
_maxInactivePeriod = maxInactivePeriod;
@@ -64,7 +85,7 @@ public abstract class AbstractTestServer
- public abstract SessionIdManager newSessionIdManager(String config);
+ public abstract SessionIdManager newSessionIdManager(Object config);
public abstract SessionManager newSessionManager();
public abstract SessionHandler newSessionHandler(SessionManager sessionManager);

Back to the top