geode-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jensde...@apache.org
Subject [08/24] incubator-geode git commit: GEODE-14: Move GemFire Sessions module and relocate all packages to 'internal'
Date Tue, 29 Dec 2015 21:11:02 GMT
GEODE-14: Move GemFire Sessions module and relocate all packages to 'internal'


Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/92ee6a79
Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/92ee6a79
Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/92ee6a79

Branch: refs/heads/feature/GEODE-14
Commit: 92ee6a7917e2fc37586984ec295a7198d4eb088d
Parents: ed3be77
Author: Jens Deppe <jdeppe@pivotal.io>
Authored: Mon Dec 28 07:46:37 2015 -0800
Committer: Jens Deppe <jdeppe@pivotal.io>
Committed: Mon Dec 28 07:46:37 2015 -0800

----------------------------------------------------------------------
 extensions/gemfire-modules-session/build.gradle |    4 +
 extensions/gemfire-modules-session/pom.xml      |   46 +
 .../release/bin/cacheserver.bat                 |   33 +
 .../release/bin/cacheserver.sh                  |   33 +
 .../release/bin/gemfire.bat                     |   23 +
 .../release/bin/gemfire.sh                      |   41 +
 .../release/bin/setenv.properties               |    6 +
 .../release/conf/cache-client.xml               |   25 +
 .../release/conf/cache-peer.xml                 |   33 +
 .../release/conf/cache-server.xml               |   59 +
 .../internal/common/AbstractSessionCache.java   |   92 ++
 .../session/internal/common/CacheProperty.java  |   56 +
 .../common/ClientServerSessionCache.java        |  176 ++
 .../internal/common/PeerToPeerSessionCache.java |  174 ++
 .../session/internal/common/SessionCache.java   |   59 +
 .../common/SessionExpirationCacheListener.java  |   43 +
 .../session/internal/filter/Constants.java      |   14 +
 .../session/internal/filter/ContextManager.java |   95 ++
 .../internal/filter/DummySessionManager.java    |  127 ++
 .../internal/filter/GemfireHttpSession.java     |  517 ++++++
 .../filter/GemfireSessionException.java         |   36 +
 .../internal/filter/GemfireSessionManager.java  |  502 ++++++
 .../internal/filter/ListenerEventType.java      |   70 +
 .../session/internal/filter/SessionManager.java |  101 ++
 .../AbstractDeltaSessionAttributes.java         |   97 ++
 .../attributes/AbstractSessionAttributes.java   |  179 ++
 .../internal/filter/attributes/DeltaEvent.java  |  109 ++
 .../DeltaQueuedSessionAttributes.java           |   84 +
 .../attributes/DeltaSessionAttributes.java      |   65 +
 .../attributes/ImmediateSessionAttributes.java  |   58 +
 .../attributes/QueuedSessionAttributes.java     |   55 +
 .../filter/attributes/SessionAttributes.java    |  111 ++
 .../filter/util/NamedThreadFactory.java         |   59 +
 .../filter/util/ThreadLocalSession.java         |   29 +
 .../internal/filter/util/TypeAwareMap.java      |   45 +
 .../session/internal/jmx/SessionStatistics.java |   69 +
 .../internal/jmx/SessionStatisticsMXBean.java   |   14 +
 .../src/test/resources/log4j.properties         |   12 +
 .../session/filter/SessionCachingFilter.java    |  639 -------
 .../modules/session/filter/SessionListener.java |   41 -
 .../modules/session/installer/Installer.java    |    4 +-
 .../internal/filter/SessionCachingFilter.java   |  639 +++++++
 .../internal/filter/SessionListener.java        |   41 +
 .../session/filter/AbstractListener.java        |   52 -
 .../modules/session/filter/Callback.java        |   17 -
 .../modules/session/filter/CallbackServlet.java |   88 -
 .../modules/session/filter/CommonTests.java     |  583 -------
 .../session/filter/GemfireCacheTest.java        |   46 -
 .../session/filter/GemfireLocalCacheTest.java   |   67 -
 .../HttpSessionAttributeListenerImpl.java       |   37 -
 .../filter/HttpSessionBindingListenerImpl.java  |   40 -
 .../session/filter/HttpSessionListenerImpl.java |   35 -
 .../session/filter/RendezvousManager.java       |   37 -
 .../ServletRequestAttributeListenerImpl.java    |   42 -
 .../filter/ServletRequestListenerImpl.java      |   36 -
 .../session/filter/SessionTestSuite1.java       |   69 -
 .../session/filter/SessionTestSuite2.java       |   68 -
 .../session/filter/SessionUberSuite.java        |   40 -
 .../internal/filter/AbstractListener.java       |   52 +
 .../session/internal/filter/Callback.java       |   17 +
 .../internal/filter/CallbackServlet.java        |   88 +
 .../session/internal/filter/CommonTests.java    |  582 +++++++
 .../internal/filter/GemfireCacheTest.java       |   46 +
 .../internal/filter/GemfireLocalCacheTest.java  |   62 +
 .../HttpSessionAttributeListenerImpl.java       |   37 +
 .../filter/HttpSessionBindingListenerImpl.java  |   40 +
 .../filter/HttpSessionListenerImpl.java         |   33 +
 .../internal/filter/RendezvousManager.java      |   37 +
 .../ServletRequestAttributeListenerImpl.java    |   40 +
 .../filter/ServletRequestListenerImpl.java      |   34 +
 .../internal/filter/SessionTestSuite1.java      |   69 +
 .../internal/filter/SessionTestSuite2.java      |   68 +
 .../internal/filter/SessionUberSuite.java       |   30 +
 .../session/filter/AbstractListener.java        |   50 -
 .../modules/session/filter/BasicServlet.java    |   46 -
 .../modules/session/filter/Callback.java        |   26 -
 .../session/filter/HttpSessionListenerImpl.java |   39 -
 .../filter/HttpSessionListenerImpl2.java        |   39 -
 .../modules/session/filter/IntegrationTest.java | 1552 ------------------
 .../modules/session/filter/MyServletTester.java |   33 -
 .../filter/ServletContextListenerImpl.java      |   48 -
 .../internal/filter/AbstractListener.java       |   50 +
 .../session/internal/filter/BasicServlet.java   |   46 +
 .../session/internal/filter/Callback.java       |   26 +
 .../filter/HttpSessionListenerImpl.java         |   39 +
 .../filter/HttpSessionListenerImpl2.java        |   39 +
 .../internal/filter/IntegrationTest.java        | 1552 ++++++++++++++++++
 .../internal/filter/MyServletTester.java        |   33 +
 .../filter/ServletContextListenerImpl.java      |   46 +
 modules/gemfire-modules-session/build.gradle    |    3 -
 modules/gemfire-modules-session/pom.xml         |   46 -
 modules/gemfire-modules-session/profiles.xml    |   18 -
 .../release/bin/cacheserver.bat                 |   33 -
 .../release/bin/cacheserver.sh                  |   33 -
 .../release/bin/gemfire.bat                     |   23 -
 .../release/bin/gemfire.sh                      |   41 -
 .../release/bin/setenv.properties               |    6 -
 .../release/conf/cache-client.xml               |   25 -
 .../release/conf/cache-peer.xml                 |   33 -
 .../release/conf/cache-server.xml               |   59 -
 .../session/common/AbstractSessionCache.java    |   92 --
 .../modules/session/common/CacheProperty.java   |   56 -
 .../common/ClientServerSessionCache.java        |  176 --
 .../session/common/PeerToPeerSessionCache.java  |  174 --
 .../modules/session/common/SessionCache.java    |   59 -
 .../common/SessionExpirationCacheListener.java  |   43 -
 .../modules/session/filter/Constants.java       |   14 -
 .../modules/session/filter/ContextManager.java  |   95 --
 .../session/filter/DummySessionManager.java     |  128 --
 .../session/filter/GemfireHttpSession.java      |  517 ------
 .../session/filter/GemfireSessionException.java |   36 -
 .../session/filter/GemfireSessionManager.java   |  503 ------
 .../session/filter/ListenerEventType.java       |   70 -
 .../modules/session/filter/SessionManager.java  |  101 --
 .../AbstractDeltaSessionAttributes.java         |   97 --
 .../attributes/AbstractSessionAttributes.java   |  179 --
 .../session/filter/attributes/DeltaEvent.java   |  109 --
 .../DeltaQueuedSessionAttributes.java           |   84 -
 .../attributes/DeltaSessionAttributes.java      |   65 -
 .../attributes/ImmediateSessionAttributes.java  |   63 -
 .../attributes/QueuedSessionAttributes.java     |   60 -
 .../filter/attributes/SessionAttributes.java    |  111 --
 .../session/filter/util/NamedThreadFactory.java |   59 -
 .../session/filter/util/ThreadLocalSession.java |   29 -
 .../session/filter/util/TypeAwareMap.java       |   45 -
 .../modules/session/jmx/SessionStatistics.java  |   69 -
 .../session/jmx/SessionStatisticsMXBean.java    |   14 -
 .../src/test/resources/log4j.properties         |   12 -
 settings.gradle                                 |    1 +
 129 files changed, 7100 insertions(+), 7152 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/92ee6a79/extensions/gemfire-modules-session/build.gradle
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/build.gradle b/extensions/gemfire-modules-session/build.gradle
new file mode 100644
index 0000000..156f204
--- /dev/null
+++ b/extensions/gemfire-modules-session/build.gradle
@@ -0,0 +1,4 @@
+dependencies {
+  compile project(':extensions/gemfire-modules')
+  compile project(':gemfire-core')
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/92ee6a79/extensions/gemfire-modules-session/pom.xml
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/pom.xml b/extensions/gemfire-modules-session/pom.xml
new file mode 100644
index 0000000..b274ab3
--- /dev/null
+++ b/extensions/gemfire-modules-session/pom.xml
@@ -0,0 +1,46 @@
+<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>
+  <groupId>com.gemstone</groupId>
+  <artifactId>gemfire-modules-session</artifactId>
+  <packaging>jar</packaging>
+  <version>${gemfire.modules.version}</version>
+  <url>http://maven.apache.org</url>
+  <name>gemfire-modules-session</name>
+
+  <parent>
+    <groupId>com.gemstone</groupId>
+    <artifactId>gemfire-modules-parent</artifactId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>servlet-api</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>com.gemstone</groupId>
+      <artifactId>gemfire-modules</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>com.gemstone.gemfire</groupId>
+      <artifactId>gemfire</artifactId>
+    </dependency>
+
+    <!--<dependency>-->
+      <!--<groupId>org.slf4j</groupId>-->
+      <!--<artifactId>slf4j-log4j12</artifactId>-->
+      <!--<scope>compile</scope>-->
+    <!--</dependency>-->
+
+  </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/92ee6a79/extensions/gemfire-modules-session/release/bin/cacheserver.bat
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/release/bin/cacheserver.bat b/extensions/gemfire-modules-session/release/bin/cacheserver.bat
new file mode 100755
index 0000000..2632dc7
--- /dev/null
+++ b/extensions/gemfire-modules-session/release/bin/cacheserver.bat
@@ -0,0 +1,33 @@
+@setlocal enableextensions
+@set scriptdir=%~dp0
+@set gf=%scriptdir:\bin\=%
+@if exist "%gf%\lib\gemfire.jar" @goto gfok
+@echo Could not determine GEMFIRE location
+@verify other 2>nul
+@goto done
+:gfok
+
+@REM Initialize classpath
+
+@REM Add GemFire classes
+@set GEMFIRE_JARS=%gf%/lib/gemfire.jar;%gf%/lib/antlr.jar;%gf%/lib/mail.jar
+
+@REM Add Tomcat classes
+@set GEMFIRE_JARS=%GEMFIRE_JARS%;%gf%/lib/servlet-api.jar;%gf%/lib/catalina.jar;%gf%/lib/${artifact.artifactId}-${artifact.version}.jar;%gf%/bin/tomcat-juli.jar
+
+@REM Add conf directory
+@set GEMFIRE_JARS=%GEMFIRE_JARS%;%gf%/conf
+
+@if defined CLASSPATH set GEMFIRE_JARS=%GEMFIRE_JARS%;%CLASSPATH%
+
+@if not defined GF_JAVA (
+@REM %GF_JAVA% is not defined, assume it is on the PATH
+@set GF_JAVA=java
+)
+
+@"%GF_JAVA%" %JAVA_ARGS% -classpath "%GEMFIRE_JARS%" com.gemstone.gemfire.internal.cache.CacheServerLauncher %*
+:done
+@set scriptdir=
+@set gf=
+@set GEMFIRE_JARS=
+

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/92ee6a79/extensions/gemfire-modules-session/release/bin/cacheserver.sh
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/release/bin/cacheserver.sh b/extensions/gemfire-modules-session/release/bin/cacheserver.sh
new file mode 100755
index 0000000..e395001
--- /dev/null
+++ b/extensions/gemfire-modules-session/release/bin/cacheserver.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+# Set GEMFIRE to the product toplevel directory
+GEMFIRE=`dirname $0`
+OLDPWD=$PWD
+cd $GEMFIRE
+GEMFIRE=`dirname $PWD`
+cd $OLDPWD
+
+if [ "x$WINDIR" != "x" ]; then
+  echo "ERROR: The variable WINDIR is set indicating this script is running in a Windows OS, please use the .bat file version instead."
+  exit 1
+fi
+
+GEMFIRE_JARS=$GEMFIRE/lib/gemfire-[0-9]*.jar
+if [ ! -f ${GEMFIRE_JARS} ]; then
+  echo "ERROR: Could not determine GEMFIRE location."
+  exit 1
+fi
+
+# Initialize classpath
+GEMFIRE_JARS=$GEMFIRE_JARS:$GEMFIRE/lib/gemfire-modules-[0-9]*
+GEMFIRE_JARS=$GEMFIRE_JARS:$GEMFIRE/lib/servlet-api-[0-9]*
+GEMFIRE_JARS=$GEMFIRE_JARS:$GEMFIRE/lib/slf4j-api-[0-9]*
+GEMFIRE_JARS=$GEMFIRE_JARS:$GEMFIRE/lib/slf4j-jdk14-[0-9]*
+
+# Add configuration
+GEMFIRE_JARS=$GEMFIRE_JARS:$GEMFIRE/conf
+
+if [ "x$CLASSPATH" != "x" ]; then
+  GEMFIRE_JARS=$GEMFIRE_JARS:$CLASSPATH
+fi
+
+${GF_JAVA:-java} ${JAVA_ARGS} -classpath ${GEMFIRE_JARS} com.gemstone.gemfire.internal.cache.CacheServerLauncher "$@"

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/92ee6a79/extensions/gemfire-modules-session/release/bin/gemfire.bat
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/release/bin/gemfire.bat b/extensions/gemfire-modules-session/release/bin/gemfire.bat
new file mode 100755
index 0000000..96d2564
--- /dev/null
+++ b/extensions/gemfire-modules-session/release/bin/gemfire.bat
@@ -0,0 +1,23 @@
+@setlocal enableextensions
+@set scriptdir=%~dp0
+@set gf=%scriptdir:\bin\=%
+@if exist "%gf%\lib\gemfire.jar" @goto gfok
+@echo Could not determine GEMFIRE location
+@verify other 2>nul
+@goto done
+:gfok
+
+@set GEMFIRE_JARS=%gf%/lib/gemfire.jar;%gf%/lib/antlr.jar;%gf%/lib/mail.jar
+@if defined CLASSPATH set GEMFIRE_JARS=%GEMFIRE_JARS%;%CLASSPATH%
+
+@if not defined GF_JAVA (
+@REM %GF_JAVA% is not defined, assume it is on the PATH
+@set GF_JAVA=java
+)
+
+@"%GF_JAVA%" %JAVA_ARGS% -classpath "%GEMFIRE_JARS%" com.gemstone.gemfire.internal.SystemAdmin %*
+:done
+@set scriptdir=
+@set gf=
+@set GEMFIRE_JARS=
+

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/92ee6a79/extensions/gemfire-modules-session/release/bin/gemfire.sh
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/release/bin/gemfire.sh b/extensions/gemfire-modules-session/release/bin/gemfire.sh
new file mode 100755
index 0000000..fa5f4cd
--- /dev/null
+++ b/extensions/gemfire-modules-session/release/bin/gemfire.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+# Set GEMFIRE to the product toplevel directory
+GEMFIRE=`dirname $0`
+OLDPWD=$PWD
+cd $GEMFIRE
+GEMFIRE=`dirname $PWD`
+cd $OLDPWD
+
+if [ "x$WINDIR" != "x" ]; then
+  echo "ERROR: The variable WINDIR is set indicating this script is running in a Windows OS, please use the .bat file version instead."
+  exit 1
+fi
+
+if [ ! -f $GEMFIRE/lib/gemfire.jar ]; then
+  echo "ERROR: Could not determine GEMFIRE location."
+  exit 1
+fi
+
+GEMFIRE_JARS=$GEMFIRE/lib/gemfire.jar:$GEMFIRE/lib/antlr.jar
+
+if [ "x$CLASSPATH" != "x" ]; then
+  GEMFIRE_JARS=$GEMFIRE_JARS:$CLASSPATH
+fi
+
+# Command line args that start with -J will be passed to the java vm in JARGS.
+# See java --help for a listing of valid vm args.
+# Example: -J-Xmx1g sets the max heap size to 1 gigabyte.
+
+JARGS=
+GEMFIRE_ARGS=
+for i in "$@"
+do
+  if [ "-J" == "${i:0:2}" ]
+  then
+    JARGS="${JARGS} \"${i#-J}\""
+  else
+    GEMFIRE_ARGS="${GEMFIRE_ARGS} \"${i}\""
+  fi
+done
+
+eval ${GF_JAVA:-java} ${JAVA_ARGS} ${JARGS} -classpath ${GEMFIRE_JARS} com.gemstone.gemfire.internal.SystemAdmin ${GEMFIRE_ARGS}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/92ee6a79/extensions/gemfire-modules-session/release/bin/setenv.properties
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/release/bin/setenv.properties b/extensions/gemfire-modules-session/release/bin/setenv.properties
new file mode 100644
index 0000000..fc8918b
--- /dev/null
+++ b/extensions/gemfire-modules-session/release/bin/setenv.properties
@@ -0,0 +1,6 @@
+java.opt.1=-Xms${initial.vm.heap.size.mb:512}M
+java.opt.2=-Xmx${maximum.vm.heap.size.mb:512}M
+java.opt.hotspot.1=-XX:+UseParNewGC
+java.opt.hotspot.2=-XX:+UseConcMarkSweepGC
+java.opt.hotspot.3=-XX:CMSInitiatingOccupancyFraction=${cms.initiating.heap.percentage:50}
+java.opt.j9.1=-Xgcpolicy:gencon
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/92ee6a79/extensions/gemfire-modules-session/release/conf/cache-client.xml
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/release/conf/cache-client.xml b/extensions/gemfire-modules-session/release/conf/cache-client.xml
new file mode 100755
index 0000000..c8444b2
--- /dev/null
+++ b/extensions/gemfire-modules-session/release/conf/cache-client.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE client-cache PUBLIC
+  "-//GemStone Systems, Inc.//GemFire Declarative Caching 6.5//EN"
+  "http://www.gemstone.com/dtd/cache6_6.dtd">
+  
+<client-cache>
+
+  <!-- The default pool connects to a cache server running on  localhost at
+       port 40404. To connect to a different server host and port, modify
+       the following pool server host and port. -->
+  <pool name="sessions" subscription-enabled="true">
+    <server host="localhost" port="40404"/>
+  </pool>
+
+  <!-- To configure the client to use a locator instead of a server, replace
+       the server pool above with the locator pool below and modify the locator
+       host and port as necessary. -->
+  <!--
+  <pool name="sessions" subscription-enabled="true">
+    <locator host="localhost" port="10334"/>
+  </pool>
+  -->
+  
+</client-cache>

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/92ee6a79/extensions/gemfire-modules-session/release/conf/cache-peer.xml
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/release/conf/cache-peer.xml b/extensions/gemfire-modules-session/release/conf/cache-peer.xml
new file mode 100755
index 0000000..1a49637
--- /dev/null
+++ b/extensions/gemfire-modules-session/release/conf/cache-peer.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE cache PUBLIC
+  "-//GemStone Systems, Inc.//GemFire Declarative Caching 6.5//EN"
+  "http://www.gemstone.com/dtd/cache6_6.dtd">
+  
+<cache>
+
+  <!-- Uncomment the following disk-store element to modify the default disk store directory -->
+  <!--
+  <disk-store name="DEFAULT">
+    <disk-dirs>
+      <disk-dir>/path/to/persistent/data</disk-dir>
+    </disk-dirs>
+  </disk-store>
+  -->
+
+  <!-- This is the definition of the default session region -->
+  <!--
+  <region name="gemfire_modules_sessions">
+    <region-attributes scope="distributed-ack" enable-gateway="false" data-policy="replicate" statistics-enabled="true">
+      <entry-idle-time>
+        <expiration-attributes timeout="0" action="invalidate">
+          <custom-expiry>
+            <class-name>com.gemstone.gemfire.modules.util.SessionCustomExpiry</class-name>
+          </custom-expiry>
+        </expiration-attributes>
+      </entry-idle-time>
+    </region-attributes>
+  </region>
+  -->
+  
+</cache>

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/92ee6a79/extensions/gemfire-modules-session/release/conf/cache-server.xml
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/release/conf/cache-server.xml b/extensions/gemfire-modules-session/release/conf/cache-server.xml
new file mode 100755
index 0000000..6ee2223
--- /dev/null
+++ b/extensions/gemfire-modules-session/release/conf/cache-server.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE cache PUBLIC
+  "-//GemStone Systems, Inc.//GemFire Declarative Caching 6.5//EN"
+  "http://www.gemstone.com/dtd/cache6_6.dtd">
+  
+<cache>
+
+  <!-- Uncomment the following gateway-hub element to create a gateway hub -->
+  <!--
+  <gateway-hub id="NY" port="11110">
+    <gateway id="LN">
+      <gateway-endpoint id="LN-1" host="localhost" port="22220"/>
+      <gateway-queue disk-store-name="NY_GATEWAY"/>
+    </gateway>
+  </gateway-hub>
+  -->
+
+  <!-- Uncomment the following cache-server element to modify the listen port -->
+  <!--
+  <cache-server port="44444"/>
+  -->
+
+  <!-- Uncomment the following disk-store element to modify the default disk store directory -->
+  <!--
+  <disk-store name="DEFAULT">
+    <disk-dirs>
+      <disk-dir>/path/to/persistent/data</disk-dir>
+    </disk-dirs>
+  </disk-store>
+  -->
+  
+  <!-- Uncomment the following disk-store element to create the NY_GATEWAY disk store
+       (for the gateway-hub element defined above) -->
+  <!--
+  <disk-store name="NY_GATEWAY">
+    <disk-dirs>
+      <disk-dir>/path/to/persistent/data</disk-dir>
+    </disk-dirs>
+  </disk-store>
+  -->
+  
+  <!-- This is the definition of the default session region -->
+  <!--
+  <region name="gemfire_modules_sessions">
+    <region-attributes enable-gateway="false" data-policy="partition" statistics-enabled="true">
+      <entry-idle-time>
+        <expiration-attributes timeout="0" action="invalidate">
+          <custom-expiry>
+            <class-name>com.gemstone.gemfire.modules.util.SessionCustomExpiry</class-name>
+          </custom-expiry>
+        </expiration-attributes>
+      </entry-idle-time>
+      <partition-attributes redundant-copies="1" total-num-buckets="113"/>
+    </region-attributes>
+  </region>
+  -->
+
+</cache>

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/92ee6a79/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/common/AbstractSessionCache.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/common/AbstractSessionCache.java b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/common/AbstractSessionCache.java
new file mode 100644
index 0000000..bc06465
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/common/AbstractSessionCache.java
@@ -0,0 +1,92 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.modules.session.internal.common;
+
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.modules.session.catalina.internal.DeltaSessionStatistics;
+import com.gemstone.gemfire.modules.session.internal.filter.util.TypeAwareMap;
+import com.gemstone.gemfire.modules.util.RegionConfiguration;
+
+import java.util.Map;
+import javax.servlet.http.HttpSession;
+
+public abstract class AbstractSessionCache implements SessionCache {
+
+  /**
+   * The sessionRegion is the <code>Region</code> that actually stores and
+   * replicates the <code>Session</code>s.
+   */
+  protected Region<String, HttpSession> sessionRegion;
+
+  /**
+   * The operatingRegion is the <code>Region</code> used to do HTTP operations.
+   * if local cache is enabled, then this will be the local <code>Region</code>;
+   * otherwise, it will be the session <code>Region</code>.
+   */
+  protected Region<String, HttpSession> operatingRegion;
+
+  protected Map<CacheProperty, Object> properties =
+      new TypeAwareMap<CacheProperty, Object>(CacheProperty.class);
+
+  protected DeltaSessionStatistics statistics;
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void stop() {
+    sessionRegion.close();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Region<String, HttpSession> getOperatingRegion() {
+    return this.operatingRegion;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Region<String, HttpSession> getSessionRegion() {
+    return this.sessionRegion;
+  }
+
+  protected void createStatistics() {
+    this.statistics =
+        new DeltaSessionStatistics(getCache().getDistributedSystem(),
+            (String) properties.get(CacheProperty.STATISTICS_NAME));
+  }
+
+  /**
+   * Build up a {@code RegionConfiguraton} object from parameters originally
+   * passed in as filter initialization parameters.
+   *
+   * @return a {@code RegionConfiguration} object
+   */
+  protected RegionConfiguration createRegionConfiguration() {
+    RegionConfiguration configuration = new RegionConfiguration();
+
+    configuration.setRegionName(
+        (String) properties.get(CacheProperty.REGION_NAME));
+    configuration.setRegionAttributesId(
+        (String) properties.get(CacheProperty.REGION_ATTRIBUTES_ID));
+
+    configuration.setEnableGatewayDeltaReplication(
+        (Boolean) properties.get(
+            CacheProperty.ENABLE_GATEWAY_DELTA_REPLICATION));
+    configuration.setEnableGatewayReplication(
+        (Boolean) properties.get(CacheProperty.ENABLE_GATEWAY_REPLICATION));
+    configuration.setEnableDebugListener(
+        (Boolean) properties.get(CacheProperty.ENABLE_DEBUG_LISTENER));
+
+    return configuration;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/92ee6a79/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/common/CacheProperty.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/common/CacheProperty.java b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/common/CacheProperty.java
new file mode 100644
index 0000000..5abd0b6
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/common/CacheProperty.java
@@ -0,0 +1,56 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+
+package com.gemstone.gemfire.modules.session.internal.common;
+
+/**
+ * Used to define cache properties
+ */
+public enum CacheProperty {
+
+  ENABLE_DEBUG_LISTENER(Boolean.class),
+
+  ENABLE_GATEWAY_REPLICATION(Boolean.class),
+
+  ENABLE_GATEWAY_DELTA_REPLICATION(Boolean.class),
+
+  ENABLE_LOCAL_CACHE(Boolean.class),
+
+  REGION_NAME(String.class),
+
+  REGION_ATTRIBUTES_ID(String.class),
+
+  STATISTICS_NAME(String.class),
+
+  /**
+   * This parameter can take the following values which match the respective
+   * attribute container classes
+   * <p/>
+   * delta_queued     : QueuedDeltaSessionAttributes delta_immediate  :
+   * DeltaSessionAttributes immediate        : ImmediateSessionAttributes queued
+   * : QueuedSessionAttributes
+   */
+  SESSION_DELTA_POLICY(String.class),
+
+  /**
+   * This parameter can take the following values:
+   * <p/>
+   * set (default) set_and_get
+   */
+  REPLICATION_TRIGGER(String.class);
+
+  Class clazz;
+
+  CacheProperty(Class clazz) {
+    this.clazz = clazz;
+  }
+
+  public Class getClazz() {
+    return clazz;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/92ee6a79/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/common/ClientServerSessionCache.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/common/ClientServerSessionCache.java b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/common/ClientServerSessionCache.java
new file mode 100644
index 0000000..a21ea2f
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/common/ClientServerSessionCache.java
@@ -0,0 +1,176 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.modules.session.internal.common;
+
+import com.gemstone.gemfire.cache.GemFireCache;
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.cache.RegionShortcut;
+import com.gemstone.gemfire.cache.client.ClientCache;
+import com.gemstone.gemfire.cache.client.ClientRegionFactory;
+import com.gemstone.gemfire.cache.client.ClientRegionShortcut;
+import com.gemstone.gemfire.cache.execute.Execution;
+import com.gemstone.gemfire.cache.execute.FunctionService;
+import com.gemstone.gemfire.cache.execute.ResultCollector;
+import com.gemstone.gemfire.modules.util.BootstrappingFunction;
+import com.gemstone.gemfire.modules.util.CreateRegionFunction;
+import com.gemstone.gemfire.modules.util.RegionConfiguration;
+import com.gemstone.gemfire.modules.util.RegionStatus;
+
+import java.util.List;
+import java.util.Map;
+import javax.servlet.http.HttpSession;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Class which defines a client/server cache.
+ */
+public class ClientServerSessionCache extends AbstractSessionCache {
+
+  private static final Logger LOG =
+      LoggerFactory.getLogger(PeerToPeerSessionCache.class.getName());
+
+  private ClientCache cache;
+
+  protected static final String DEFAULT_REGION_ATTRIBUTES_ID =
+      RegionShortcut.PARTITION_REDUNDANT.toString();
+
+  protected static final Boolean DEFAULT_ENABLE_LOCAL_CACHE = true;
+
+  /**
+   * Constructor
+   *
+   * @param cache
+   * @param properties
+   */
+  public ClientServerSessionCache(ClientCache cache,
+      Map<CacheProperty, Object> properties) {
+    super();
+    this.cache = cache;
+
+    /**
+     * Set some default properties for this cache if they haven't already
+     * been set
+     */
+    this.properties.put(CacheProperty.REGION_ATTRIBUTES_ID,
+        DEFAULT_REGION_ATTRIBUTES_ID);
+    this.properties.put(CacheProperty.ENABLE_LOCAL_CACHE,
+        DEFAULT_ENABLE_LOCAL_CACHE);
+    this.properties.putAll(properties);
+  }
+
+  @Override
+  public void initialize() {
+    // Bootstrap the servers
+    bootstrapServers();
+
+    // Create or retrieve the region
+    createOrRetrieveRegion();
+
+    // Set the session region directly as the operating region since there is no difference
+    // between the local cache region and the session region.
+    operatingRegion = sessionRegion;
+
+    // Create or retrieve the statistics
+    createStatistics();
+  }
+
+  @Override
+  public GemFireCache getCache() {
+    return cache;
+  }
+
+  @Override
+  public boolean isClientServer() {
+    return true;
+  }
+
+
+  ////////////////////////////////////////////////////////////////////////
+  // Private methods
+
+  private void bootstrapServers() {
+    Execution execution = FunctionService.onServers(this.cache);
+    ResultCollector collector = execution.execute(new BootstrappingFunction());
+    // Get the result. Nothing is being done with it.
+    try {
+      collector.getResult();
+    } catch (Exception e) {
+      // If an exception occurs in the function, log it.
+      LOG.warn("Caught unexpected exception:", e);
+    }
+  }
+
+  private void createOrRetrieveRegion() {
+    // Retrieve the local session region
+    this.sessionRegion =
+        this.cache.getRegion(
+            (String) properties.get(CacheProperty.REGION_NAME));
+
+    // If necessary, create the regions on the server and client
+    if (this.sessionRegion == null) {
+      // Create the PR on the servers
+      createSessionRegionOnServers();
+
+      // Create the region on the client
+      this.sessionRegion = createLocalSessionRegion();
+      LOG.debug("Created session region: " + this.sessionRegion);
+    } else {
+      LOG.debug("Retrieved session region: " + this.sessionRegion);
+    }
+  }
+
+  private void createSessionRegionOnServers() {
+    // Create the RegionConfiguration
+    RegionConfiguration configuration = createRegionConfiguration();
+
+    // Send it to the server tier
+    Execution execution = FunctionService.onServer(this.cache).withArgs(
+        configuration);
+    ResultCollector collector = execution.execute(CreateRegionFunction.ID);
+
+    // Verify the region was successfully created on the servers
+    List<RegionStatus> results = (List<RegionStatus>) collector.getResult();
+    for (RegionStatus status : results) {
+      if (status == RegionStatus.INVALID) {
+        StringBuilder builder = new StringBuilder();
+        builder.append(
+            "An exception occurred on the server while attempting to create or validate region named ");
+        builder.append(properties.get(CacheProperty.REGION_NAME));
+        builder.append(". See the server log for additional details.");
+        throw new IllegalStateException(builder.toString());
+      }
+    }
+  }
+
+  private Region<String, HttpSession> createLocalSessionRegion() {
+    ClientRegionFactory<String, HttpSession> factory = null;
+    boolean enableLocalCache =
+        (Boolean) properties.get(CacheProperty.ENABLE_LOCAL_CACHE);
+
+    String regionName = (String) properties.get(CacheProperty.REGION_NAME);
+    if (enableLocalCache) {
+      // Create the region factory with caching and heap LRU enabled
+      factory = ((ClientCache) this.cache).
+          createClientRegionFactory(
+              ClientRegionShortcut.CACHING_PROXY_HEAP_LRU);
+      LOG.info("Created new local client session region: {}", regionName);
+    } else {
+      // Create the region factory without caching enabled
+      factory = ((ClientCache) this.cache).createClientRegionFactory(
+          ClientRegionShortcut.PROXY);
+      LOG.info(
+          "Created new local client (uncached) session region: {} without any session expiry",
+          regionName);
+    }
+
+    // Create the region
+    return factory.create(regionName);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/92ee6a79/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/common/PeerToPeerSessionCache.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/common/PeerToPeerSessionCache.java b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/common/PeerToPeerSessionCache.java
new file mode 100644
index 0000000..7ba5e76
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/common/PeerToPeerSessionCache.java
@@ -0,0 +1,174 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.modules.session.internal.common;
+
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache.GemFireCache;
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.cache.RegionFactory;
+import com.gemstone.gemfire.cache.RegionShortcut;
+import com.gemstone.gemfire.cache.execute.FunctionService;
+import com.gemstone.gemfire.modules.session.catalina.callback.LocalSessionCacheLoader;
+import com.gemstone.gemfire.modules.session.catalina.callback.LocalSessionCacheWriter;
+import com.gemstone.gemfire.modules.util.RegionConfiguration;
+import com.gemstone.gemfire.modules.util.RegionHelper;
+import com.gemstone.gemfire.modules.util.TouchPartitionedRegionEntriesFunction;
+import com.gemstone.gemfire.modules.util.TouchReplicatedRegionEntriesFunction;
+
+import java.util.Map;
+import javax.servlet.http.HttpSession;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Class which defines a peer-to-peer cache
+ */
+public class PeerToPeerSessionCache extends AbstractSessionCache {
+
+  private static final Logger LOG =
+      LoggerFactory.getLogger(PeerToPeerSessionCache.class.getName());
+
+  private Cache cache;
+
+  private static final String DEFAULT_REGION_ATTRIBUTES_ID =
+      RegionShortcut.REPLICATE.toString();
+
+  private static final Boolean DEFAULT_ENABLE_LOCAL_CACHE = false;
+
+  /**
+   * Constructor
+   *
+   * @param cache
+   * @param properties
+   */
+  public PeerToPeerSessionCache(Cache cache,
+      Map<CacheProperty, Object> properties) {
+    super();
+    this.cache = cache;
+
+    /**
+     * Set some default properties for this cache if they haven't already
+     * been set
+     */
+    this.properties.put(CacheProperty.REGION_ATTRIBUTES_ID,
+        DEFAULT_REGION_ATTRIBUTES_ID);
+    this.properties.put(CacheProperty.ENABLE_LOCAL_CACHE,
+        DEFAULT_ENABLE_LOCAL_CACHE);
+    this.properties.putAll(properties);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void initialize() {
+    // Register Functions
+    registerFunctions();
+
+    // Create or retrieve the region
+    createOrRetrieveRegion();
+
+    /**
+     * If local cache is enabled, create the local region fronting the
+     * session region and set it as the operating region; otherwise, use
+     * the session region directly as the operating region.
+     */
+    boolean enableLocalCache =
+        (Boolean) properties.get(CacheProperty.ENABLE_LOCAL_CACHE);
+    operatingRegion = enableLocalCache
+        ? createOrRetrieveLocalRegion()
+        : this.sessionRegion;
+
+    // Create or retrieve the statistics
+    createStatistics();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public GemFireCache getCache() {
+    return cache;
+  }
+
+  @Override
+  public boolean isClientServer() {
+    return false;
+  }
+
+  private void registerFunctions() {
+    // Register the touch partitioned region entries function if it is not already registered
+    if (!FunctionService.isRegistered(
+        TouchPartitionedRegionEntriesFunction.ID)) {
+      FunctionService.registerFunction(
+          new TouchPartitionedRegionEntriesFunction());
+    }
+
+    // Register the touch replicated region entries function if it is not already registered
+    if (!FunctionService.isRegistered(
+        TouchReplicatedRegionEntriesFunction.ID)) {
+      FunctionService.registerFunction(
+          new TouchReplicatedRegionEntriesFunction());
+    }
+  }
+
+  private void createOrRetrieveRegion() {
+    // Create the RegionConfiguration
+    RegionConfiguration configuration = createRegionConfiguration();
+
+    // Attempt to retrieve the region
+    // If it already exists, validate it
+    // If it doesn't already exist, create it
+    Region region = this.cache.getRegion(
+        (String) properties.get(CacheProperty.REGION_NAME));
+    if (region == null) {
+      // Create the region
+      region = RegionHelper.createRegion(cache, configuration);
+      LOG.info("Created new session region: " + region);
+    } else {
+      // Validate the existing region
+      LOG.info("Retrieved existing session region: " + region);
+      RegionHelper.validateRegion(cache, configuration, region);
+    }
+
+    // Set the session region
+    this.sessionRegion = region;
+  }
+
+  /**
+   * Create a local region fronting the main region.
+   *
+   * @return
+   */
+  private Region<String, HttpSession> createOrRetrieveLocalRegion() {
+    // Attempt to retrieve the fronting region
+    String frontingRegionName = this.sessionRegion.getName() + "_local";
+    Region<String, HttpSession> frontingRegion =
+        this.cache.getRegion(frontingRegionName);
+
+    if (frontingRegion == null) {
+      // Create the region factory
+      RegionFactory<String, HttpSession> factory =
+          this.cache.createRegionFactory(RegionShortcut.LOCAL_HEAP_LRU);
+
+      // Add the cache loader and writer
+      factory.setCacheLoader(new LocalSessionCacheLoader(this.sessionRegion));
+      factory.setCacheWriter(new LocalSessionCacheWriter(this.sessionRegion));
+
+      // Create the region
+      frontingRegion = factory.create(frontingRegionName);
+      LOG.info("Created new local session region: {}", frontingRegion);
+    } else {
+      LOG.info("Retrieved existing local session region: {}",
+          frontingRegion);
+    }
+
+    return frontingRegion;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/92ee6a79/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/common/SessionCache.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/common/SessionCache.java b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/common/SessionCache.java
new file mode 100644
index 0000000..e0aa6bf
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/common/SessionCache.java
@@ -0,0 +1,59 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+
+package com.gemstone.gemfire.modules.session.internal.common;
+
+import com.gemstone.gemfire.cache.GemFireCache;
+import com.gemstone.gemfire.cache.Region;
+
+import javax.servlet.http.HttpSession;
+
+/**
+ * Interface to basic cache operations.
+ */
+public interface SessionCache {
+
+  /**
+   * Initialize the cache and create the appropriate region.
+   */
+  public void initialize();
+
+  /**
+   * Stop the cache.
+   */
+  public void stop();
+
+  /**
+   * Retrieve the cache reference.
+   *
+   * @return a {@code GemFireCache} reference
+   */
+  public GemFireCache getCache();
+
+  /**
+   * Get the {@code Region} being used by client code to put attributes.
+   *
+   * @return a {@code Region<String, HttpSession>} reference
+   */
+  public Region<String, HttpSession> getOperatingRegion();
+
+  /**
+   * Get the backing {@code Region} being used. This may not be the same as the
+   * region being used by client code to put attributes.
+   *
+   * @return a {@code Region<String, HttpSession>} reference
+   */
+  public Region<String, HttpSession> getSessionRegion();
+
+  /**
+   * Is this cache client-server? The only other alternative is peer-to-peer.
+   *
+   * @return true if this cache is client-server.
+   */
+  public boolean isClientServer();
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/92ee6a79/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/common/SessionExpirationCacheListener.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/common/SessionExpirationCacheListener.java b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/common/SessionExpirationCacheListener.java
new file mode 100644
index 0000000..836f4af
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/common/SessionExpirationCacheListener.java
@@ -0,0 +1,43 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.modules.session.internal.common;
+
+import com.gemstone.gemfire.cache.Declarable;
+import com.gemstone.gemfire.cache.EntryEvent;
+import com.gemstone.gemfire.cache.Operation;
+import com.gemstone.gemfire.cache.util.CacheListenerAdapter;
+
+import java.util.Properties;
+import javax.servlet.http.HttpSession;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SessionExpirationCacheListener extends
+    CacheListenerAdapter<String, HttpSession> implements Declarable {
+
+  private static final Logger LOG =
+      LoggerFactory.getLogger(SessionExpirationCacheListener.class.getName());
+
+  @Override
+  public void afterDestroy(EntryEvent<String, HttpSession> event) {
+    /**
+     * A Session expired. If it was destroyed by GemFire expiration,
+     * process it. If it was destroyed via Session.invalidate, ignore it
+     * since it has already been processed.
+     */
+    if (event.getOperation() == Operation.EXPIRE_DESTROY) {
+      HttpSession session = (HttpSession) event.getOldValue();
+      session.invalidate();
+    }
+  }
+
+  @Override
+  public void init(Properties p) {
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/92ee6a79/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/Constants.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/Constants.java b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/Constants.java
new file mode 100644
index 0000000..f62f9db
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/Constants.java
@@ -0,0 +1,14 @@
+
+package com.gemstone.gemfire.modules.session.internal.filter;
+
+/**
+ * Various constant values used through the app
+ */
+public class Constants {
+
+  public static String GEMFIRE_SESSION_REQUEST = "_gemfire_session_request_";
+
+  public static String SESSION_STATISTICS_MBEAN_NAME =
+      "com.gemstone:type=SessionStatistics,name=sessionStatistics";
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/92ee6a79/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/ContextManager.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/ContextManager.java b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/ContextManager.java
new file mode 100644
index 0000000..4954376
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/ContextManager.java
@@ -0,0 +1,95 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package com.gemstone.gemfire.modules.session.internal.filter;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import javax.servlet.ServletContext;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class is a singleton and manages the mapping of context paths to
+ * original ServletContext objects as well as a mapping of paths to Cache
+ * reference handles.
+ */
+public class ContextManager {
+
+  /**
+   * Logger object
+   */
+  private static final Logger LOG =
+      LoggerFactory.getLogger(ContextManager.class.getName());
+
+  /**
+   * Mapping of context path to ServletContext object
+   */
+  private final ConcurrentMap<String, ServletContext> contextMap =
+      new ConcurrentHashMap<String, ServletContext>(16);
+
+  /**
+   * Our singleton reference
+   */
+  private static final ContextManager manager = new ContextManager();
+
+  private ContextManager() {
+    // This is a singleton
+    LOG.info("Initializing ContextManager");
+  }
+
+  /**
+   * Return our singleton instance
+   *
+   * @return
+   */
+  public static ContextManager getInstance() {
+    return manager;
+  }
+
+  /**
+   * Add a context to our collection
+   *
+   * @param context the {@code ServletContext} to add
+   */
+  public void putContext(ServletContext context) {
+    String path = context.getContextPath();
+    contextMap.put(path, context);
+    LOG.info("Adding context '{}' {}", path, context);
+  }
+
+  /**
+   * Remove a context from our collection
+   *
+   * @param context the context to remove
+   */
+  public void removeContext(ServletContext context) {
+    String path = context.getContextPath();
+    contextMap.remove(path);
+    LOG.info("Removing context '{}'", path);
+  }
+
+  /**
+   * Retrieve the context for a given path
+   *
+   * @param path
+   * @return the GemfireServletContext object or null if the path is not found
+   */
+  public ServletContext getContext(String path) {
+    ServletContext ctx = contextMap.get(path);
+    if (ctx == null) {
+      LOG.warn("No context for requested contextPath '{}'", path);
+    }
+    return ctx;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/92ee6a79/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/DummySessionManager.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/DummySessionManager.java b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/DummySessionManager.java
new file mode 100644
index 0000000..bfa5e57
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/DummySessionManager.java
@@ -0,0 +1,127 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package com.gemstone.gemfire.modules.session.internal.filter;
+
+import com.gemstone.gemfire.modules.session.internal.filter.attributes.AbstractSessionAttributes;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+import javax.servlet.http.HttpSession;
+
+/**
+ * Class which fakes an in-memory basic session manager for testing purposes.
+ */
+public class DummySessionManager implements SessionManager {
+
+  /**
+   * Map of sessions
+   */
+  private final Map<String, HttpSession> sessions =
+      new HashMap<String, HttpSession>();
+
+  private class Attributes extends AbstractSessionAttributes {
+
+    @Override
+    public Object putAttribute(String attr, Object value) {
+      return attributes.put(attr, value);
+    }
+
+    @Override
+    public Object removeAttribute(String attr) {
+      return attributes.remove(attr);
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void start(Object config, ClassLoader loader) {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void stop() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public HttpSession getSession(String id) {
+    return sessions.get(id);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public HttpSession wrapSession(HttpSession nativeSession) {
+    String id = generateId();
+    AbstractSessionAttributes attributes = new Attributes();
+    GemfireHttpSession session = new GemfireHttpSession(id, nativeSession);
+    session.setManager(this);
+    session.setAttributes(attributes);
+    sessions.put(id, session);
+
+    return session;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public HttpSession getWrappingSession(String nativeId) {
+    return sessions.get(nativeId);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void putSession(HttpSession session) {
+    // shouldn't ever get called
+    throw new UnsupportedOperationException("Not supported yet.");
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void destroySession(String id) {
+    sessions.remove(id);
+  }
+
+  @Override
+  public String destroyNativeSession(String id) {
+    return null;
+  }
+
+  public String getSessionCookieName() {
+    return "JSESSIONID";
+  }
+
+  public String getJvmId() {
+    return "jvm-id";
+  }
+
+  /**
+   * Generate an ID string
+   */
+  private String generateId() {
+    return UUID.randomUUID().toString().toUpperCase() + "-GF";
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/92ee6a79/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/GemfireHttpSession.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/GemfireHttpSession.java b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/GemfireHttpSession.java
new file mode 100644
index 0000000..1f114bc
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/GemfireHttpSession.java
@@ -0,0 +1,517 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+
+package com.gemstone.gemfire.modules.session.internal.filter;
+
+import com.gemstone.gemfire.DataSerializable;
+import com.gemstone.gemfire.DataSerializer;
+import com.gemstone.gemfire.Delta;
+import com.gemstone.gemfire.Instantiator;
+import com.gemstone.gemfire.InvalidDeltaException;
+import com.gemstone.gemfire.modules.session.internal.filter.attributes.AbstractSessionAttributes;
+import com.gemstone.gemfire.modules.session.internal.filter.attributes.SessionAttributes;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.concurrent.atomic.AtomicBoolean;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpSessionContext;
+
+import com.gemstone.gemfire.modules.util.ClassLoaderObjectInputStream;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Class which implements a Gemfire persisted {@code HttpSession}
+ */
+public class GemfireHttpSession implements
+    HttpSession, DataSerializable, Delta {
+
+  private static transient final Logger LOG =
+      LoggerFactory.getLogger(GemfireHttpSession.class.getName());
+
+  /**
+   * Serial id
+   */
+  private static final long serialVersionUID = 238915238964017823L;
+
+  /**
+   * Id for the session
+   */
+  private String id;
+
+  /**
+   * Attributes really hold the essence of persistence.
+   */
+  private SessionAttributes attributes;
+
+  private transient SessionManager manager;
+
+  private HttpSession nativeSession = null;
+
+  /**
+   * A session becomes invalid if it is explicitly invalidated or if it
+   * expires.
+   */
+  private boolean isValid = true;
+
+  private boolean isNew = true;
+
+  private boolean isDirty = false;
+
+  /**
+   * This is set during serialization and then reset by the SessionManager when
+   * it is retrieved from the attributes.
+   */
+  private AtomicBoolean serialized = new AtomicBoolean(false);
+
+  /**
+   * Register ourselves for de-serialization
+   */
+  static {
+    Instantiator.register(new Instantiator(GemfireHttpSession.class, 27315) {
+      @Override
+      public DataSerializable newInstance() {
+        return new GemfireHttpSession();
+      }
+    });
+  }
+
+  /**
+   * Constructor used for de-serialization
+   */
+  private GemfireHttpSession() {
+  }
+
+  /**
+   * Constructor
+   */
+  public GemfireHttpSession(String id, HttpSession nativeSession) {
+    this();
+    this.id = id;
+    this.nativeSession = nativeSession;
+    if (nativeSession != null) {
+      attributes.setMaxInactiveInterval(nativeSession.getMaxInactiveInterval());
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Object getAttribute(String name) {
+    if (!isValid) {
+      throw new IllegalStateException("Session is already invalidated");
+    }
+    Object obj = attributes.getAttribute(name);
+
+    if (obj != null) {
+      Object tmpObj = null;
+      ClassLoader loader = ((GemfireSessionManager) manager).getReferenceClassLoader();
+
+      if (obj.getClass().getClassLoader() != loader) {
+        LOG.debug(
+            "Attribute '{}' needs to be reconstructed with a new classloader",
+            name);
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        try {
+          ObjectOutputStream oos = new ObjectOutputStream(baos);
+          oos.writeObject(obj);
+          oos.close();
+
+          ObjectInputStream ois = new ClassLoaderObjectInputStream(
+              new ByteArrayInputStream(baos.toByteArray()),
+              loader);
+          tmpObj = ois.readObject();
+        } catch (IOException e) {
+          LOG.error("Exception while recreating attribute '" + name +
+              "'", e);
+        } catch (ClassNotFoundException e) {
+          LOG.error("Exception while recreating attribute '" + name +
+              "'", e);
+        }
+        if (tmpObj != null) {
+          setAttribute(name, tmpObj);
+          obj = tmpObj;
+        }
+      }
+    }
+
+    return obj;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Enumeration getAttributeNames() {
+    if (!isValid) {
+      throw new IllegalStateException("Session is already invalidated");
+    }
+    return Collections.enumeration(attributes.getAttributeNames());
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public long getCreationTime() {
+    if (nativeSession != null) {
+      return nativeSession.getCreationTime();
+    } else {
+      return 0;
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String getId() {
+    return id;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public long getLastAccessedTime() {
+    if (!isValid) {
+      throw new IllegalStateException("Session is already invalidated");
+    }
+    return attributes.getLastAccessedTime();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public ServletContext getServletContext() {
+    if (nativeSession != null) {
+      return nativeSession.getServletContext();
+    } else {
+      return null;
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public HttpSessionContext getSessionContext() {
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Object getValue(String name) {
+    return getAttribute(name);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String[] getValueNames() {
+    return attributes.getAttributeNames().toArray(new String[0]);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void invalidate() {
+    nativeSession.invalidate();
+    manager.destroySession(id);
+    isValid = false;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean isNew() {
+    if (!isValid) {
+      throw new IllegalStateException("Session is already invalidated");
+    }
+    return isNew;
+  }
+
+  public void setIsNew(boolean isNew) {
+    this.isNew = isNew;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void setMaxInactiveInterval(int interval) {
+    if (nativeSession != null) {
+      nativeSession.setMaxInactiveInterval(interval);
+    }
+    attributes.setMaxInactiveInterval(interval);
+    isDirty = true;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public int getMaxInactiveInterval() {
+    if (nativeSession != null) {
+      return nativeSession.getMaxInactiveInterval();
+    } else {
+      return attributes.getMaxIntactiveInterval();
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void putValue(String name, Object value) {
+    setAttribute(name, value);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void removeAttribute(final String name) {
+    LOG.debug("Session {} removing attribute {}", getId(), name);
+    nativeSession.removeAttribute(name);
+    attributes.removeAttribute(name);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void removeValue(String name) {
+    removeAttribute(name);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void setAttribute(final String name, final Object value) {
+
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("Session {} setting attribute {} = '{}'",
+          new Object[]{id, name, value});
+    }
+
+    isDirty = true;
+    nativeSession.setAttribute(name, value);
+    if (value == null) {
+      removeAttribute(name);
+    } else {
+      attributes.putAttribute(name, value);
+    }
+  }
+
+  /**
+   * Gemfire serialization {@inheritDoc}
+   */
+  @Override
+  public void toData(DataOutput out) throws IOException {
+    DataSerializer.writeString(id, out);
+    DataSerializer.writeObject(attributes, out);
+  }
+
+  /**
+   * Gemfire de-serialization {@inheritDoc}
+   */
+  @Override
+  public void fromData(DataInput in) throws IOException,
+      ClassNotFoundException {
+    id = DataSerializer.readString(in);
+    attributes = DataSerializer.readObject(in);
+    if (getNativeSession() != null) {
+      for (String s : attributes.getAttributeNames()) {
+        getNativeSession().setAttribute(s, attributes.getAttribute(s));
+      }
+    }
+
+    // Explicit sets
+    serialized.set(true);
+    attributes.setSession(this);
+  }
+
+  /**
+   * These three methods handle delta propagation and are deferred to the
+   * attribute object.
+   */
+  @Override
+  public boolean hasDelta() {
+    return isDirty;
+  }
+
+  @Override
+  public void toDelta(DataOutput out) throws IOException {
+    if (attributes instanceof Delta) {
+      ((Delta) attributes).toDelta(out);
+    } else {
+      toData(out);
+    }
+  }
+
+  @Override
+  public void fromDelta(DataInput in) throws IOException,
+      InvalidDeltaException {
+    if (attributes instanceof Delta) {
+      ((Delta) attributes).fromDelta(in);
+    } else {
+      try {
+        fromData(in);
+      } catch (ClassNotFoundException cex) {
+        throw new IOException("Unable to forward fromDelta() call "
+            + "to fromData()", cex);
+      }
+    }
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder builder = new StringBuilder();
+    builder.append("[id=").append(id)
+        .append(", isNew=").append(isNew)
+        .append(", isValid=").append(isValid)
+        .append(", hasDelta=").append(hasDelta())
+        .append(", lastAccessedTime=").append(attributes.getLastAccessedTime())
+        .append(", jvmOwnerId=").append(attributes.getJvmOwnerId());
+    builder.append("]");
+    return builder.toString();
+  }
+
+  /**
+   * Flush the session object to the region
+   */
+  public void putInRegion() {
+
+    manager.putSession(this);
+    isDirty = false;
+  }
+
+  /**
+   * Determine whether the session is still valid or whether it has expired.
+   *
+   * @return true or false
+   */
+  public boolean isValid() {
+    if (!isValid) {
+      return false;
+    }
+    if (getMaxInactiveInterval() >= 0) {
+      long now = System.currentTimeMillis();
+      if (now - attributes.getLastAccessedTime() >= getMaxInactiveInterval() * 1000) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Is this session dirty and should it be written to cache
+   */
+  public boolean isDirty() {
+    return isDirty;
+  }
+
+  public void setManager(SessionManager manager) {
+    this.manager = manager;
+  }
+
+  /**
+   * For testing allow retrieval of the wrapped, native session.
+   */
+  public HttpSession getNativeSession() {
+    return nativeSession;
+  }
+
+
+  public void setNativeSession(HttpSession session) {
+    this.nativeSession = session;
+  }
+
+  /**
+   * Handle the process of failing over the session to a new native session
+   * object.
+   *
+   * @param session
+   */
+  public void failoverSession(HttpSession session) {
+    LOG.debug("Failing over session {} to {}", getId(), session.getId());
+    setNativeSession(session);
+    for (String name : attributes.getAttributeNames()) {
+      LOG.debug("Copying '{}' => {}", name, attributes.getAttribute(name));
+      session.setAttribute(name, attributes.getAttribute(name));
+    }
+    session.setMaxInactiveInterval(attributes.getMaxIntactiveInterval());
+    manager.putSession(this);
+  }
+
+
+  /**
+   * Update the last accessed time
+   */
+  public void updateAccessTime() {
+    attributes.setLastAccessedTime(System.currentTimeMillis());
+  }
+
+  /**
+   * The {@code SessionManager} injects this when creating a new session.
+   *
+   * @param attributes
+   */
+  public void setAttributes(AbstractSessionAttributes attributes) {
+    this.attributes = attributes;
+  }
+
+  /**
+   * This is called on deserialization. You can only call it once to get a
+   * meaningful value as it resets the serialized state. In other words, this
+   * call is not idempotent.
+   *
+   * @return whether this object has just been serialized
+   */
+  public boolean justSerialized() {
+    return serialized.getAndSet(false);
+  }
+
+  /**
+   * Called when the session is about to go out of scope. If the session has
+   * been defined to use async queued attributes then they will be written out
+   * at this point.
+   */
+  public void commit() {
+    attributes.setJvmOwnerId(manager.getJvmId());
+    attributes.flush();
+  }
+
+  public String getJvmOwnerId() {
+    if (attributes != null) {
+      return attributes.getJvmOwnerId();
+    }
+
+    return null;
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/92ee6a79/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/GemfireSessionException.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/GemfireSessionException.java b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/GemfireSessionException.java
new file mode 100644
index 0000000..2a34b5e
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/GemfireSessionException.java
@@ -0,0 +1,36 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package com.gemstone.gemfire.modules.session.internal.filter;
+
+/**
+ * Exception class for Gemfire Session Cache specific exceptions.
+ */
+public class GemfireSessionException extends Exception {
+
+  public GemfireSessionException() {
+    super();
+  }
+
+  public GemfireSessionException(String message) {
+    super(message);
+  }
+
+  public GemfireSessionException(String message, Throwable cause) {
+    super(message, cause);
+  }
+
+  public GemfireSessionException(Throwable cause) {
+    super(cause);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/92ee6a79/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/GemfireSessionManager.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/GemfireSessionManager.java b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/GemfireSessionManager.java
new file mode 100644
index 0000000..dd148d2
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/GemfireSessionManager.java
@@ -0,0 +1,502 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+
+package com.gemstone.gemfire.modules.session.internal.filter;
+
+import com.gemstone.gemfire.cache.CacheClosedException;
+import com.gemstone.gemfire.cache.CacheFactory;
+import com.gemstone.gemfire.cache.EntryNotFoundException;
+import com.gemstone.gemfire.cache.control.ResourceManager;
+import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
+import com.gemstone.gemfire.modules.session.bootstrap.AbstractCache;
+import com.gemstone.gemfire.modules.session.bootstrap.ClientServerCache;
+import com.gemstone.gemfire.modules.session.bootstrap.LifecycleTypeAdapter;
+import com.gemstone.gemfire.modules.session.bootstrap.PeerToPeerCache;
+import com.gemstone.gemfire.modules.session.internal.common.CacheProperty;
+import com.gemstone.gemfire.modules.session.internal.common.ClientServerSessionCache;
+import com.gemstone.gemfire.modules.session.internal.common.PeerToPeerSessionCache;
+import com.gemstone.gemfire.modules.session.internal.common.SessionCache;
+import com.gemstone.gemfire.modules.session.internal.filter.attributes.AbstractSessionAttributes;
+import com.gemstone.gemfire.modules.session.internal.filter.attributes.DeltaQueuedSessionAttributes;
+import com.gemstone.gemfire.modules.session.internal.filter.attributes.DeltaSessionAttributes;
+import com.gemstone.gemfire.modules.session.internal.filter.attributes.ImmediateSessionAttributes;
+import com.gemstone.gemfire.modules.session.internal.filter.util.TypeAwareMap;
+import com.gemstone.gemfire.modules.session.internal.jmx.SessionStatistics;
+import com.gemstone.gemfire.modules.util.RegionHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.naming.InitialContext;
+import javax.servlet.FilterConfig;
+import javax.servlet.http.HttpSession;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * This class implements the session management using a Gemfire distributedCache
+ * as a persistent store for the session objects
+ */
+public class GemfireSessionManager implements SessionManager {
+
+  private final Logger LOG;
+
+  /**
+   * Prefix of init param string used to set gemfire properties
+   */
+  private static final String GEMFIRE_PROPERTY = "gemfire.property.";
+
+  /**
+   * Prefix of init param string used to set gemfire distributedCache setting
+   */
+  private static final String GEMFIRE_CACHE = "gemfire.cache.";
+
+  private static final String INIT_PARAM_CACHE_TYPE = "cache-type";
+  private static final String CACHE_TYPE_CLIENT_SERVER = "client-server";
+  private static final String CACHE_TYPE_PEER_TO_PEER = "peer-to-peer";
+  private static final String INIT_PARAM_SESSION_COOKIE_NAME = "session-cookie-name";
+  private static final String INIT_PARAM_JVM_ID = "jvm-id";
+  private static final String DEFAULT_JVM_ID = "default";
+
+  private SessionCache sessionCache = null;
+
+  /**
+   * Reference to the distributed system
+   */
+  private AbstractCache distributedCache = null;
+
+  /**
+   * Boolean indicating whether the manager is shutting down
+   */
+  private boolean isStopping = false;
+
+  /**
+   * Boolean indicating whether this manager is defined in the same context (war
+   * / classloader) as the filter.
+   */
+  private boolean isolated = false;
+
+  /**
+   * Map of wrapping GemFire session id to native session id
+   */
+  private Map<String, String> nativeSessionMap =
+      new HashMap<String, String>();
+
+  /**
+   * MBean for statistics
+   */
+  private SessionStatistics mbean;
+
+  /**
+   * This CL is used to compare against the class loader of attributes getting
+   * pulled out of the cache. This variable should be set to the CL of the
+   * filter running everything.
+   */
+  private ClassLoader referenceClassLoader;
+
+  private String sessionCookieName = "JSESSIONID";
+
+  /**
+   * Give this JVM a unique identifier.
+   */
+  private String jvmId = "default";
+
+  /**
+   * Set up properties with default values
+   */
+  private TypeAwareMap<CacheProperty, Object> properties =
+      new TypeAwareMap<CacheProperty, Object>(CacheProperty.class) {{
+        put(CacheProperty.REGION_NAME, RegionHelper.NAME + "_sessions");
+        put(CacheProperty.ENABLE_GATEWAY_DELTA_REPLICATION, Boolean.FALSE);
+        put(CacheProperty.ENABLE_GATEWAY_REPLICATION, Boolean.FALSE);
+        put(CacheProperty.ENABLE_DEBUG_LISTENER, Boolean.FALSE);
+        put(CacheProperty.STATISTICS_NAME, "gemfire_statistics");
+        put(CacheProperty.SESSION_DELTA_POLICY, "delta_queued");
+        put(CacheProperty.REPLICATION_TRIGGER, "set");
+        /**
+         * For REGION_ATTRIBUTES_ID and ENABLE_LOCAL_CACHE the default
+         * is different for ClientServerCache and PeerToPeerCache
+         * so those values are set in the relevant constructors when
+         * these properties are passed in to them.
+         */
+      }};
+
+  public GemfireSessionManager() {
+    LOG = LoggerFactory.getLogger(GemfireSessionManager.class.getName());
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void start(Object conf, ClassLoader loader) {
+    this.referenceClassLoader = loader;
+    FilterConfig config = (FilterConfig) conf;
+
+    startDistributedSystem(config);
+    initializeSessionCache(config);
+
+    // Register MBean
+    registerMBean();
+
+    if (distributedCache.getClass().getClassLoader() == loader) {
+      isolated = true;
+    }
+
+    String sessionCookieName = config.getInitParameter(
+        INIT_PARAM_SESSION_COOKIE_NAME);
+    if (sessionCookieName != null && !sessionCookieName.isEmpty()) {
+      this.sessionCookieName = sessionCookieName;
+      LOG.info("Session cookie name set to: {}", this.sessionCookieName);
+    }
+
+    jvmId = config.getInitParameter(INIT_PARAM_JVM_ID);
+    if (jvmId == null || jvmId.isEmpty()) {
+      jvmId = DEFAULT_JVM_ID;
+    }
+
+    LOG.info("Started GemfireSessionManager (isolated={}, jvmId={})",
+        isolated, jvmId);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void stop() {
+    isStopping = true;
+
+    if (isolated) {
+      if (distributedCache != null) {
+        LOG.info("Closing distributed cache - assuming isolated cache");
+        distributedCache.close();
+      }
+    } else {
+      LOG.info("Not closing distributed cache - assuming common cache");
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public HttpSession getSession(String id) {
+    GemfireHttpSession session = (GemfireHttpSession) sessionCache.getOperatingRegion().get(
+        id);
+
+    if (session != null) {
+      if (session.justSerialized()) {
+        session.setManager(this);
+        LOG.debug("Recovered serialized session {} (jvmId={})", id,
+            session.getJvmOwnerId());
+      }
+      LOG.debug("Retrieved session id {}", id);
+    } else {
+      LOG.debug("Session id {} not found", id);
+    }
+    return session;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public HttpSession wrapSession(HttpSession nativeSession) {
+    String id = generateId();
+    GemfireHttpSession session =
+        new GemfireHttpSession(id, nativeSession);
+
+    /**
+     * Set up the attribute container depending on how things are configured
+     */
+    AbstractSessionAttributes attributes;
+    if ("delta_queued".equals(
+        properties.get(CacheProperty.SESSION_DELTA_POLICY))) {
+      attributes = new DeltaQueuedSessionAttributes();
+      ((DeltaQueuedSessionAttributes) attributes).setReplicationTrigger(
+          (String) properties.get(CacheProperty.REPLICATION_TRIGGER));
+    } else if ("delta_immediate".equals(
+        properties.get(CacheProperty.SESSION_DELTA_POLICY))) {
+      attributes = new DeltaSessionAttributes();
+    } else if ("immediate".equals(
+        properties.get(CacheProperty.SESSION_DELTA_POLICY))) {
+      attributes = new ImmediateSessionAttributes();
+    } else {
+      attributes = new DeltaSessionAttributes();
+      LOG.warn(
+          "No session delta policy specified - using default of 'delta_immediate'");
+    }
+
+    attributes.setSession(session);
+    attributes.setJvmOwnerId(jvmId);
+
+    session.setManager(this);
+    session.setAttributes(attributes);
+
+    LOG.debug("Creating new session {}", id);
+    sessionCache.getOperatingRegion().put(id, session);
+
+    mbean.incActiveSessions();
+
+    return session;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public HttpSession getWrappingSession(String nativeId) {
+    HttpSession session = null;
+    String gemfireId = getGemfireSessionIdFromNativeId(nativeId);
+
+    if (gemfireId != null) {
+      session = getSession(gemfireId);
+    }
+    return session;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void destroySession(String id) {
+    if (!isStopping) {
+      try {
+        GemfireHttpSession session = (GemfireHttpSession) sessionCache.getOperatingRegion().get(
+            id);
+        if (session != null && session.getJvmOwnerId().equals(jvmId)) {
+          LOG.debug("Destroying session {}", id);
+          sessionCache.getOperatingRegion().destroy(id);
+          mbean.decActiveSessions();
+        }
+      } catch (EntryNotFoundException nex) {
+      }
+    } else {
+      if (sessionCache.isClientServer()) {
+        LOG.debug("Destroying session {}", id);
+        try {
+          sessionCache.getOperatingRegion().localDestroy(id);
+        } catch (EntryNotFoundException nex) {
+          // Ignored
+        } catch (CacheClosedException ccex) {
+          // Ignored
+        }
+      } else {
+        GemfireHttpSession session = (GemfireHttpSession) sessionCache.getOperatingRegion().get(
+            id);
+        if (session != null) {
+          session.setNativeSession(null);
+        }
+      }
+    }
+
+    synchronized (nativeSessionMap) {
+      String nativeId = nativeSessionMap.remove(id);
+      LOG.debug("destroySession called for {} wrapping {}", id, nativeId);
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void putSession(HttpSession session) {
+    sessionCache.getOperatingRegion().put(session.getId(), session);
+    mbean.incRegionUpdates();
+    nativeSessionMap.put(session.getId(),
+        ((GemfireHttpSession) session).getNativeSession().getId());
+  }
+
+  @Override
+  public String destroyNativeSession(String nativeId) {
+    String gemfireSessionId = getGemfireSessionIdFromNativeId(nativeId);
+    if (gemfireSessionId != null) {
+      destroySession(gemfireSessionId);
+    }
+    return gemfireSessionId;
+  }
+
+  public ClassLoader getReferenceClassLoader() {
+    return referenceClassLoader;
+  }
+
+  /**
+   * This method is called when a native session gets destroyed. It will check
+   * if the GemFire session is actually still valid/not expired and will then
+   * attach a new, native session.
+   *
+   * @param nativeId the id of the native session
+   * @return the id of the newly attached native session or null if the GemFire
+   * session was already invalid
+   */
+  public String refreshSession(String nativeId) {
+    String gemfireId = getGemfireSessionIdFromNativeId(nativeId);
+    if (gemfireId == null) {
+      return null;
+    }
+
+    GemfireHttpSession session = (GemfireHttpSession) sessionCache.getOperatingRegion().get(
+        gemfireId);
+    if (session.isValid()) {
+
+    }
+
+    return null;
+  }
+
+  public String getSessionCookieName() {
+    return sessionCookieName;
+  }
+
+  public String getJvmId() {
+    return jvmId;
+  }
+
+
+  ///////////////////////////////////////////////////////////////////////
+  // Private methods
+
+  private String getGemfireSessionIdFromNativeId(String nativeId) {
+    if (nativeId == null) {
+      return null;
+    }
+
+    for (Map.Entry<String, String> e : nativeSessionMap.entrySet()) {
+      if (nativeId.equals(e.getValue())) {
+        return e.getKey();
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Start the underlying distributed system
+   *
+   * @param config
+   */
+  private void startDistributedSystem(FilterConfig config) {
+    // Get the distributedCache type
+    final String cacheType = config.getInitParameter(INIT_PARAM_CACHE_TYPE);
+    if (CACHE_TYPE_CLIENT_SERVER.equals(cacheType)) {
+      distributedCache = ClientServerCache.getInstance();
+    } else if (CACHE_TYPE_PEER_TO_PEER.equals(cacheType)) {
+      distributedCache = PeerToPeerCache.getInstance();
+    } else {
+      LOG.error("No 'cache-type' initialization param set. "
+          + "Cache will not be started");
+      return;
+    }
+
+    if (!distributedCache.isStarted()) {
+      /**
+       * Process all the init params and see if any apply to the
+       * distributed system.
+       */
+      for (Enumeration<String> e = config.getInitParameterNames(); e.hasMoreElements(); ) {
+        String param = e.nextElement();
+        if (!param.startsWith(GEMFIRE_PROPERTY)) {
+          continue;
+        }
+
+        String gemfireProperty = param.substring(GEMFIRE_PROPERTY.length());
+        LOG.info("Setting gemfire property: {} = {}",
+            gemfireProperty, config.getInitParameter(param));
+        distributedCache.setProperty(gemfireProperty,
+            config.getInitParameter(param));
+      }
+
+      distributedCache.lifecycleEvent(LifecycleTypeAdapter.START);
+    }
+  }
+
+  /**
+   * Initialize the distributedCache
+   */
+  private void initializeSessionCache(FilterConfig config) {
+    // Retrieve the distributedCache
+    GemFireCacheImpl cache = (GemFireCacheImpl) CacheFactory.getAnyInstance();
+    if (cache == null) {
+      throw new IllegalStateException("No cache exists. Please configure "
+          + "either a PeerToPeerCacheLifecycleListener or "
+          + "ClientServerCacheLifecycleListener in the "
+          + "server.xml file.");
+    }
+
+    /**
+     * Process all the init params and see if any apply to the distributedCache
+     */
+    ResourceManager rm = cache.getResourceManager();
+    for (Enumeration<String> e = config.getInitParameterNames(); e.hasMoreElements(); ) {
+      String param = e.nextElement();
+
+      // Uggh - don't like this non-generic stuff
+      if (param.equalsIgnoreCase("criticalHeapPercentage")) {
+        float val = Float.parseFloat(config.getInitParameter(param));
+        rm.setCriticalHeapPercentage(val);
+      }
+
+      if (param.equalsIgnoreCase("evictionHeapPercentage")) {
+        float val = Float.parseFloat(config.getInitParameter(param));
+        rm.setEvictionHeapPercentage(val);
+      }
+
+
+      if (!param.startsWith(GEMFIRE_CACHE)) {
+        continue;
+      }
+
+      String gemfireWebParam = param.substring(GEMFIRE_CACHE.length());
+      LOG.info("Setting cache parameter: {} = {}",
+          gemfireWebParam, config.getInitParameter(param));
+      properties.put(CacheProperty.valueOf(gemfireWebParam.toUpperCase()),
+          config.getInitParameter(param));
+    }
+
+    // Create the appropriate session distributedCache
+    sessionCache = cache.isClient()
+        ? new ClientServerSessionCache(cache, properties)
+        : new PeerToPeerSessionCache(cache, properties);
+
+    // Initialize the session distributedCache
+    sessionCache.initialize();
+  }
+
+  /**
+   * Register a bean for statistic gathering purposes
+   */
+  private void registerMBean() {
+    mbean = new SessionStatistics();
+
+    try {
+      InitialContext ctx = new InitialContext();
+      MBeanServer mbs = MBeanServer.class.cast(
+          ctx.lookup("java:comp/env/jmx/runtime"));
+      ObjectName oname = new ObjectName(
+          Constants.SESSION_STATISTICS_MBEAN_NAME);
+
+      mbs.registerMBean(mbean, oname);
+    } catch (Exception ex) {
+      LOG.warn("Unable to register statistics MBean. Error: {}",
+          ex.getMessage());
+    }
+  }
+
+
+  /**
+   * Generate an ID string
+   */
+  private String generateId() {
+    return UUID.randomUUID().toString().toUpperCase() + "-GF";
+  }
+
+  AbstractCache getCache() {
+    return distributedCache;
+  }
+}
\ No newline at end of file



Mime
View raw message