You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ds...@apache.org on 2015/07/06 23:46:29 UTC

[08/20] incubator-geode git commit: GEODE-14: Imported modules from geode-1.0.0-SNAPSHOT-2.src.tar

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/4b56f5e4/modules/gemfire-modules-session-integration-test/src/test/java/com/gemstone/gemfire/modules/session/filter/IntegrationTest.java
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session-integration-test/src/test/java/com/gemstone/gemfire/modules/session/filter/IntegrationTest.java b/modules/gemfire-modules-session-integration-test/src/test/java/com/gemstone/gemfire/modules/session/filter/IntegrationTest.java
new file mode 100644
index 0000000..50b6425
--- /dev/null
+++ b/modules/gemfire-modules-session-integration-test/src/test/java/com/gemstone/gemfire/modules/session/filter/IntegrationTest.java
@@ -0,0 +1,1552 @@
+/*=========================================================================
+ * 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.filter;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.concurrent.TimeUnit;
+import javax.servlet.DispatcherType;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.modules.junit.PerTestClassLoaderRunner;
+import org.apache.jasper.servlet.JspServlet;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.eclipse.jetty.servlet.FilterHolder;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.http.HttpTester;
+
+import static org.junit.Assert.*;
+
+/**
+ * In-container testing using Jetty. This allows us to test context listener
+ * events as well as dispatching actions.
+ */
+@RunWith(PerTestClassLoaderRunner.class)
+public class IntegrationTest {
+
+  private MyServletTester tester;
+
+  private HttpTester.Request request;
+
+  private HttpTester.Response response;
+
+  private ServletHolder servletHolder;
+
+  private FilterHolder filterHolder;
+
+  private static final File tmpdir;
+
+  private static final String gemfire_log;
+
+  static {
+    // Create a per-user scratch directory
+    tmpdir = new File(System.getProperty("java.io.tmpdir"),
+        "gemfire_modules-" + System.getProperty("user.name"));
+    tmpdir.mkdirs();
+    tmpdir.deleteOnExit();
+
+    gemfire_log = tmpdir.getPath() +
+        System.getProperty("file.separator") + "gemfire_modules.log";
+  }
+
+  @Before
+  public void setUp() throws Exception {
+    request = HttpTester.newRequest();
+
+    tester = new MyServletTester();
+    tester.setContextPath("/test");
+
+    filterHolder = tester.addFilter(SessionCachingFilter.class, "/*",
+        EnumSet.of(DispatcherType.REQUEST));
+    filterHolder.setInitParameter("gemfire.property.mcast-port", "0");
+    filterHolder.setInitParameter("gemfire.property.writable-working-dir",
+        tmpdir.getPath());
+    filterHolder.setInitParameter("cache-type", "peer-to-peer");
+    filterHolder.setInitParameter("gemfire.property.log-file",
+        gemfire_log);
+
+    servletHolder = tester.addServlet(BasicServlet.class, "/hello");
+    servletHolder.setInitParameter("test.callback", "callback_1");
+
+    /**
+     * This starts the servlet. Our wrapped servlets *must* start
+     * immediately otherwise the ServletContext is not captured correctly.
+     */
+    servletHolder.setInitOrder(0);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    if (tester.isStarted()) {
+      ContextManager.getInstance().removeContext(
+          servletHolder.getServlet().getServletConfig().getServletContext());
+    }
+    tester.stop();
+  }
+
+  @Test
+  public void testSanity() throws Exception {
+    Callback c = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException {
+        PrintWriter out = response.getWriter();
+        out.write("Hello World");
+      }
+    };
+
+    tester.setAttribute("callback_1", c);
+    tester.start();
+    ContextManager.getInstance().putContext(
+        servletHolder.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    assertEquals(200, response.getStatus());
+    assertEquals("Hello World", response.getContent());
+  }
+
+  @Test
+  public void testSessionGenerated() throws Exception {
+    Callback c = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException {
+        PrintWriter out = response.getWriter();
+        out.write(request.getSession().getId());
+      }
+    };
+
+    tester.setAttribute("callback_1", c);
+    tester.start();
+    ContextManager.getInstance().putContext(
+        servletHolder.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    assertTrue("Not a correctly generated session id",
+        response.getContent().endsWith("-GF"));
+
+    List<Cookie> cookies = getCookies(response);
+    assertEquals("Session id != JSESSIONID from cookie",
+        response.getContent(), cookies.get(0).getValue());
+
+    Region r = getRegion();
+    assertNotNull("Session not found in region",
+        r.get(cookies.get(0).getValue()));
+  }
+
+
+  /**
+   * Test that getSession(false) does not create a new session
+   */
+  @Test
+  public void testSessionNotGenerated() throws Exception {
+    Callback c = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException {
+        String output = "OK";
+        HttpSession s = request.getSession(false);
+        if (s != null) {
+          output = s.getId();
+        }
+        PrintWriter out = response.getWriter();
+        out.write(output);
+      }
+    };
+
+    tester.setAttribute("callback_1", c);
+    tester.start();
+    ContextManager.getInstance().putContext(
+        servletHolder.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    assertEquals("Session should not have been created", "OK",
+        response.getContent());
+  }
+
+
+  @Test
+  public void testUnknownAttributeIsNull() throws Exception {
+    Callback c = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException {
+        Object o = request.getSession().getAttribute("unknown");
+        PrintWriter out = response.getWriter();
+        if (o == null) {
+          out.write("null");
+        } else {
+          out.write(o.toString());
+        }
+      }
+    };
+
+    tester.setAttribute("callback_1", c);
+    tester.start();
+    ContextManager.getInstance().putContext(
+        servletHolder.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    assertEquals("Unknown attribute should be null", "null",
+        response.getContent());
+  }
+
+
+  @Test
+  public void testSessionRemains1() throws Exception {
+    Callback c = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException {
+        String output = "null";
+        HttpSession session = request.getSession();
+        if (session.isNew()) {
+          output = "new";
+          session.setAttribute("foo", output);
+        } else {
+          output = (String) session.getAttribute("foo");
+          if (output != null) {
+            output = "old";
+          }
+        }
+        PrintWriter out = response.getWriter();
+        out.write(output);
+      }
+    };
+
+    tester.setAttribute("callback_1", c);
+    tester.start();
+    ContextManager.getInstance().putContext(
+        servletHolder.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    assertEquals("Session should be new", "new", response.getContent());
+
+    List<Cookie> cookies = getCookies(response);
+    request.setHeader("Cookie", "JSESSIONID=" + cookies.get(0).getValue());
+
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    assertEquals("Session should be old", "old", response.getContent());
+
+    List<Cookie> cookies2 = getCookies(response);
+    assertEquals("Session IDs should be the same", cookies.get(0).getValue(),
+        cookies2.get(0).getValue());
+
+    Region r = getRegion();
+    assertNotNull("Session object should exist in region",
+        r.get(cookies.get(0).getValue()));
+  }
+
+  /**
+   * Test that attributes are updated on the backend
+   */
+  @Test
+  public void testAttributesUpdatedInRegion() throws Exception {
+    Callback c_1 = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException, ServletException {
+        request.getSession().setAttribute("foo", "bar");
+      }
+    };
+
+    // This is the callback used to invalidate the session
+    Callback c_2 = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException, ServletException {
+        request.getSession().setAttribute("foo", "baz");
+      }
+    };
+
+    tester.setAttribute("callback_1", c_1);
+    tester.setAttribute("callback_2", c_2);
+
+    servletHolder.setInitParameter("test.callback", "callback_1");
+
+    ServletHolder sh2 = tester.addServlet(BasicServlet.class, "/request2");
+    sh2.setInitParameter("test.callback", "callback_2");
+
+    tester.start();
+    ContextManager.getInstance().putContext(
+        servletHolder.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    List<Cookie> cookies = getCookies(response);
+
+    Region r = getRegion();
+    assertEquals("bar",
+        ((HttpSession) r.get(cookies.get(0).getValue())).getAttribute("foo"));
+
+    request.setHeader("Cookie", "JSESSIONID=" + cookies.get(0).getValue());
+    request.setURI("/test/request2");
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    assertEquals("baz",
+        ((HttpSession) r.get(cookies.get(0).getValue())).getAttribute(
+            "foo"));
+  }
+
+  /**
+   * Test setting an attribute to null deletes it
+   */
+  @Test
+  public void testSetAttributeNullDeletesIt() throws Exception {
+    Callback c_1 = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException, ServletException {
+        request.getSession().setAttribute("foo", "bar");
+      }
+    };
+
+    // This is the callback used to invalidate the session
+    Callback c_2 = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException, ServletException {
+        request.getSession().setAttribute("foo", null);
+      }
+    };
+
+    tester.setAttribute("callback_1", c_1);
+    tester.setAttribute("callback_2", c_2);
+
+    servletHolder.setInitParameter("test.callback", "callback_1");
+
+    ServletHolder sh2 = tester.addServlet(BasicServlet.class, "/request2");
+    sh2.setInitParameter("test.callback", "callback_2");
+
+    tester.start();
+    ContextManager.getInstance().putContext(
+        servletHolder.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    List<Cookie> cookies = getCookies(response);
+
+    Region r = getRegion();
+    assertEquals("bar",
+        ((HttpSession) r.get(cookies.get(0).getValue())).getAttribute(
+            "foo"));
+
+    request.setHeader("Cookie", "JSESSIONID=" + cookies.get(0).getValue());
+    request.setURI("/test/request2");
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    assertNull(
+        ((HttpSession) r.get(cookies.get(0).getValue())).getAttribute(
+            "foo"));
+  }
+
+// Don't see how to do this currently as the SessionListener needs a full
+// web context to work in.
+
+//    /**
+//     * Test that sessions expire correctly
+//     */
+//    public void testSessionExpiration() throws Exception {
+//        Callback c_1 = new Callback() {
+//            @Override
+//            public void call(HttpServletRequest request, HttpServletResponse response)
+//                    throws IOException, ServletException {
+//                HttpSession s = request.getSession();
+//                s.setAttribute("foo", "bar");
+//                s.setMaxInactiveInterval(1);
+//
+//                PrintWriter out = response.getWriter();
+//                out.write(s.getId());
+//            }
+//        };
+//
+//        // This is the callback used to check if the session is still there
+//        Callback c_2 = new Callback() {
+//            @Override
+//            public void call(HttpServletRequest request, HttpServletResponse response)
+//                    throws IOException, ServletException {
+//                HttpSession s = request.getSession(false);
+//                String output;
+//                if (s == null) {
+//                    output = "null";
+//                } else {
+//                    output = s.getId();
+//                }
+//
+//                PrintWriter out = response.getWriter();
+//                out.write(output);
+//            }
+//        };
+//
+//        tester.addEventListener(new SessionListener());
+//        tester.setAttribute("callback_1", c_1);
+//        tester.setAttribute("callback_2", c_2);
+//
+//        servletHolder.setInitParameter("test.callback", "callback_1");
+//
+//        ServletHolder sh2 = tester.addServlet(BasicServlet.class, "/request2");
+//        sh2.setInitParameter("test.callback", "callback_2");
+//
+//        tester.start();
+//        ContextManager.getInstance().putContext(
+//                servletHolder.getServlet().getServletConfig().getServletContext());
+//
+//        request.setMethod("GET");
+//        request.setURI("/test/hello");
+//        request.setHeader("Host", "tester");
+//        request.setVersion("HTTP/1.0");
+//        response.parse(tester.getResponses(request.generate()));
+//
+//        String id = response.getContent();
+//
+//        // Wait for the session to expire
+//        Thread.sleep(2000);
+//
+//        request.setHeader("Cookie", "JSESSIONID=" + id);
+//        request.setURI("/test/request2");
+//        response.parse(tester.getResponses(request.generate()));
+//
+//        assertEquals("null", response.getContent());
+//
+//        Region r = getRegion();
+//        assertNull("Region should not contain session", r.get(id));
+//    }
+
+  /**
+   * Test that invalidating a session destroys it as well as the backend
+   * object.
+   */
+  @Test
+  public void testInvalidateSession1() throws Exception {
+    Callback c_1 = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException, ServletException {
+        request.getSession().setAttribute("foo", "bar");
+      }
+    };
+
+    // This is the callback used to invalidate the session
+    Callback c_2 = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException, ServletException {
+        request.getSession(false).invalidate();
+      }
+    };
+
+    tester.setAttribute("callback_1", c_1);
+    tester.setAttribute("callback_2", c_2);
+
+    servletHolder.setInitParameter("test.callback", "callback_1");
+
+    ServletHolder sh2 = tester.addServlet(BasicServlet.class, "/request2");
+    sh2.setInitParameter("test.callback", "callback_2");
+
+    tester.start();
+    ContextManager.getInstance().putContext(
+        servletHolder.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    List<Cookie> cookies = getCookies(response);
+    Region r = getRegion();
+    assertEquals("bar",
+        ((HttpSession) r.get(cookies.get(0).getValue())).getAttribute("foo"));
+
+    request.setHeader("Cookie", "JSESSIONID=" + cookies.get(0).getValue());
+    request.setURI("/test/request2");
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    assertNull("Region should not contain session",
+        r.get(cookies.get(0).getValue()));
+  }
+
+  /**
+   * Test that invalidating a session throws an exception on subsequent access.
+   */
+  @Test
+  public void testInvalidateSession2() throws Exception {
+    Callback c_1 = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException, ServletException {
+        HttpSession s = request.getSession();
+        s.invalidate();
+        PrintWriter out = response.getWriter();
+        try {
+          s.getAttribute("foo");
+        } catch (IllegalStateException iex) {
+          out.write("OK");
+        }
+      }
+    };
+
+    tester.setAttribute("callback_1", c_1);
+
+    servletHolder.setInitParameter("test.callback", "callback_1");
+
+    tester.start();
+    ContextManager.getInstance().putContext(
+        servletHolder.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    assertEquals("OK", response.getContent());
+  }
+
+  /**
+   * Test that invalidating a session throws an exception on subsequent access.
+   */
+  @Test
+  public void testInvalidateSession3() throws Exception {
+    Callback c_1 = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException, ServletException {
+        HttpSession s = request.getSession();
+        s.invalidate();
+        PrintWriter out = response.getWriter();
+        try {
+          s.getAttributeNames();
+        } catch (IllegalStateException iex) {
+          out.write("OK");
+        }
+      }
+    };
+
+    tester.setAttribute("callback_1", c_1);
+
+    servletHolder.setInitParameter("test.callback", "callback_1");
+
+    tester.start();
+    ContextManager.getInstance().putContext(
+        servletHolder.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    assertEquals("OK", response.getContent());
+  }
+
+  /**
+   * Test that invalidating a session throws an exception on subsequent access.
+   */
+  @Test
+  public void testInvalidateSession4() throws Exception {
+    Callback c_1 = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException, ServletException {
+        HttpSession s = request.getSession();
+        s.invalidate();
+        PrintWriter out = response.getWriter();
+        try {
+          s.getCreationTime();
+        } catch (IllegalStateException iex) {
+          out.write("OK");
+        }
+      }
+    };
+
+    tester.setAttribute("callback_1", c_1);
+
+    servletHolder.setInitParameter("test.callback", "callback_1");
+
+    tester.start();
+    ContextManager.getInstance().putContext(
+        servletHolder.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    assertEquals("OK", response.getContent());
+  }
+
+  /**
+   * Test that invalidating a session does not throw an exception for subsequent
+   * getId calls.
+   */
+  @Test
+  public void testInvalidateSession5() throws Exception {
+    Callback c_1 = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException, ServletException {
+        HttpSession s = request.getSession();
+        s.invalidate();
+        s.getId();
+        PrintWriter out = response.getWriter();
+        out.write("OK");
+      }
+    };
+
+    tester.setAttribute("callback_1", c_1);
+
+    servletHolder.setInitParameter("test.callback", "callback_1");
+
+    tester.start();
+    ContextManager.getInstance().putContext(
+        servletHolder.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    assertEquals("OK", response.getContent());
+  }
+
+  /**
+   * Test that invalidating a session throws an exception on subsequent access.
+   */
+  @Test
+  public void testInvalidateSession6() throws Exception {
+    Callback c_1 = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException, ServletException {
+        HttpSession s = request.getSession();
+        s.invalidate();
+        PrintWriter out = response.getWriter();
+        try {
+          s.getLastAccessedTime();
+        } catch (IllegalStateException iex) {
+          out.write("OK");
+        }
+      }
+    };
+
+    tester.setAttribute("callback_1", c_1);
+
+    servletHolder.setInitParameter("test.callback", "callback_1");
+
+    tester.start();
+    ContextManager.getInstance().putContext(
+        servletHolder.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    assertEquals("OK", response.getContent());
+  }
+
+  /**
+   * Test that invalidating a session does not throw an exception for
+   * subsequent getMaxInactiveInterval calls.
+   */
+
+// I've commented this out for now as Jetty seems to want to throw an
+// Exception here where the HttpServlet api doesn't specify that.
+  @Test
+  public void testInvalidateSession7() throws Exception {
+    Callback c_1 = new Callback() {
+      @Override
+      public void call(HttpServletRequest request,
+          HttpServletResponse response) throws IOException, ServletException {
+        HttpSession s = request.getSession();
+        s.invalidate();
+        s.getMaxInactiveInterval();
+        PrintWriter out = response.getWriter();
+        out.write("OK");
+      }
+    };
+
+    tester.setAttribute("callback_1", c_1);
+
+    servletHolder.setInitParameter("test.callback", "callback_1");
+
+    tester.start();
+    ContextManager.getInstance().putContext(
+        servletHolder.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    assertEquals("OK", response.getContent());
+  }
+
+  /**
+   * Test that invalidating a session does not throw an exception for subsequent
+   * getServletContext calls.
+   */
+  @Test
+  public void testInvalidateSession8() throws Exception {
+    Callback c_1 = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException, ServletException {
+        HttpSession s = request.getSession();
+        s.invalidate();
+        s.getServletContext();
+        PrintWriter out = response.getWriter();
+        out.write("OK");
+      }
+    };
+
+    tester.setAttribute("callback_1", c_1);
+
+    servletHolder.setInitParameter("test.callback", "callback_1");
+
+    tester.start();
+    ContextManager.getInstance().putContext(
+        servletHolder.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    assertEquals("OK", response.getContent());
+  }
+
+  /**
+   * Test that invalidating a session throws an exception on subsequent access.
+   */
+  @Test
+  public void testInvalidateSession9() throws Exception {
+    Callback c_1 = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException, ServletException {
+        HttpSession s = request.getSession();
+        s.invalidate();
+        PrintWriter out = response.getWriter();
+        try {
+          s.isNew();
+        } catch (IllegalStateException iex) {
+          out.write("OK");
+        }
+      }
+    };
+
+    tester.setAttribute("callback_1", c_1);
+
+    servletHolder.setInitParameter("test.callback", "callback_1");
+
+    tester.start();
+    ContextManager.getInstance().putContext(
+        servletHolder.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    assertEquals("OK", response.getContent());
+  }
+
+  /**
+   * Test that invalidating a session throws an exception on subsequent access.
+   */
+  @Test
+  public void testInvalidateSession10() throws Exception {
+    Callback c_1 = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException, ServletException {
+        HttpSession s = request.getSession();
+        s.invalidate();
+        PrintWriter out = response.getWriter();
+        try {
+          s.removeAttribute("foo");
+        } catch (IllegalStateException iex) {
+          out.write("OK");
+        }
+      }
+    };
+
+    tester.setAttribute("callback_1", c_1);
+
+    servletHolder.setInitParameter("test.callback", "callback_1");
+
+    tester.start();
+    ContextManager.getInstance().putContext(
+        servletHolder.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    assertEquals("OK", response.getContent());
+  }
+
+  /**
+   * Test that invalidating a session throws an exception on subsequent access.
+   */
+  @Test
+  public void testInvalidateSession11() throws Exception {
+    Callback c_1 = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException, ServletException {
+        HttpSession s = request.getSession();
+        s.invalidate();
+        PrintWriter out = response.getWriter();
+        try {
+          s.setAttribute("foo", "bar");
+        } catch (IllegalStateException iex) {
+          out.write("OK");
+        }
+      }
+    };
+
+    tester.setAttribute("callback_1", c_1);
+
+    servletHolder.setInitParameter("test.callback", "callback_1");
+
+    tester.start();
+    ContextManager.getInstance().putContext(
+        servletHolder.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    assertEquals("OK", response.getContent());
+  }
+
+  /**
+   * Test that invalidating a session does not throw an exception for subsequent
+   * setMaxInactiveInterval calls.
+   */
+  @Test
+  public void testInvalidateSession12() throws Exception {
+    Callback c_1 = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException, ServletException {
+        HttpSession s = request.getSession();
+        s.invalidate();
+        s.setMaxInactiveInterval(1);
+        PrintWriter out = response.getWriter();
+        out.write("OK");
+      }
+    };
+
+    tester.setAttribute("callback_1", c_1);
+
+    servletHolder.setInitParameter("test.callback", "callback_1");
+
+    tester.start();
+    ContextManager.getInstance().putContext(
+        servletHolder.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    assertEquals("OK", response.getContent());
+  }
+
+  /**
+   * Test that invalidating a session results in null being returned on
+   * subsequent getSession(false) calls.
+   */
+  @Test
+  public void testInvalidateSession13() throws Exception {
+    Callback c_1 = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException, ServletException {
+        HttpSession s = request.getSession();
+        s.invalidate();
+        s = request.getSession(false);
+        PrintWriter out = response.getWriter();
+        if (s == null) {
+          out.write("OK");
+        } else {
+          out.write(s.toString());
+        }
+      }
+    };
+
+    tester.setAttribute("callback_1", c_1);
+
+    servletHolder.setInitParameter("test.callback", "callback_1");
+
+    tester.start();
+    ContextManager.getInstance().putContext(
+        servletHolder.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    assertEquals("OK", response.getContent());
+  }
+
+
+  /**
+   * Test that we can invalidate and then recreate a new session
+   */
+  @Test
+  public void testInvalidateAndRecreateSession() throws Exception {
+    Callback c_1 = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException, ServletException {
+
+        PrintWriter out = response.getWriter();
+        out.write(request.getSession().getId());
+      }
+    };
+
+    Callback c_2 = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException, ServletException {
+        HttpSession s = request.getSession();
+        s.invalidate();
+
+        PrintWriter out = response.getWriter();
+        out.write(request.getSession().getId());
+      }
+    };
+
+    tester.setAttribute("callback_1", c_1);
+    tester.setAttribute("callback_2", c_2);
+
+    ServletHolder sh = tester.addServlet(BasicServlet.class, "/dispatch");
+    sh.setInitParameter("test.callback", "callback_2");
+
+    tester.start();
+    ContextManager.getInstance().putContext(
+        sh.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+    String session1 = response.getContent();
+
+    request.setHeader("Cookie", "JSESSIONID=" + session1);
+    request.setURI("/test/request2");
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    String session12 = response.getContent();
+    assertFalse("First and subsequent session ids must not be the same",
+        session1.equals(session12));
+  }
+
+
+  /**
+   * Test that creation time does not change on subsequent access
+   */
+  @Test
+  public void testGetCreationTime() throws Exception {
+    Callback c = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException {
+        HttpSession session = request.getSession();
+        PrintWriter out = response.getWriter();
+        out.write(Long.toString(session.getCreationTime()));
+      }
+    };
+
+    tester.setAttribute("callback_1", c);
+    tester.start();
+    ContextManager.getInstance().putContext(
+        servletHolder.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    long time1 = Long.parseLong(response.getContent());
+    assertTrue("Creation time should be positive", time1 > 0);
+
+    List<Cookie> cookies = getCookies(response);
+    request.setHeader("Cookie", "JSESSIONID=" + cookies.get(0).getValue());
+
+    try {
+      Thread.sleep(1000);
+    } catch (Exception ex) {
+    }
+
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+    long time2 = Long.parseLong(response.getContent());
+    assertTrue("Creation time should be the same across requests",
+        time1 == time2);
+  }
+
+  /**
+   * Test that the last accessed time is updated on subsequent access
+   */
+  @Test
+  public void testGetLastAccessedTime() throws Exception {
+    Callback c = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException {
+        HttpSession session = request.getSession();
+        PrintWriter out = response.getWriter();
+        out.write(Long.toString(session.getLastAccessedTime()));
+      }
+    };
+
+    tester.setAttribute("callback_1", c);
+    tester.start();
+    ContextManager.getInstance().putContext(
+        servletHolder.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    long time1 = Long.parseLong(response.getContent());
+//        assertTrue("Last accessed time should be positive", time1 > 0);
+
+    List<Cookie> cookies = getCookies(response);
+    request.setHeader("Cookie", "JSESSIONID=" + cookies.get(0).getValue());
+
+    Thread.sleep(1000);
+
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+    long time2 = Long.parseLong(response.getContent());
+    assertTrue("Last accessed time should be increasing across requests",
+        time2 > time1);
+  }
+
+  /**
+   * Test that the underlying native session remains the same across requests
+   */
+  @Test
+  public void testNativeSessionRemainsUnchanged() throws Exception {
+    Callback c = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException {
+        GemfireHttpSession session = (GemfireHttpSession) request.getSession();
+        PrintWriter out = response.getWriter();
+        out.write(session.getNativeSession().getId());
+      }
+    };
+
+    tester.setAttribute("callback_1", c);
+    tester.start();
+    ContextManager.getInstance().putContext(
+        servletHolder.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+    String nativeSessionId = response.getContent();
+
+    List<Cookie> cookies = getCookies(response);
+    String sessionId = cookies.get(0).getValue();
+    Region r = getRegion();
+
+    assertEquals(
+        "Cached native session id does not match servlet returned native session id",
+        nativeSessionId,
+        ((GemfireHttpSession) r.get(sessionId)).getNativeSession().getId());
+
+    request.setHeader("Cookie", "JSESSIONID=" + cookies.get(0).getValue());
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    assertEquals(
+        "Underlying native sessions must remain the same across requests",
+        nativeSessionId,
+        ((GemfireHttpSession) r.get(sessionId)).getNativeSession().getId());
+  }
+
+  /**
+   * Test session id embedded in the URL
+   */
+  @Test
+  public void testSessionIdEmbeddedInUrl() throws Exception {
+    Callback c = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException {
+        GemfireHttpSession session = (GemfireHttpSession) request.getSession();
+        PrintWriter out = response.getWriter();
+        out.write(session.getId());
+      }
+    };
+
+    tester.setAttribute("callback_1", c);
+    tester.start();
+    ContextManager.getInstance().putContext(
+        servletHolder.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+    List<Cookie> cookies = getCookies(response);
+    String sessionId = response.getContent();
+    assertEquals("Session ids should be the same", sessionId,
+        cookies.get(0).getValue());
+
+    request.setURI("/test/hello;jsessionid=" + sessionId);
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+    cookies = getCookies(response);
+
+    assertEquals("Session ids should be the same", sessionId,
+        cookies.get(0).getValue());
+  }
+
+
+  /**
+   * Test that request forward dispatching works
+   */
+  @Test
+  public void testDispatchingForward1() throws Exception {
+    Callback c_1 = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException, ServletException {
+        RequestDispatcher dispatcher = request.getRequestDispatcher("dispatch");
+        dispatcher.forward(request, response);
+
+        // This should not appear in the output
+        PrintWriter out = response.getWriter();
+        out.write("bang");
+      }
+    };
+
+    // This is the callback used by the forward servlet
+    Callback c_2 = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException, ServletException {
+        PrintWriter out = response.getWriter();
+        out.write("dispatched");
+      }
+    };
+
+    tester.setAttribute("callback_1", c_1);
+    tester.setAttribute("callback_2", c_2);
+
+    ServletHolder sh = tester.addServlet(BasicServlet.class, "/dispatch");
+    sh.setInitParameter("test.callback", "callback_2");
+
+    tester.start();
+    ContextManager.getInstance().putContext(
+        sh.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+    assertEquals("dispatched", response.getContent());
+
+    ContextManager.getInstance().removeContext(
+        sh.getServlet().getServletConfig().getServletContext());
+  }
+
+
+  /**
+   * Test that request include dispatching works
+   */
+  @Test
+  public void testDispatchingInclude() throws Exception {
+    Callback c_1 = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException, ServletException {
+        RequestDispatcher dispatcher = request.getRequestDispatcher("dispatch");
+        dispatcher.include(request, response);
+
+        // This *should* appear in the output
+        PrintWriter out = response.getWriter();
+        out.write("_bang");
+      }
+    };
+
+    // This is the callback used by the include servlet
+    Callback c_2 = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException, ServletException {
+        PrintWriter out = response.getWriter();
+        out.write("dispatched");
+      }
+    };
+
+    tester.setAttribute("callback_1", c_1);
+    tester.setAttribute("callback_2", c_2);
+
+    ServletHolder sh = tester.addServlet(BasicServlet.class, "/dispatch");
+    sh.setInitParameter("test.callback", "callback_2");
+
+    tester.start();
+    ContextManager.getInstance().putContext(
+        sh.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+    assertEquals("dispatched_bang", response.getContent());
+
+    ContextManager.getInstance().removeContext(
+        sh.getServlet().getServletConfig().getServletContext());
+  }
+
+
+  /**
+   * Test to try and simulate a failover scenario
+   */
+  @Test
+  public void testFailover1() throws Exception {
+    Callback c_1 = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException, ServletException {
+        HttpSession s = request.getSession();
+        s.setAttribute("foo", "bar");
+
+        PrintWriter out = response.getWriter();
+        out.write(request.getSession().getId());
+      }
+    };
+
+    Callback c_2 = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException, ServletException {
+        HttpSession s = request.getSession();
+
+        PrintWriter out = response.getWriter();
+        out.write((String) s.getAttribute("foo"));
+      }
+    };
+
+    tester.setAttribute("callback_1", c_1);
+    tester.setAttribute("callback_2", c_2);
+
+    ServletHolder sh = tester.addServlet(BasicServlet.class, "/request2");
+    sh.setInitParameter("test.callback", "callback_2");
+
+    tester.start();
+    ContextManager.getInstance().putContext(
+        sh.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+    String id = response.getContent();
+
+    // Now we simulate the failover by removing the native session from
+    // the stored session
+    Region r = getRegion();
+    GemfireHttpSession sessObj = (GemfireHttpSession) r.get(id);
+    sessObj.setNativeSession(null);
+
+    r.put(id, sessObj);
+
+    request.setHeader("Cookie", "JSESSIONID=" + id);
+    request.setURI("/test/request2");
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    assertEquals("bar", response.getContent());
+  }
+
+  @Test
+  public void testHttpSessionListener1() throws Exception {
+    HttpSessionListenerImpl listener = new HttpSessionListenerImpl();
+    tester.getContext().getSessionHandler().addEventListener(listener);
+
+    Callback c = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException {
+        HttpSession s = request.getSession();
+        // This is set in HttpSessionListenerImpl
+        String result = (String) s.getAttribute("gemfire-session-id");
+        response.getWriter().write(result);
+      }
+    };
+
+    tester.setAttribute("callback_1", c);
+    tester.start();
+    ContextManager.getInstance().putContext(
+        servletHolder.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    assertEquals(200, response.getStatus());
+
+    List<Cookie> cookies = getCookies(response);
+
+//        AbstractListener listener = RendezvousManager.getListener();
+    tester.stop();
+
+    assertTrue("Timeout waiting for events",
+        listener.await(1, TimeUnit.SECONDS));
+    assertEquals(ListenerEventType.SESSION_CREATED,
+        listener.events.get(0));
+    assertEquals(ListenerEventType.SESSION_DESTROYED,
+        listener.events.get(1));
+    assertEquals(cookies.get(0).getValue(), response.getContent());
+  }
+
+  @Test
+  public void testHttpSessionListener2() throws Exception {
+    HttpSessionListenerImpl2 listener = new HttpSessionListenerImpl2();
+    tester.getContext().getSessionHandler().addEventListener(listener);
+
+    Callback c = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException {
+        HttpSession s = request.getSession();
+        s.setAttribute("test01", "test01");
+        s = request.getSession(false);
+        s.invalidate();
+        response.getWriter().write(s.getId());
+      }
+    };
+
+    tester.setAttribute("callback_1", c);
+    tester.start();
+    ContextManager.getInstance().putContext(
+        servletHolder.getServlet().getServletConfig().getServletContext());
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    assertEquals(200, response.getStatus());
+
+    List<Cookie> cookies = getCookies(response);
+
+    tester.stop();
+
+    assertTrue("Timeout waiting for events",
+        listener.await(1, TimeUnit.SECONDS));
+    assertEquals(ListenerEventType.SESSION_CREATED,
+        listener.events.get(0));
+    assertEquals(ListenerEventType.SESSION_DESTROYED,
+        listener.events.get(1));
+    assertEquals(cookies.get(0).getValue(), response.getContent());
+  }
+
+
+
+
+//  @Test
+  public void testJsp() throws Exception {
+    tester.setResourceBase("target/test-classes");
+    ServletHolder jspHolder = tester.addServlet(JspServlet.class, "/test/*");
+    jspHolder.setInitOrder(1);
+
+    jspHolder.setInitParameter("scratchdir", tmpdir.getPath());
+
+    Callback c_1 = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response)
+          throws IOException, ServletException {
+        request.getSession().setAttribute("foo", "bar");
+        request.setAttribute("foo", "baz");
+        RequestDispatcher dispatcher = request.getRequestDispatcher(
+            "pagecontext.jsp");
+        dispatcher.forward(request, response);
+      }
+    };
+
+    tester.getContext().setClassLoader(Thread.currentThread().getContextClassLoader());
+    tester.setAttribute("callback_1", c_1);
+
+    tester.start();
+
+    request.setMethod("GET");
+    request.setURI("/test/hello");
+    request.setHeader("Host", "tester");
+    request.setVersion("HTTP/1.0");
+
+    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
+
+    assertEquals(200, response.getStatus());
+    assertEquals("baz", response.getContent().trim());
+  }
+
+
+  ////////////////////////////////////////////////////////////////////
+  // Private methods
+
+  /**
+   * Why doesn't HttpTester do this already??
+   */
+  private List<Cookie> getCookies(HttpTester.Response response) {
+    List<Cookie> cookies = new ArrayList<Cookie>();
+
+    Enumeration e = response.getValues("Set-Cookie");
+
+    while (e != null && e.hasMoreElements()) {
+      String header = (String) e.nextElement();
+      Cookie c = null;
+
+      StringTokenizer st = new StringTokenizer(header, ";");
+      while (st.hasMoreTokens()) {
+        String[] split = st.nextToken().split("=");
+        String param = split[0].trim();
+        String value = null;
+        if (split.length > 1) {
+          value = split[1].trim();
+        }
+        if ("version".equalsIgnoreCase(param)) {
+          c.setVersion(Integer.parseInt(value));
+        } else if ("comment".equalsIgnoreCase(param)) {
+          c.setComment(value);
+        } else if ("domain".equalsIgnoreCase(param)) {
+          c.setDomain(value);
+        } else if ("max-age".equalsIgnoreCase(param)) {
+          c.setMaxAge(Integer.parseInt(value));
+        } else if ("discard".equalsIgnoreCase(param)) {
+          c.setMaxAge(-1);
+        } else if ("path".equalsIgnoreCase(param)) {
+          c.setPath(value);
+        } else if ("secure".equalsIgnoreCase(param)) {
+          c.setSecure(true);
+        } else if ("httponly".equalsIgnoreCase(param)) {
+          // Ignored??
+        } else {
+          if (c == null) {
+            c = new Cookie(param, value);
+          } else {
+            throw new IllegalStateException("Unknown cookie param: " + param);
+          }
+        }
+      }
+
+      if (c != null) {
+        cookies.add(c);
+      }
+    }
+
+    return cookies;
+  }
+
+  private Region getRegion() {
+    // Yuck...
+    return ((GemfireSessionManager) ((SessionCachingFilter) filterHolder.getFilter()).getSessionManager()).getCache().getCache().getRegion(
+        "gemfire_modules_sessions");
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/4b56f5e4/modules/gemfire-modules-session-integration-test/src/test/java/com/gemstone/gemfire/modules/session/filter/MyServletTester.java
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session-integration-test/src/test/java/com/gemstone/gemfire/modules/session/filter/MyServletTester.java b/modules/gemfire-modules-session-integration-test/src/test/java/com/gemstone/gemfire/modules/session/filter/MyServletTester.java
new file mode 100644
index 0000000..43aed76
--- /dev/null
+++ b/modules/gemfire-modules-session-integration-test/src/test/java/com/gemstone/gemfire/modules/session/filter/MyServletTester.java
@@ -0,0 +1,33 @@
+/*=========================================================================
+ * 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.filter;
+
+import org.eclipse.jetty.servlet.ServletTester;
+
+/**
+ * Extend the base ServletTester class with a couple of helper methods. This
+ * depends on a patched ServletTester class which exposes the _server variable
+ * as package-private.
+ */
+public class MyServletTester extends ServletTester {
+
+  public boolean isStarted() {
+//    return _server.isStarted();
+    return false;
+  }
+
+  public boolean isStopped() {
+//    return _server.isStopped();
+    return false;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/4b56f5e4/modules/gemfire-modules-session-integration-test/src/test/java/com/gemstone/gemfire/modules/session/filter/ServletContextListenerImpl.java
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session-integration-test/src/test/java/com/gemstone/gemfire/modules/session/filter/ServletContextListenerImpl.java b/modules/gemfire-modules-session-integration-test/src/test/java/com/gemstone/gemfire/modules/session/filter/ServletContextListenerImpl.java
new file mode 100644
index 0000000..0eae4d5
--- /dev/null
+++ b/modules/gemfire-modules-session-integration-test/src/test/java/com/gemstone/gemfire/modules/session/filter/ServletContextListenerImpl.java
@@ -0,0 +1,48 @@
+/*=========================================================================
+ * 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.filter;
+
+import com.gemstone.gemfire.modules.session.filter.ListenerEventType;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+/**
+ * @author jdeppe
+ */
+public class ServletContextListenerImpl extends AbstractListener
+    implements ServletContextListener {
+
+  /**
+   * This is a 'custom' constructor which sets our latch count to 2. This is
+   * done because the earliest point, within our test code, where we can get a
+   * reference to the listener (in order to reset the latch count) an event
+   * *may* (more than likely) already have been fired.
+   */
+  public ServletContextListenerImpl() {
+    super(2);
+  }
+
+  @Override
+  public void contextInitialized(ServletContextEvent sce) {
+    events.add(ListenerEventType.SERVLET_CONTEXT_INITIALIZED);
+    latch.countDown();
+  }
+
+  @Override
+  public void contextDestroyed(ServletContextEvent sce) {
+    events.add(ListenerEventType.SERVLET_CONTEXT_DESTROYED);
+    latch.countDown();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/4b56f5e4/modules/gemfire-modules-session-integration-test/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session-integration-test/src/test/resources/log4j.properties b/modules/gemfire-modules-session-integration-test/src/test/resources/log4j.properties
new file mode 100644
index 0000000..b346714
--- /dev/null
+++ b/modules/gemfire-modules-session-integration-test/src/test/resources/log4j.properties
@@ -0,0 +1,12 @@
+# To change this template, choose Tools | Templates
+# and open the template in the editor.
+
+# Set root logger level to DEBUG and its only appender to A1.
+log4j.rootLogger=DEBUG, A1
+
+# A1 is set to be a ConsoleAppender.
+log4j.appender.A1=org.apache.log4j.ConsoleAppender
+
+# A1 uses PatternLayout.
+log4j.appender.A1.layout=org.apache.log4j.PatternLayout
+log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/4b56f5e4/modules/gemfire-modules-session-integration-test/src/test/resources/pagecontext.jsp
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session-integration-test/src/test/resources/pagecontext.jsp b/modules/gemfire-modules-session-integration-test/src/test/resources/pagecontext.jsp
new file mode 100644
index 0000000..17f0009
--- /dev/null
+++ b/modules/gemfire-modules-session-integration-test/src/test/resources/pagecontext.jsp
@@ -0,0 +1 @@
+<%= pageContext.getRequest().getAttribute("foo") %> <%-- PAGE_SCOPE --%>

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

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/4b56f5e4/modules/gemfire-modules-session/pom.xml
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session/pom.xml b/modules/gemfire-modules-session/pom.xml
new file mode 100644
index 0000000..b274ab3
--- /dev/null
+++ b/modules/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/4b56f5e4/modules/gemfire-modules-session/profiles.xml
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session/profiles.xml b/modules/gemfire-modules-session/profiles.xml
new file mode 100644
index 0000000..3bad1da
--- /dev/null
+++ b/modules/gemfire-modules-session/profiles.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<profilesXml xmlns="http://maven.apache.org/PROFILES/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/PROFILES/1.0.0 http://maven.apache.org/xsd/profiles-1.0.0.xsd">
+    <profiles>
+        <profile>
+            <id>netbeans-private</id>
+            <activation>
+                <property>
+                    <name>netbeans.execution</name>
+                    <value>true</value>
+                </property>
+            </activation>
+            <properties>
+                <netbeans.deployment.server.id>[/Users/jdeppe/apps/glassfishv3/glassfish]deployer:gfv3ee6:localhost:4848</netbeans.deployment.server.id>
+            </properties>
+        </profile>
+    </profiles>
+</profilesXml>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/4b56f5e4/modules/gemfire-modules-session/release/bin/cacheserver.bat
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session/release/bin/cacheserver.bat b/modules/gemfire-modules-session/release/bin/cacheserver.bat
new file mode 100755
index 0000000..2632dc7
--- /dev/null
+++ b/modules/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/4b56f5e4/modules/gemfire-modules-session/release/bin/cacheserver.sh
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session/release/bin/cacheserver.sh b/modules/gemfire-modules-session/release/bin/cacheserver.sh
new file mode 100755
index 0000000..e395001
--- /dev/null
+++ b/modules/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/4b56f5e4/modules/gemfire-modules-session/release/bin/gemfire.bat
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session/release/bin/gemfire.bat b/modules/gemfire-modules-session/release/bin/gemfire.bat
new file mode 100755
index 0000000..96d2564
--- /dev/null
+++ b/modules/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/4b56f5e4/modules/gemfire-modules-session/release/bin/gemfire.sh
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session/release/bin/gemfire.sh b/modules/gemfire-modules-session/release/bin/gemfire.sh
new file mode 100755
index 0000000..fa5f4cd
--- /dev/null
+++ b/modules/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/4b56f5e4/modules/gemfire-modules-session/release/bin/setenv.properties
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session/release/bin/setenv.properties b/modules/gemfire-modules-session/release/bin/setenv.properties
new file mode 100644
index 0000000..fc8918b
--- /dev/null
+++ b/modules/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/4b56f5e4/modules/gemfire-modules-session/release/conf/cache-client.xml
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session/release/conf/cache-client.xml b/modules/gemfire-modules-session/release/conf/cache-client.xml
new file mode 100755
index 0000000..c8444b2
--- /dev/null
+++ b/modules/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/4b56f5e4/modules/gemfire-modules-session/release/conf/cache-peer.xml
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session/release/conf/cache-peer.xml b/modules/gemfire-modules-session/release/conf/cache-peer.xml
new file mode 100755
index 0000000..1a49637
--- /dev/null
+++ b/modules/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/4b56f5e4/modules/gemfire-modules-session/release/conf/cache-server.xml
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session/release/conf/cache-server.xml b/modules/gemfire-modules-session/release/conf/cache-server.xml
new file mode 100755
index 0000000..6ee2223
--- /dev/null
+++ b/modules/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/4b56f5e4/modules/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/common/AbstractSessionCache.java
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/common/AbstractSessionCache.java b/modules/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/common/AbstractSessionCache.java
new file mode 100644
index 0000000..a60b154
--- /dev/null
+++ b/modules/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/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.common;
+
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.modules.session.catalina.internal.DeltaSessionStatistics;
+import com.gemstone.gemfire.modules.session.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/4b56f5e4/modules/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/common/CacheProperty.java
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/common/CacheProperty.java b/modules/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/common/CacheProperty.java
new file mode 100644
index 0000000..d8b7c64
--- /dev/null
+++ b/modules/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/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.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/4b56f5e4/modules/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/common/ClientServerSessionCache.java
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/common/ClientServerSessionCache.java b/modules/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/common/ClientServerSessionCache.java
new file mode 100644
index 0000000..a53bfbc
--- /dev/null
+++ b/modules/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/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.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);
+  }
+}