geode-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dschnei...@apache.org
Subject [10/20] incubator-geode git commit: GEODE-14: Imported modules from geode-1.0.0-SNAPSHOT-2.src.tar
Date Mon, 06 Jul 2015 21:46:31 GMT
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/4b56f5e4/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/Installer.java
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/Installer.java b/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/Installer.java
new file mode 100644
index 0000000..ee773d2
--- /dev/null
+++ b/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/Installer.java
@@ -0,0 +1,287 @@
+/*=========================================================================
+ * 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.installer;
+
+import com.gemstone.gemfire.modules.session.installer.args.Argument;
+import com.gemstone.gemfire.modules.session.installer.args.ArgumentProcessor;
+import com.gemstone.gemfire.modules.session.installer.args.ArgumentValues;
+import com.gemstone.gemfire.modules.session.installer.args.UnknownArgumentHandler;
+import com.gemstone.gemfire.modules.session.installer.args.UsageException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ *
+ */
+public class Installer {
+
+  private static final String GEMFIRE_FILTER_CLASS =
+      "com.gemstone.gemfire.modules.session.filter.SessionCachingFilter";
+
+  private static final String GEMFIRE_LISTENER_CLASS =
+      "com.gemstone.gemfire.modules.session.filter.SessionListener";
+
+  private ArgumentValues argValues;
+
+  private static final Argument ARG_HELP =
+      new Argument("-h", false).
+          setDescription("Displays this help message.");
+
+  private static Argument ARG_GEMFIRE_PARAMETERS =
+      new Argument("-p", false, "param=value").
+          setDescription("Specific parameter for inclusion into the "
+              + "session filter definition as a regular "
+              + "init-param. Can be given multiple times.");
+
+  private static Argument ARG_CACHE_TYPE =
+      new Argument("-t", false, "cache-type").
+          setDescription(
+              "Type of cache. Must be one of 'peer-to-peer' or "
+                  + "'client-server'. Default is peer-to-peer.").
+          setDefaults("peer-to-peer");
+
+  private static Argument ARG_WEB_XML_FILE =
+      new Argument("-w", true, "web.xml file").
+          setDescription("The web.xml file to be modified.");
+
+
+  /**
+   * Class main method
+   *
+   * @param args Arguments passed in via the command line
+   * @throws Exception in the event of any errors
+   */
+  public static void main(final String[] args) throws Exception {
+    new Installer(args).process();
+  }
+
+  public static void log(String message) {
+    System.err.println(message);
+  }
+
+
+  public Installer(String[] args) throws Exception {
+    final ArgumentProcessor processor = new ArgumentProcessor("Installer");
+
+    argValues = null;
+    try {
+      // These are ordered so as to keep the options alphabetical
+      processor.addArgument(ARG_HELP);
+      processor.addArgument(ARG_GEMFIRE_PARAMETERS);
+      processor.addArgument(ARG_CACHE_TYPE);
+      processor.addArgument(ARG_WEB_XML_FILE);
+
+      processor.setUnknownArgumentHandler(new UnknownArgumentHandler() {
+        @Override
+        public void handleUnknownArgument(
+            final String form, final String[] params) {
+          log("Unknown argument being ignored: "
+              + form + " (" + params.length + " params)");
+          log("Use '-h' argument to display usage");
+        }
+      });
+      argValues = processor.process(args);
+
+      if (argValues.isDefined(ARG_HELP)) {
+        final UsageException usageException =
+            new UsageException("Usage requested by user");
+        usageException.setUsage(processor.getUsage());
+        throw (usageException);
+      }
+
+    } catch (UsageException ux) {
+      final StringBuilder error = new StringBuilder();
+      error.append("\nERROR: ");
+      error.append(ux.getMessage());
+      error.append("\n");
+      if (ux.getUsage() != null) {
+        error.append(ux.getUsage());
+      }
+      log(error.toString());
+      System.exit(2);
+    }
+
+  }
+
+
+  /**
+   * The main entry point for processing
+   *
+   * @throws Exception if any errors occur.
+   */
+  public void process() throws Exception {
+    String argInputFile = argValues.getFirstResult(ARG_WEB_XML_FILE);
+
+    ByteArrayOutputStream output = new ByteArrayOutputStream();
+    InputStream input = new FileInputStream(argInputFile);
+
+    processWebXml(input, output);
+    input.close();
+
+    System.out.println(output.toString());
+  }
+
+
+  private void processWebXml(final InputStream webXml,
+      final OutputStream out) throws Exception {
+
+    Document doc = createWebXmlDoc(webXml);
+    mangleWebXml(doc);
+
+    streamXML(doc, out);
+  }
+
+
+  private Document createWebXmlDoc(final InputStream webXml)
+      throws Exception {
+    Document doc;
+    final DocumentBuilderFactory factory =
+        DocumentBuilderFactory.newInstance();
+    final DocumentBuilder builder = factory.newDocumentBuilder();
+    doc = builder.parse(webXml);
+
+    return doc;
+  }
+
+
+  private Document mangleWebXml(final Document doc) {
+    final Element docElement = doc.getDocumentElement();
+    final NodeList nodelist = docElement.getChildNodes();
+    Node firstFilter = null;
+    Node displayElement = null;
+    Node afterDisplayElement = null;
+
+    for (int i = 0; i < nodelist.getLength(); i++) {
+      final Node node = nodelist.item(i);
+      final String name = node.getNodeName();
+      if ("display-name".equals(name)) {
+        displayElement = node;
+      } else {
+        if ("filter".equals(name)) {
+          if (firstFilter == null) {
+            firstFilter = node;
+          }
+        }
+        if (displayElement != null && afterDisplayElement == null) {
+          afterDisplayElement = node;
+        }
+      }
+    }
+
+    Node initParam;
+    final Element filter = doc.createElement("filter");
+    append(doc, filter, "filter-name", "gemfire-session-filter");
+    append(doc, filter, "filter-class", GEMFIRE_FILTER_CLASS);
+
+    // Set the type of cache
+    initParam = append(doc, filter, "init-param", null);
+    append(doc, initParam, "param-name", "cache-type");
+    append(doc, initParam, "param-value",
+        argValues.getFirstResult(ARG_CACHE_TYPE));
+
+
+    if (argValues.isDefined(ARG_GEMFIRE_PARAMETERS)) {
+      for (String[] val : argValues.getAllResults(ARG_GEMFIRE_PARAMETERS)) {
+        String gfParam = val[0];
+        int idx = gfParam.indexOf("=");
+        initParam = append(doc, filter, "init-param", null);
+        append(doc, initParam, "param-name", gfParam.substring(0, idx));
+        append(doc, initParam, "param-value", gfParam.substring(idx + 1));
+      }
+    }
+
+    Node first = firstFilter;
+    if (first == null) {
+      if (afterDisplayElement != null) {
+        first = afterDisplayElement;
+      }
+    }
+    if (first == null) {
+      first = docElement.getFirstChild();
+    }
+    docElement.insertBefore(filter, first);
+    final Element filterMapping = doc.createElement("filter-mapping");
+    append(doc, filterMapping, "filter-name", "gemfire-session-filter");
+    append(doc, filterMapping, "url-pattern", "/*");
+    append(doc, filterMapping, "dispatcher", "FORWARD");
+    append(doc, filterMapping, "dispatcher", "INCLUDE");
+    append(doc, filterMapping, "dispatcher", "REQUEST");
+    append(doc, filterMapping, "dispatcher", "ERROR");
+    final Element contextListener = doc.createElement("listener");
+    append(doc, contextListener, "listener-class", GEMFIRE_LISTENER_CLASS);
+    docElement.insertBefore(filterMapping, after(docElement, "filter"));
+    docElement.insertBefore(contextListener,
+        after(docElement, "filter-mapping"));
+    return doc;
+  }
+
+  private Node after(final Node parent, final String nodeName) {
+    final NodeList nodelist = parent.getChildNodes();
+    int index = -1;
+    for (int i = 0; i < nodelist.getLength(); i++) {
+      final Node node = nodelist.item(i);
+      final String name = node.getNodeName();
+      if (nodeName.equals(name)) {
+        index = i;
+      }
+    }
+    if (index == -1)
+      return null;
+    if (nodelist.getLength() > (index + 1)) {
+      return nodelist.item(index + 1);
+    }
+    return null;
+  }
+
+  private Node append(final Document doc, final Node parent,
+      final String element,
+      final String value) {
+    final Element child = doc.createElement(element);
+    if (value != null)
+      child.setTextContent(value);
+    parent.appendChild(child);
+    return child;
+  }
+
+  private void streamXML(final Document doc, final OutputStream out) {
+    try {// Use a Transformer for output
+      final TransformerFactory tFactory = TransformerFactory.newInstance();
+      final Transformer transformer = tFactory.newTransformer();
+      if (doc.getDoctype() != null) {
+        final String systemId = doc.getDoctype().getSystemId();
+        final String publicId = doc.getDoctype().getPublicId();
+        transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, publicId);
+        transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, systemId);
+      }
+      transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+      transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount",
+          "4");
+      final DOMSource source = new DOMSource(doc);
+      final StreamResult result = new StreamResult(out);
+      transformer.transform(source, result);
+    } catch (final Exception e) {
+      e.printStackTrace();
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/4b56f5e4/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/JarClassLoader.java
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/JarClassLoader.java b/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/JarClassLoader.java
new file mode 100644
index 0000000..1d850bf
--- /dev/null
+++ b/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/JarClassLoader.java
@@ -0,0 +1,114 @@
+/*=========================================================================
+ * 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.installer;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Enumeration;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+/**
+ * Classloader, grabbed from the web, which allows finding classes in jars
+ * within jars. This is used to check whether a listener, as found in web.xml,
+ * is a ServletContextListener
+ */
+public class JarClassLoader extends URLClassLoader {
+
+  public JarClassLoader(URL[] urls, ClassLoader parent) {
+    super(urls, parent);
+
+    try {
+      for (URL url : urls) {
+        if (isJar(url.getFile())) {
+          addJarResource(new File(url.getPath()));
+        }
+      }
+    } catch (IOException e) {
+      e.printStackTrace();
+    }
+  }
+
+  private void addJarResource(File file) throws IOException {
+    JarFile jarFile = new JarFile(file);
+    addURL(file.toURL());
+    Enumeration<JarEntry> jarEntries = jarFile.entries();
+    while (jarEntries.hasMoreElements()) {
+      JarEntry jarEntry = jarEntries.nextElement();
+      if (!jarEntry.isDirectory() && isJar(jarEntry.getName())) {
+        addJarResource(jarEntryAsFile(jarFile, jarEntry));
+      }
+    }
+  }
+
+  @Override
+  protected synchronized Class<?> loadClass(String name, boolean resolve)
+      throws ClassNotFoundException {
+    try {
+      Class<?> clazz = findLoadedClass(name);
+      if (clazz == null) {
+        clazz = findClass(name);
+        if (resolve) {
+          resolveClass(clazz);
+        }
+      }
+      return clazz;
+    } catch (ClassNotFoundException e) {
+      return super.loadClass(name, resolve);
+    }
+  }
+
+  private static void close(Closeable closeable) {
+    if (closeable != null) {
+      try {
+        closeable.close();
+      } catch (IOException e) {
+        e.printStackTrace();
+      }
+    }
+  }
+
+  private static boolean isJar(String fileName) {
+    return fileName != null && (fileName.toLowerCase().endsWith(".jar") ||
+        fileName.toLowerCase().endsWith(".war") ||
+        fileName.toLowerCase().endsWith(".ear"));
+  }
+
+  private static File jarEntryAsFile(JarFile jarFile,
+      JarEntry jarEntry) throws IOException {
+    InputStream input = null;
+    OutputStream output = null;
+    try {
+      String name = jarEntry.getName().replace('/', '_');
+      int i = name.lastIndexOf(".");
+      String extension = i > -1 ? name.substring(i) : "";
+      File file = File.createTempFile(
+          name.substring(0, name.length() - extension.length()) + ".",
+          extension);
+      file.deleteOnExit();
+      input = jarFile.getInputStream(jarEntry);
+      output = new FileOutputStream(file);
+      int readCount;
+      byte[] buffer = new byte[4096];
+      while ((readCount = input.read(buffer)) != -1) {
+        output.write(buffer, 0, readCount);
+      }
+      return file;
+    } finally {
+      close(input);
+      close(output);
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/4b56f5e4/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/args/Argument.java
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/args/Argument.java b/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/args/Argument.java
new file mode 100644
index 0000000..bb1a73d
--- /dev/null
+++ b/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/args/Argument.java
@@ -0,0 +1,265 @@
+/*=========================================================================
+ * 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.installer.args;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Class representing a single command line argument.
+ */
+public class Argument {
+
+  /**
+   * Parameter names.
+   */
+  private final String[] paramNames;
+
+  /**
+   * Default values for the parameters when not explicitly set.
+   */
+  private String[] defaults;
+
+  /**
+   * Environment variable names forfor each parameter where values will be
+   * pulled in, if not explicitly provided and if the environment variable
+   * exists.
+   */
+  private String[] envVars;
+
+  /**
+   * Flag indicating whether this argument is required on the command line.
+   */
+  private final boolean required;
+
+  /**
+   * Handler used to hook into processing.
+   */
+  private ArgumentHandler handler;
+
+  /**
+   * List of all representation forms.
+   */
+  private final List<String> forms = new ArrayList<String>();
+
+  /**
+   * Usage description.
+   */
+  private String description;
+
+  ///////////////////////////////////////////////////////////////////////////
+  // Constructor:
+
+  /**
+   * Contructor to create an argument definition.
+   *
+   * @param primaryForm    the form of the argument (e.g., --foo).  Should start
+   *                       with a dash.
+   * @param argRequired    flag indicating whether or not the argument is
+   *                       required to be onthe command line
+   * @param parameterNames names of the parameters to this argument for use in
+   *                       the usage generation
+   */
+  public Argument(
+      final String primaryForm,
+      final boolean argRequired,
+      final String... parameterNames) {
+    forms.add(primaryForm);
+    paramNames = parameterNames;
+    required = argRequired;
+  }
+
+  /**
+   * Returns the number of parameters that this argument takes.
+   *
+   * @return parameter count
+   */
+  public int getParameterCount() {
+    return paramNames.length;
+  }
+
+  /**
+   * Returns the name of the parameter position requested.
+   *
+   * @param idx parameter index
+   * @return parameter name
+   */
+  public String getParameterName(final int idx) {
+    return paramNames[idx];
+  }
+
+  /**
+   * Returns whether or not this argument is required to be defined.
+   *
+   * @return true if required, false if optional
+   */
+  public boolean isRequired() {
+    return required;
+  }
+
+  /**
+   * Determines if the argument provisioning has been done via the environment.
+   */
+  public boolean isDefinedInEnv() {
+    if (envVars == null || paramNames.length == 0) {
+      return false;
+    }
+    for (String var : envVars) {
+      if (System.getenv(var) == null) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Sets the argument handler.
+   *
+   * @param aHandler argument handler
+   * @return this argument (for chained calls)
+   */
+  public Argument setArgumentHandler(final ArgumentHandler aHandler) {
+    handler = aHandler;
+    return this;
+  }
+
+  /**
+   * Returns the argument handler.
+   *
+   * @return argument handler
+   */
+  public ArgumentHandler getArgumentHandler() {
+    return handler;
+  }
+
+  /**
+   * Adds a possible representation of the command line argument.
+   *
+   * @param aliasName additional form to accept
+   * @return this argument (for chained calls)
+   */
+  public Argument addForm(final String aliasName) {
+    forms.add(aliasName);
+    return this;
+  }
+
+  /**
+   * Returns the primary form of the argument.
+   *
+   * @return primary form
+   */
+  public String getPrimaryForm() {
+    if (forms.isEmpty()) {
+      return null;
+    } else {
+      return forms.get(0);
+    }
+  }
+
+  /**
+   * Returns a list of all valid representations of this command line argument.
+   *
+   * @return list of all registered forms
+   */
+  public List<String> getForms() {
+    return forms;
+  }
+
+  /**
+   * Sets a usage description for this argument.
+   *
+   * @param str usage description
+   * @return this argument (for chained calls)
+   */
+  public Argument setDescription(final String str) {
+    description = str;
+    return this;
+  }
+
+  /**
+   * Returns a usage description of this argument.
+   *
+   * @return description
+   */
+  public String getDescription() {
+    return description;
+  }
+
+  /**
+   * Sets the default values when no explicit values were provided.
+   *
+   * @param newDefaults default values for all argument parameters
+   * @return this argument (for chained calls)
+   */
+  public Argument setDefaults(final String... newDefaults) {
+    if (newDefaults.length != paramNames.length) {
+      throw (new IllegalArgumentException(
+          "Defaults array length provided is not the correct size"));
+    }
+    defaults = newDefaults;
+    return this;
+  }
+
+  /**
+   * Returns the defaults.
+   *
+   * @return default parameter values
+   */
+  public String[] getDefaults() {
+    return defaults;
+  }
+
+  /**
+   * Sets the environment variables which will be checked for values before
+   * falling back on the default values.
+   *
+   * @param newEnvVars environment variable name array
+   * @return this argument (for chained calls)
+   */
+  public Argument setEnvVars(final String... newEnvVars) {
+    if (newEnvVars.length != paramNames.length) {
+      throw (new IllegalArgumentException(
+          "Environment variables array length provided is not "
+              + "the correct size"));
+    }
+    envVars = newEnvVars;
+    return this;
+  }
+
+  /**
+   * Returns the environment variable names for each parameter.
+   *
+   * @return environment variable names
+   */
+  public String[] getEnvVars() {
+    return envVars;
+  }
+
+  /**
+   * Returns a human readable form.
+   *
+   * @return human readable string
+   */
+  @Override
+  public String toString() {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("[Argument '");
+    builder.append(forms.get(0));
+    builder.append("'");
+    if (paramNames.length > 0) {
+      for (int i = 0; i < paramNames.length; i++) {
+        builder.append(" <");
+        builder.append(paramNames[i]);
+        builder.append(">");
+      }
+    }
+    builder.append("]");
+    return builder.toString();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/4b56f5e4/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/args/ArgumentHandler.java
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/args/ArgumentHandler.java b/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/args/ArgumentHandler.java
new file mode 100644
index 0000000..a165148
--- /dev/null
+++ b/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/args/ArgumentHandler.java
@@ -0,0 +1,28 @@
+/*=========================================================================
+ * 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.installer.args;
+
+/**
+ * Interface specifying the requirements for objects wiching to be able to
+ * examine arguments (potentially tweaking parameters) at the time of parsing,
+ * thereby allowing for usage display to occur automatically.
+ */
+public interface ArgumentHandler {
+
+  /**
+   * Process the argument values specified.
+   *
+   * @param arg    argument definition
+   * @param form   form which was used on the command line
+   * @param params parameters supplied to the argument
+   * @throws UsageException when usage was suboptimal
+   */
+  void handleArgument(Argument arg, String form, String[] params)
+      throws UsageException;
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/4b56f5e4/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/args/ArgumentProcessor.java
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/args/ArgumentProcessor.java b/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/args/ArgumentProcessor.java
new file mode 100644
index 0000000..950f2f0
--- /dev/null
+++ b/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/args/ArgumentProcessor.java
@@ -0,0 +1,387 @@
+/*=========================================================================
+ * 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.installer.args;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+
+/**
+ * This class is used to process command line arguments for Java programs in a
+ * flexible and powerful manner.
+ */
+public class ArgumentProcessor {
+  /**
+   * Logger.
+   */
+  private static final Logger LOG =
+      Logger.getLogger(ArgumentProcessor.class.getName());
+
+  /**
+   * Description line length.
+   */
+  private static final int LINE_LENGTH = 60;
+
+  /**
+   * Map containing all arguments defined, indexed by their unique IDs.
+   */
+  private final List<Argument> args = new ArrayList<Argument>();
+
+  /**
+   * Unknown argument handler.
+   */
+  private UnknownArgumentHandler handler;
+
+  /**
+   * Program name to display in usage.
+   */
+  private String programName;
+
+  ///////////////////////////////////////////////////////////////////////////
+  // Classes:
+
+  /**
+   * Structure used to represent an argument match.
+   */
+  private static class Match {
+    /**
+     * The argument which matched.
+     */
+    private final Argument arg;
+
+    /**
+     * The specific form which matched.
+     */
+    private final String form;
+
+    /**
+     * The parameters to the argument form.
+     */
+    private final String[] params;
+
+    /**
+     * Constructor.
+     *
+     * @param theArgument the argument which matched
+     * @param theForm     the form used
+     * @param theParams   the parameters supplied
+     */
+    public Match(
+        final Argument theArgument,
+        final String theForm, final String[] theParams) {
+      arg = theArgument;
+      form = theForm;
+      params = theParams;
+    }
+
+    /**
+     * Accessor.
+     *
+     * @return argument which matched
+     */
+    public Argument getArgument() {
+      return arg;
+    }
+
+    /**
+     * Accessor.
+     *
+     * @return form which was used
+     */
+    public String getForm() {
+      return form;
+    }
+
+    /**
+     * Accessor.
+     *
+     * @return parameters supplied
+     */
+    public String[] getParams() {
+      return params;
+    }
+  }
+
+  ///////////////////////////////////////////////////////////////////////////
+  // Constructors:
+
+  /**
+   * Creates a new Argument processor instance for te program name given.
+   *
+   * @param progName program name used in usage
+   */
+  public ArgumentProcessor(final String progName) {
+    programName = progName;
+  }
+
+
+  ///////////////////////////////////////////////////////////////////////////
+  // Public methods:
+
+  /**
+   * Adds a new argument.
+   *
+   * @param arg argument to add
+   */
+  public void addArgument(final Argument arg) {
+    args.add(arg);
+  }
+
+  /**
+   * Sets the handler to call when an unknown argument is encountered.
+   *
+   * @param aHandler unknown arg handler, or null to unset
+   */
+  public void setUnknownArgumentHandler(
+      final UnknownArgumentHandler aHandler) {
+    handler = aHandler;
+  }
+
+  /**
+   * Process the command line arguments provided.
+   *
+   * @param programArgs command line arguments supplied to program
+   * @return argument values parsed out of command line
+   * @throws UsageException when usge sucked
+   */
+  public ArgumentValues process(final String[] programArgs)
+      throws UsageException {
+    ArgumentHandler argHandler;
+    final ArgumentValues result = new ArgumentValues();
+    List<Argument> unmatched;
+    List<Match> matches;
+
+    // Find all argument matches and set postArgs
+    matches = checkMatches(programArgs, result);
+
+    // Find arguments which didnt match
+    unmatched = new ArrayList<Argument>();
+    unmatched.addAll(args);
+    for (Match match : matches) {
+      unmatched.remove(match.getArgument());
+    }
+
+    // Error on unmatched yet required args
+    for (Argument arg : unmatched) {
+      if (arg.isRequired() && !arg.isDefinedInEnv()) {
+        final UsageException usageException = new UsageException(
+            "Required argument not provided: " + arg);
+        usageException.setUsage(getUsage());
+        throw usageException;
+      }
+    }
+
+    // Handle the arguments
+    for (Match match : matches) {
+      final Argument arg = match.getArgument();
+      argHandler = arg.getArgumentHandler();
+      if (argHandler != null) {
+        argHandler.handleArgument(
+            arg, match.getForm(), match.getParams());
+      }
+      result.addResult(arg, match.getParams());
+    }
+
+    return result;
+  }
+
+
+  /**
+   * Generates command line usage text for display to user.
+   *
+   * @return usage to dusplay to user
+   */
+  public String getUsage() {
+    final StringBuilder builder = new StringBuilder();
+    List<String> descriptionLines;
+    final String blank20 = "                    ";
+
+    builder.append("\nUSAGE: ");
+    if (programName == null) {
+      builder.append("<program>");
+    } else {
+      builder.append(programName);
+    }
+    if (args.isEmpty()) {
+      builder.append("\nNo arguments supported.\n");
+    } else {
+      builder.append(" <args>\nWHERE <args>:\n\n");
+      for (Argument arg : args) {
+        for (String form : arg.getForms()) {
+          builder.append("    ");
+          builder.append(form);
+
+          for (int i = 0; i < arg.getParameterCount(); i++) {
+            builder.append(" <");
+            builder.append(arg.getParameterName(i));
+            builder.append(">");
+          }
+          builder.append("\n");
+        }
+
+        descriptionLines =
+            breakupString(arg.getDescription(), LINE_LENGTH);
+        if (descriptionLines.isEmpty()) {
+          builder.append(blank20);
+          builder.append("No argument description provided.");
+          builder.append("\n\n");
+        } else {
+          for (String line : descriptionLines) {
+            builder.append(blank20);
+            builder.append(line.trim());
+            builder.append("\n");
+          }
+          builder.append("\n");
+        }
+      }
+    }
+    builder.append("\n");
+
+    return builder.toString();
+  }
+
+
+  ///////////////////////////////////////////////////////////////////////////
+  // Private methods:
+
+  /**
+   * Builds a listof all argument matches and sets the postArgs array.
+   *
+   * @param programArgs command line arguments to search through
+   * @param values      values object in which to store results
+   * @return list of matches
+   * @throws UsageException when there is EBKAC
+   */
+  private List<Match> checkMatches(
+      final String[] programArgs, final ArgumentValues values)
+      throws UsageException {
+    final List<Match> result = new ArrayList<Match>();
+    Match match;
+    String[] params;
+    String[] postArgs;
+    int idx = 0;
+    int idx2;
+
+    while (idx < programArgs.length) {
+      // Check for end-of-parameters arg
+      if ("--".equals(programArgs[idx])) {
+        if (++idx < programArgs.length) {
+          postArgs = new String[programArgs.length - idx];
+          System.arraycopy(programArgs, idx,
+              postArgs, 0, postArgs.length);
+          values.setPostArgs(postArgs);
+        }
+        // We're done processing args'
+        break;
+      }
+
+      // Determine parameter count
+      idx2 = idx;
+      while ((idx2 + 1) < programArgs.length
+          && programArgs[idx2 + 1].charAt(0) != '-') {
+        idx2++;
+      }
+
+      // Generate parameter array
+      params = new String[idx2 - idx];
+      System.arraycopy(programArgs, idx + 1, params, 0, params.length);
+
+      LOG.fine("Arg: " + programArgs[idx]);
+      LOG.fine("Params: " + params.length);
+
+      // Find first argument matches
+      match = null;
+      for (Argument arg : args) {
+        match = checkMatch(programArgs[idx], arg, params);
+        if (match != null) {
+          result.add(match);
+          LOG.fine("Match found: ");
+          LOG.fine("     ID: " + arg);
+          LOG.fine("   Form: " + match.getForm());
+          break;
+        }
+      }
+      if (match == null) {
+        if (handler == null) {
+          final UsageException usageException = new UsageException(
+              "Unknown argument: " + programArgs[idx]
+                  + " with " + params.length + " parameters.");
+          usageException.setUsage(getUsage());
+          throw (usageException);
+        } else {
+          handler.handleUnknownArgument(programArgs[idx], params);
+        }
+      }
+
+      idx += params.length + 1;
+    }
+
+    return result;
+  }
+
+  /**
+   * Checks to see if an rgument form matches the suppies parameter list.
+   *
+   * @param argName argument name
+   * @param arg     argument
+   * @param params  parameters supplied
+   * @return match object on match, null otherwise
+   */
+  private Match checkMatch(
+      final String argName, final Argument arg, final String[] params) {
+    // Look for a matching form
+    for (String form : arg.getForms()) {
+      if (
+          form.equals(argName)
+              && arg.getParameterCount() == params.length) {
+        return new Match(arg, form, params);
+      }
+    }
+
+    return null;
+  }
+
+  /**
+   * Breaks up a string into sub-strings, each with a length equal to or less
+   * than the max length specified.
+   *
+   * @param str       string to break up
+   * @param maxLength maximum line length to use
+   * @return broken up string
+   */
+  private List<String> breakupString(
+      final String str, final int maxLength) {
+    final List<String> result = new ArrayList<String>();
+    int startIdx = -1;
+    int lastIdx;
+    int idx;
+
+    if (str == null) {
+      return result;
+    }
+
+    do {
+      idx = startIdx;
+      do {
+        lastIdx = idx;
+        idx = str.indexOf(' ', lastIdx + 1);
+        LOG.fine("startIdx=" + startIdx + "  lastIdx=" + lastIdx
+            + "  idx=" + idx);
+        if (idx < 0) {
+          // Canot break line up any further
+          result.add(str.substring(startIdx + 1));
+          return result;
+        }
+      } while ((idx - startIdx) <= maxLength);
+
+      result.add(str.substring(startIdx + 1, lastIdx));
+      startIdx = lastIdx;
+    } while (true);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/4b56f5e4/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/args/ArgumentValues.java
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/args/ArgumentValues.java b/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/args/ArgumentValues.java
new file mode 100644
index 0000000..7be926c
--- /dev/null
+++ b/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/args/ArgumentValues.java
@@ -0,0 +1,212 @@
+/*=========================================================================
+ * 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.installer.args;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Result object capturing the result of processing command line arguments.
+ */
+public class ArgumentValues {
+
+  /**
+   * Storage location for all arguments found after the "--" pseudo-arg.
+   */
+  private String[] postArgs = new String[]{};
+
+  /**
+   * Storage location for the command line argument values.
+   */
+  private final Map<Argument, List<String[]>> values =
+      new LinkedHashMap<Argument, List<String[]>>();
+
+  /**
+   * Constructor.
+   */
+  ArgumentValues() {
+    // Empty.
+  }
+
+  /**
+   * Sets the post-arguments found after the "--" pseudo-argument.
+   *
+   * @param newPostArgs arguments defined after the special "--" argument
+   */
+  void setPostArgs(final String[] newPostArgs) {
+    postArgs = newPostArgs;
+  }
+
+  /**
+   * After processing the command line arguments, this method may be used to
+   * return all arguments which were excluded from processing by their placement
+   * after the "<code>--</code>" psuedo-argument.
+   *
+   * @return all unprocess arguments
+   */
+  public String[] getPostArgs() {
+    return postArgs;
+  }
+
+  /**
+   * Sets the data values found for a specific argument.
+   *
+   * @param arg         argument
+   * @param paramValues parameter values for the argument
+   */
+  public void addResult(final Argument arg, final String[] paramValues) {
+    List<String[]> list = values.get(arg);
+    if (list == null) {
+      list = new ArrayList<String[]>();
+      list.add(paramValues);
+      values.put(arg, list);
+    } else {
+      list.add(paramValues);
+    }
+  }
+
+  /**
+   * Returns a list of all defined arguments.
+   *
+   * @return set of arguments
+   */
+  public Set<Argument> getDefinedArguments() {
+    return values.keySet();
+  }
+
+  /**
+   * Counts the number of arguments defined on the command line which are in the
+   * list provided.
+   *
+   * @param ofThese the arguments to search for, or null to count all supplied
+   *                arguments
+   * @return count of the defined arguments
+   */
+  public int getDefinedCount(Argument... ofThese) {
+    if (ofThese.length == 0) {
+      return values.keySet().size();
+    }
+
+    int count = 0;
+    for (Argument arg : values.keySet()) {
+      boolean found = false;
+      for (int i = 0; !found && i < ofThese.length; i++) {
+        if (ofThese[i].equals(arg)) {
+          count++;
+          found = true;
+        }
+      }
+    }
+    return count;
+  }
+
+  /**
+   * Returns whetheror not the command line argument was actually provided on
+   * the command line.
+   *
+   * @param arg argument to query
+   * @return true if the argument is defined by the command line, false
+   * otherwise
+   */
+  public boolean isDefined(final Argument arg) {
+    final List<String[]> result = values.get(arg);
+    return (result != null);
+  }
+
+  /**
+   * Returns all results for the specified argument.  If a command line option
+   * is specified more than once, this is the method to use to get all values.
+   *
+   * @param arg argument to query
+   * @return list of all parameter lists defined for this argument
+   */
+  public List<String[]> getAllResults(final Argument arg) {
+    List<String[]> result = values.get(arg);
+
+    if (result == null) {
+      final String[] envVars = arg.getEnvVars();
+      final String[] defaults = arg.getDefaults();
+      final String[] vals = new String[arg.getParameterCount()];
+      boolean found = defaults != null;
+
+      for (int i = 0; i < arg.getParameterCount(); i++) {
+        if (defaults != null) {
+          vals[i] = defaults[i];
+        }
+        if (envVars != null) {
+          String val = System.getenv(envVars[i]);
+          if (val != null) {
+            found = true;
+            vals[i] = val;
+          }
+        }
+      }
+
+      if (found) {
+        result = new ArrayList<String[]>();
+        result.add(vals);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Convenience method to retrieve the first instance of the command line
+   * argument's values.
+   *
+   * @param arg argument to query
+   * @return first parameter list defined for this argument
+   */
+  public String[] getResult(final Argument arg) {
+    final List<String[]> all = getAllResults(arg);
+    if (all == null) {
+      return null;
+    } else {
+      return all.get(0);
+    }
+  }
+
+  /**
+   * Convenience method to return the first value of the first instance of the
+   * command line argument values for the specified argument.
+   *
+   * @param arg argument to query
+   * @return first parameter of the first list of parameters supplied
+   */
+  public String getFirstResult(final Argument arg) {
+    final String[] all = getResult(arg);
+    if (all == null) {
+      return null;
+    } else {
+      return all[0];
+    }
+  }
+
+  /**
+   * Convenience method to return the result of getFirstResult method as an
+   * integer.
+   *
+   * @param arg            argument to query
+   * @param undefinedValue value to return when argument is not defined or is
+   *                       illegally defined
+   * @return value specified, or default value provided
+   */
+  public int getFirstResultAsInt(
+      final Argument arg, final int undefinedValue) {
+    final String value = getFirstResult(arg);
+    if (value == null) {
+      return undefinedValue;
+    } else {
+      return Integer.parseInt(value);
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/4b56f5e4/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/args/URLArgumentHandler.java
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/args/URLArgumentHandler.java b/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/args/URLArgumentHandler.java
new file mode 100644
index 0000000..f0800d4
--- /dev/null
+++ b/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/args/URLArgumentHandler.java
@@ -0,0 +1,67 @@
+/*=========================================================================
+ * 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.installer.args;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Argument handler implementation which accepts file paths or URLs and
+ * normalizes the parameters to URLs.
+ */
+public class URLArgumentHandler implements ArgumentHandler {
+
+  /**
+   * Logger.
+   */
+  private static final Logger LOG =
+      Logger.getLogger(URLArgumentHandler.class.getName());
+
+  /**
+   * Ensure that the argument is either a file path or a properly formatted URL.
+   *  If it is a file path, convert to a URL.  If neither, throws a
+   * UsageException.
+   *
+   * @param arg        argument
+   * @param form       form used
+   * @param parameters parameters supplied
+   * @throws UsageException when file not found or not a workable URL
+   */
+  public void handleArgument(
+      final Argument arg,
+      final String form,
+      final String[] parameters)
+      throws UsageException {
+    final File file = new File(parameters[0]);
+    URL result = null;
+
+    if (file.exists()) {
+      try {
+        result = file.toURI().toURL();
+      } catch (MalformedURLException mux) {
+        LOG.log(Level.FINEST, "Caught Exception", mux);
+      }
+    }
+    if (result == null) {
+      try {
+        result = new URL(parameters[0]);
+      } catch (MalformedURLException mux) {
+        LOG.log(Level.FINEST, "Caught Exception", mux);
+      }
+    }
+    if (result == null) {
+      throw (new UsageException(
+          "Argument parameter value is not a valid file "
+              + "path or URL: " + arg));
+    }
+    parameters[0] = result.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/4b56f5e4/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/args/UnknownArgumentHandler.java
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/args/UnknownArgumentHandler.java b/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/args/UnknownArgumentHandler.java
new file mode 100644
index 0000000..1cf0ecc
--- /dev/null
+++ b/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/args/UnknownArgumentHandler.java
@@ -0,0 +1,19 @@
+package com.gemstone.gemfire.modules.session.installer.args;
+
+/**
+ * Interface defining unknown argument handlers, given the opportunity to either
+ * ignore the issue or force the parameter to be dealt with.
+ */
+public interface UnknownArgumentHandler {
+
+  /**
+   * Called when an unknown argument is supplied.
+   *
+   * @param form   argument name used
+   * @param params parameters passed into it
+   * @throws UsageException when the user needs to fix it
+   */
+  void handleUnknownArgument(String form, String[] params)
+      throws UsageException;
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/4b56f5e4/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/args/UsageException.java
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/args/UsageException.java b/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/args/UsageException.java
new file mode 100644
index 0000000..1d22dee
--- /dev/null
+++ b/modules/gemfire-modules-session-external/src/main/java/com/gemstone/gemfire/modules/session/installer/args/UsageException.java
@@ -0,0 +1,79 @@
+/*=========================================================================
+ * 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.installer.args;
+
+/**
+ * Invalid usage exception.
+ */
+public class UsageException extends Exception {
+
+  /**
+   * Serial format version.
+   */
+  private static final long serialVersionUID = 1L;
+
+  /**
+   * Stored usage message.
+   */
+  private String usage;
+
+  /**
+   * Creates a new UsageException.
+   */
+  public UsageException() {
+    super();
+  }
+
+  /**
+   * Creates a new UsageException.
+   *
+   * @param message description of exceptional condition
+   */
+  public UsageException(final String message) {
+    super(message);
+  }
+
+  /**
+   * Creates a new UsageException.
+   *
+   * @param message description of exceptional condition
+   * @param cause   provoking exception
+   */
+  public UsageException(final String message, final Throwable cause) {
+    super(message, cause);
+  }
+
+  /**
+   * Creates a new UsageException.
+   *
+   * @param cause provoking exception
+   */
+  public UsageException(final Throwable cause) {
+    super(cause);
+  }
+
+
+  /**
+   * Attaches a usage message to the exception for later consumption.
+   *
+   * @param usageText text to display to user to guide them to correct usage.
+   *                  This is generated and set by the <code>ArgsProcessor</code>.
+   */
+  public void setUsage(final String usageText) {
+    usage = usageText;
+  }
+
+  /**
+   * Returns the usage message previously set.
+   *
+   * @return message or null if not set.
+   */
+  public String getUsage() {
+    return usage;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/4b56f5e4/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/AbstractListener.java
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/AbstractListener.java b/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/AbstractListener.java
new file mode 100644
index 0000000..75e5c8b
--- /dev/null
+++ b/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/AbstractListener.java
@@ -0,0 +1,52 @@
+/*=========================================================================
+ * 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.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author jdeppe
+ */
+public abstract class AbstractListener {
+
+  protected final List<ListenerEventType> events =
+      new ArrayList<ListenerEventType>();
+
+  protected CountDownLatch latch;
+
+  public AbstractListener() {
+    this(1);
+  }
+
+  public AbstractListener(int numCalls) {
+    latch = new CountDownLatch(numCalls);
+    RendezvousManager.registerListener(this);
+  }
+
+  public synchronized void setLatch(int numCalls) {
+    latch = new CountDownLatch(numCalls);
+    events.clear();
+  }
+
+  public boolean await(long timeout,
+      TimeUnit unit) throws InterruptedException {
+    return latch.await(timeout, unit);
+  }
+
+  public List<ListenerEventType> getEvents() {
+    return events;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/4b56f5e4/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/Callback.java
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/Callback.java b/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/Callback.java
new file mode 100644
index 0000000..ccca6c4
--- /dev/null
+++ b/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/Callback.java
@@ -0,0 +1,17 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package com.gemstone.gemfire.modules.session.filter;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * @author jdeppe
+ */
+public interface Callback {
+  public void call(HttpServletRequest request,
+      HttpServletResponse response);
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/4b56f5e4/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/CallbackServlet.java
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/CallbackServlet.java b/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/CallbackServlet.java
new file mode 100644
index 0000000..69c2e09
--- /dev/null
+++ b/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/CallbackServlet.java
@@ -0,0 +1,88 @@
+/*=========================================================================
+ * 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.IOException;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * @author jdeppe
+ */
+public class CallbackServlet extends HttpServlet {
+
+  private Callback callback;
+
+  /**
+   * Processes requests for both HTTP <code>GET</code> and <code>POST</code>
+   * methods.
+   *
+   * @param request  servlet request
+   * @param response servlet response
+   * @throws ServletException if a servlet-specific error occurs
+   * @throws IOException      if an I/O error occurs
+   */
+  protected void processRequest(HttpServletRequest request,
+      HttpServletResponse response)
+      throws ServletException, IOException {
+
+    if (callback != null) {
+      callback.call(request, response);
+    }
+  }
+
+  public void setCallback(Callback callback) {
+    this.callback = callback;
+  }
+
+  /**
+   * Handles the HTTP <code>GET</code> method.
+   *
+   * @param request  servlet request
+   * @param response servlet response
+   * @throws ServletException if a servlet-specific error occurs
+   * @throws IOException      if an I/O error occurs
+   */
+  @Override
+  protected void doGet(HttpServletRequest request, HttpServletResponse response)
+      throws ServletException, IOException {
+    processRequest(request, response);
+  }
+
+  /**
+   * Handles the HTTP <code>POST</code> method.
+   *
+   * @param request  servlet request
+   * @param response servlet response
+   * @throws ServletException if a servlet-specific error occurs
+   * @throws IOException      if an I/O error occurs
+   */
+  @Override
+  protected void doPost(HttpServletRequest request,
+      HttpServletResponse response)
+      throws ServletException, IOException {
+    processRequest(request, response);
+  }
+
+  /**
+   * Returns a short description of the servlet.
+   *
+   * @return a String containing servlet description
+   */
+  @Override
+  public String getServletInfo() {
+    return "Short description";
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/4b56f5e4/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/ChildFirstClassLoader.java
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/ChildFirstClassLoader.java b/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/ChildFirstClassLoader.java
new file mode 100644
index 0000000..a8d9a7d
--- /dev/null
+++ b/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/ChildFirstClassLoader.java
@@ -0,0 +1,77 @@
+/*=========================================================================
+ * 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.filter;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+
+public class ChildFirstClassLoader extends URLClassLoader {
+
+  public ChildFirstClassLoader() {
+    super(new URL[]{});
+  }
+
+  public ChildFirstClassLoader(URL[] urls) {
+    super(urls);
+  }
+
+  public ChildFirstClassLoader(URL[] urls, ClassLoader parent) {
+    super(urls, parent);
+  }
+
+  @Override
+  public void addURL(URL url) {
+    super.addURL(url);
+  }
+
+  @Override
+  public Class loadClass(String name) throws ClassNotFoundException {
+    return loadClass(name, false);
+  }
+
+  /**
+   * We override the parent-first behavior established by
+   * java.lang.Classloader.
+   */
+  @Override
+  protected Class loadClass(String name, boolean resolve)
+      throws ClassNotFoundException {
+    Class c = null;
+
+    if (name.startsWith("com.gemstone")) {
+      // First, check if the class has already been loaded
+      c = findLoadedClass(name);
+
+      // if not loaded, search the local (child) resources
+      if (c == null) {
+        try {
+          c = findClass(name);
+        } catch (ClassNotFoundException cnfe) {
+          // ignore
+        }
+      }
+    }
+
+    // if we could not find it, delegate to parent
+    // Note that we don't attempt to catch any ClassNotFoundException
+    if (c == null) {
+      if (getParent() != null) {
+        c = getParent().loadClass(name);
+      } else {
+        c = getSystemClassLoader().loadClass(name);
+      }
+    }
+
+    if (resolve) {
+      resolveClass(c);
+    }
+
+    return c;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/4b56f5e4/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/CommonTests.java
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/CommonTests.java b/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/CommonTests.java
new file mode 100644
index 0000000..8a8a829
--- /dev/null
+++ b/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/CommonTests.java
@@ -0,0 +1,583 @@
+/*=========================================================================
+ * 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.mockrunner.mock.web.MockFilterConfig;
+import com.mockrunner.mock.web.MockHttpServletRequest;
+import com.mockrunner.mock.web.MockHttpServletResponse;
+import com.mockrunner.mock.web.MockHttpSession;
+import com.mockrunner.servlet.BasicServletTestCaseAdapter;
+import org.junit.After;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.util.concurrent.TimeUnit;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpSessionAttributeListener;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.*;
+
+/**
+ * This servlet tests the effects of the downstream SessionCachingFilter filter.
+ * When these tests are performed, the filter would already have taken effect.
+ */
+public abstract class CommonTests extends BasicServletTestCaseAdapter {
+
+  protected static final String CONTEXT_PATH = "/test";
+
+  @After
+  public void tearDown() throws Exception {
+    super.tearDown();
+  }
+
+  @Test
+  public void testGetSession1() throws Exception {
+    doFilter();
+    HttpSession session1 =
+        ((HttpServletRequest) getFilteredRequest()).getSession();
+    HttpSession session2 =
+        ((HttpServletRequest) getFilteredRequest()).getSession();
+
+    assertSame("Session should be the same", session1, session2);
+  }
+
+  @Test
+  public void testGetSession2() throws Exception {
+    doFilter();
+
+    HttpSession session1 = ((HttpServletRequest) getFilteredRequest()).getSession();
+
+    MockHttpServletResponse response = getWebMockObjectFactory().getMockResponse();
+    Cookie cookie = (Cookie) response.getCookies().get(0);
+    getWebMockObjectFactory().getMockRequest().addCookie(cookie);
+
+    doFilter();
+
+    HttpSession session2 = ((HttpServletRequest) getFilteredRequest()).getSession();
+
+    assertEquals("Session objects across requests should be the same", session1, session2);
+  }
+
+  @Test
+  public void testGetAttributeRequest1() throws Exception {
+    doFilter();
+
+    getFilteredRequest().setAttribute("foo", "bar");
+
+    assertEquals("bar", getFilteredRequest().getAttribute("foo"));
+    assertNull("Unknown attribute should be null",
+        getFilteredRequest().getAttribute("baz"));
+  }
+
+  @Test
+  public void testGetAttributeRequest2() throws Exception {
+    // Setup
+    CallbackServlet s = (CallbackServlet) getServlet();
+    s.setCallback(new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response) {
+        request.setAttribute("foo", "bar");
+      }
+    });
+    doFilter();
+
+    assertEquals("bar", getFilteredRequest().getAttribute("foo"));
+    assertNull("Unknown attribute should be null",
+        getFilteredRequest().getAttribute("baz"));
+  }
+
+  @Test
+  public void testGetAttributeSession1() throws Exception {
+    doFilter();
+
+    ((HttpServletRequest) getFilteredRequest()).getSession().setAttribute("foo", "bar");
+
+    HttpServletRequest request = (HttpServletRequest) getFilteredRequest();
+    assertEquals("bar", request.getSession().getAttribute("foo"));
+  }
+
+  /**
+   * Are attributes preserved across client requests?
+   */
+  @Test
+  public void testGetAttributeSession2() throws Exception {
+    doFilter();
+
+    ((HttpServletRequest) getFilteredRequest()).getSession().setAttribute("foo", "bar");
+
+    MockHttpServletResponse response = getWebMockObjectFactory().getMockResponse();
+    Cookie cookie = (Cookie) response.getCookies().get(0);
+    getWebMockObjectFactory().getMockRequest().addCookie(cookie);
+
+    doFilter();
+    HttpServletRequest request = (HttpServletRequest) getFilteredRequest();
+
+    assertEquals("bar", request.getSession().getAttribute("foo"));
+  }
+
+  /**
+   * Setting a session attribute to null should remove it
+   */
+  @Test
+  public void testSetAttributeNullSession1() throws Exception {
+    // Setup
+    CallbackServlet s = (CallbackServlet) getServlet();
+    s.setCallback(new Callback() {
+      private boolean called = false;
+
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response) {
+        if (called) {
+          request.getSession().setAttribute("foo", null);
+        } else {
+          request.getSession().setAttribute("foo", "bar");
+          called = true;
+        }
+      }
+    });
+
+    doFilter();
+    doFilter();
+
+    HttpSession session = ((HttpServletRequest) getFilteredRequest()).getSession();
+
+    String attr = (String) session.getAttribute("foo");
+    assertNull("Attribute should be null but is " + attr, attr);
+  }
+
+
+  /**
+   * Test that various methods throw the appropriate exception when the session is
+   * invalid.
+   */
+  @Test
+  public void testInvalidate1() throws Exception {
+    doFilter();
+
+    HttpSession session = ((HttpServletRequest) getFilteredRequest()).getSession();
+    session.invalidate();
+
+    try {
+      session.getAttribute("foo");
+      fail("Session should be invalid and an exception should be thrown");
+    } catch (IllegalStateException iex) {
+      // Pass
+    }
+  }
+
+  @Test
+  public void testInvalidate2() throws Exception {
+    doFilter();
+
+    HttpSession session = ((HttpServletRequest) getFilteredRequest()).getSession();
+    session.invalidate();
+
+    try {
+      session.getAttributeNames();
+      fail("Session should be invalid and an exception should be thrown");
+    } catch (IllegalStateException iex) {
+      // Pass
+    }
+  }
+
+  @Ignore(value = "until mockrunner 1.0.9 - see pull request #23")
+  public void testInvalidate3() throws Exception {
+    doFilter();
+
+    HttpSession session = ((HttpServletRequest) getFilteredRequest()).getSession();
+    session.invalidate();
+
+    try {
+      session.getCreationTime();
+      fail("Session should be invalid and an exception should be thrown");
+    } catch (IllegalStateException iex) {
+      // Pass
+    }
+  }
+
+  @Test
+  public void testInvalidate4() throws Exception {
+    doFilter();
+
+    HttpSession session = ((HttpServletRequest) getFilteredRequest()).getSession();
+    session.invalidate();
+
+    try {
+      session.getId();
+    } catch (Exception iex) {
+      fail("Exception should not be thrown");
+    }
+  }
+
+  @Test
+  public void testInvalidate5() throws Exception {
+    doFilter();
+
+    HttpSession session = ((HttpServletRequest) getFilteredRequest()).getSession();
+    session.invalidate();
+
+    try {
+      session.getLastAccessedTime();
+      fail("Session should be invalid and an exception should be thrown");
+    } catch (IllegalStateException iex) {
+      // Pass
+    }
+  }
+
+  @Test
+  public void testInvalidate6() throws Exception {
+    doFilter();
+
+    HttpSession session = ((HttpServletRequest) getFilteredRequest()).getSession();
+    session.invalidate();
+
+    try {
+      session.getMaxInactiveInterval();
+    } catch (Exception ex) {
+      fail("Exception should not be thrown");
+    }
+  }
+
+  @Test
+  public void testInvalidate7() throws Exception {
+    doFilter();
+
+    HttpSession session = ((HttpServletRequest) getFilteredRequest()).getSession();
+    session.invalidate();
+
+    try {
+      session.getServletContext();
+    } catch (Exception ex) {
+      fail("Exception should not be thrown");
+    }
+  }
+
+  @Test
+  public void testInvalidate8() throws Exception {
+    doFilter();
+
+    HttpSession session = ((HttpServletRequest) getFilteredRequest()).getSession();
+    session.invalidate();
+
+    try {
+      session.isNew();
+      fail("Session should be invalid and an exception should be thrown");
+    } catch (IllegalStateException iex) {
+      // Pass
+    }
+  }
+
+  @Test
+  public void testInvalidate9() throws Exception {
+    doFilter();
+
+    HttpSession session = ((HttpServletRequest) getFilteredRequest()).getSession();
+    session.invalidate();
+
+    try {
+      session.removeAttribute("foo");
+      fail("Session should be invalid and an exception should be thrown");
+    } catch (IllegalStateException iex) {
+      // Pass
+    }
+  }
+
+  @Test
+  public void testInvalidate10() throws Exception {
+    doFilter();
+
+    HttpSession session = ((HttpServletRequest) getFilteredRequest()).getSession();
+    session.invalidate();
+
+    try {
+      session.setAttribute("foo", "bar");
+      fail("Session should be invalid and an exception should be thrown");
+    } catch (IllegalStateException iex) {
+      // Pass
+    }
+  }
+
+  @Test
+  public void testInvalidate11() throws Exception {
+    doFilter();
+
+    HttpSession session = ((HttpServletRequest) getFilteredRequest()).getSession();
+    session.invalidate();
+
+    try {
+      session.setMaxInactiveInterval(1);
+    } catch (Exception ex) {
+      fail("Exception should not be thrown");
+    }
+  }
+
+  /**
+   * Test that Session Attribute events get triggered
+   */
+  @Test
+  public void testSessionAttributeListener1() throws Exception {
+    AbstractListener listener = new HttpSessionAttributeListenerImpl();
+    RendezvousManager.registerListener(listener);
+    listener.setLatch(3);
+
+    doFilter();
+
+    // Ugh
+    MockHttpSession session = (MockHttpSession) ((GemfireHttpSession) ((HttpServletRequest) getFilteredRequest()).getSession()).getNativeSession();
+    session.addAttributeListener((HttpSessionAttributeListener) listener);
+    session.setAttribute("foo", "bar");
+    session.setAttribute("foo", "baz");
+    session.setAttribute("foo", null);
+
+    assertTrue("Event timeout", listener.await(1, TimeUnit.SECONDS));
+    assertEquals(ListenerEventType.SESSION_ATTRIBUTE_ADDED, listener.getEvents().get(0));
+    assertEquals(ListenerEventType.SESSION_ATTRIBUTE_REPLACED,
+        listener.getEvents().get(1));
+    assertEquals(ListenerEventType.SESSION_ATTRIBUTE_REMOVED,
+        listener.getEvents().get(2));
+  }
+
+  /**
+   * Test that both replace and remove events get triggered
+   */
+  @Test
+  public void testHttpSessionBindingListener1() throws Exception {
+    doFilter();
+
+    HttpSession session =
+        ((HttpServletRequest) getFilteredRequest()).getSession();
+
+    HttpSessionBindingListenerImpl listener1 =
+        new HttpSessionBindingListenerImpl(2);
+    HttpSessionBindingListenerImpl listener2 =
+        new HttpSessionBindingListenerImpl(2);
+
+    session.setAttribute("foo", listener1);
+    session.setAttribute("foo", listener2);
+    session.setAttribute("foo", null);
+
+    assertTrue("Event timeout", listener1.await(1, TimeUnit.SECONDS));
+    assertTrue("Event timeout", listener2.await(1, TimeUnit.SECONDS));
+
+    assertEquals("Event list size incorrect", 2, listener1.getEvents().size());
+    assertEquals("Event list size incorrect", 2, listener2.getEvents().size());
+    assertEquals(ListenerEventType.SESSION_VALUE_BOUND, listener1.getEvents().get(0));
+    assertEquals(ListenerEventType.SESSION_VALUE_UNBOUND,
+        listener1.getEvents().get(1));
+    assertEquals(ListenerEventType.SESSION_VALUE_BOUND, listener2.getEvents().get(0));
+    assertEquals(ListenerEventType.SESSION_VALUE_UNBOUND,
+        listener2.getEvents().get(1));
+  }
+
+  @Test
+  public void testGetId1() throws Exception {
+    doFilter();
+
+    assertNotNull("Session Id should not be null",
+        ((HttpServletRequest) getFilteredRequest()).getSession().getId());
+  }
+
+  /**
+   * Test that multiple calls from the same client return the same session id
+   */
+  @Test
+  public void testGetId2() throws Exception {
+    doFilter();
+
+    String sessionId = ((HttpServletRequest) getFilteredRequest()).getSession().getId();
+
+    MockHttpServletResponse response = getWebMockObjectFactory().getMockResponse();
+    Cookie cookie = (Cookie) response.getCookies().get(0);
+    getWebMockObjectFactory().getMockRequest().addCookie(cookie);
+
+    doFilter();
+
+    assertEquals("Session Ids should be the same", sessionId,
+        ((HttpServletRequest) getFilteredRequest()).getSession().getId());
+  }
+
+  @Test
+  public void testGetCreationTime1() throws Exception {
+    doFilter();
+
+    HttpServletRequest request = (HttpServletRequest) getFilteredRequest();
+    assertTrue("Session should have a non-zero creation time",
+        request.getSession().getCreationTime() > 0);
+  }
+
+
+  /**
+   * Test that multiple calls from the same client don't change the creation time.
+   */
+  @Test
+  public void testGetCreationTime2() throws Exception {
+    doFilter();
+
+    long creationTime = ((HttpServletRequest) getFilteredRequest()).getSession().getCreationTime();
+
+    MockHttpServletResponse response = getWebMockObjectFactory().getMockResponse();
+    Cookie cookie = (Cookie) response.getCookies().get(0);
+    getWebMockObjectFactory().getMockRequest().addCookie(cookie);
+
+    doFilter();
+
+    assertEquals("Session creation time should be the same", creationTime,
+        ((HttpServletRequest) getFilteredRequest()).getSession().getCreationTime());
+  }
+
+  @Test
+  public void testResponseContainsRequestedSessionId1() throws Exception {
+    Cookie cookie = new Cookie("JSESSIONID", "999-GF");
+    getWebMockObjectFactory().getMockRequest().addCookie(cookie);
+
+    doFilter();
+
+    HttpServletRequest request = (HttpServletRequest) getFilteredRequest();
+
+    assertEquals("Request does not contain requested session ID", "999-GF",
+        request.getRequestedSessionId());
+  }
+
+  @Test
+  public void testGetLastAccessedTime1() throws Exception {
+    doFilter();
+
+    HttpServletRequest request = (HttpServletRequest) getFilteredRequest();
+    assertTrue("Session should have a non-zero last access time",
+        request.getSession().getLastAccessedTime() > 0);
+  }
+
+
+  /**
+   * Test that repeated accesses update the last accessed time
+   */
+  @Test
+  public void testGetLastAccessedTime2() throws Exception {
+    // Setup
+    CallbackServlet s = (CallbackServlet) getServlet();
+    s.setCallback(new Callback() {
+
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response) {
+        request.getSession();
+      }
+    });
+
+    doFilter();
+
+    HttpServletRequest request = (HttpServletRequest) getFilteredRequest();
+    long lastAccess = request.getSession().getLastAccessedTime();
+    assertTrue("Session should have a non-zero last access time", lastAccess > 0);
+
+    MockHttpServletResponse response = getWebMockObjectFactory().getMockResponse();
+    Cookie cookie = (Cookie) response.getCookies().get(0);
+
+    MockHttpServletRequest mRequest = getWebMockObjectFactory().createMockRequest();
+    mRequest.setRequestURL("/test/foo/bar");
+    mRequest.setContextPath(CONTEXT_PATH);
+    mRequest.addCookie(cookie);
+    getWebMockObjectFactory().addRequestWrapper(mRequest);
+
+    Thread.sleep(50);
+    doFilter();
+
+    assertTrue("Last access time should be changing",
+        request.getSession().getLastAccessedTime() > lastAccess);
+  }
+
+  @Test
+  public void testGetSetMaxInactiveInterval() throws Exception {
+    doFilter();
+
+    HttpServletRequest request = (HttpServletRequest) getFilteredRequest();
+    request.getSession().setMaxInactiveInterval(50);
+
+    assertEquals(50, request.getSession().getMaxInactiveInterval());
+  }
+
+  @Test
+  public void testIsNew1() throws Exception {
+    doFilter();
+
+    HttpServletRequest request = (HttpServletRequest) getFilteredRequest();
+    assertTrue("Session should be new", request.getSession().isNew());
+  }
+
+  /**
+   * Subsequent calls should not return true
+   */
+  @Test
+  public void testIsNew2() throws Exception {
+    // Setup
+    CallbackServlet s = (CallbackServlet) getServlet();
+    s.setCallback(new Callback() {
+
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response) {
+        request.getSession();
+      }
+    });
+
+    doFilter();
+
+    HttpServletRequest request = (HttpServletRequest) getFilteredRequest();
+    request.getSession();
+
+    MockHttpServletResponse response = getWebMockObjectFactory().getMockResponse();
+    Cookie cookie = (Cookie) response.getCookies().get(0);
+
+    MockHttpServletRequest mRequest = getWebMockObjectFactory().createMockRequest();
+    mRequest.setRequestURL("/test/foo/bar");
+    mRequest.setContextPath(CONTEXT_PATH);
+    mRequest.addCookie(cookie);
+    getWebMockObjectFactory().addRequestWrapper(mRequest);
+
+    doFilter();
+
+    request = (HttpServletRequest) getFilteredRequest();
+    HttpSession s1 = request.getSession();
+
+    assertFalse("Subsequent isNew() calls should be false", request.getSession().isNew());
+  }
+
+  @Test
+  public void testIsRequestedSessionIdFromCookie() {
+    MockHttpServletRequest mRequest = getWebMockObjectFactory().getMockRequest();
+    Cookie c = new Cookie("JSESSIONID", "1-GF");
+    mRequest.addCookie(c);
+
+    doFilter();
+    HttpServletRequest request = (HttpServletRequest) getFilteredRequest();
+    request.getSession();
+
+    assertTrue(request.isRequestedSessionIdFromCookie());
+  }
+
+  @Test
+  public void testIsRequestedSessionIdFromURL() {
+    MockHttpServletRequest mRequest = getWebMockObjectFactory().getMockRequest();
+    mRequest.setRequestURL("/foo/bar;jsessionid=1");
+
+    doFilter();
+    HttpServletRequest request = (HttpServletRequest) getFilteredRequest();
+    request.getSession();
+
+    assertFalse("Session ID should not be from cookie",
+        request.isRequestedSessionIdFromCookie());
+    assertTrue("Session ID should be from URL", request.isRequestedSessionIdFromURL());
+  }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/4b56f5e4/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/GemfireCacheTest.java
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/GemfireCacheTest.java b/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/GemfireCacheTest.java
new file mode 100644
index 0000000..01ce9fb
--- /dev/null
+++ b/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/GemfireCacheTest.java
@@ -0,0 +1,46 @@
+/*=========================================================================
+ * 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.mockrunner.mock.web.MockFilterConfig;
+import com.mockrunner.mock.web.MockServletConfig;
+import org.junit.Before;
+
+/**
+ * This servlet tests the effects of the downstream SessionCachingFilter filter.
+ * When these tests are performed, the filter would already have taken effect.
+ */
+public class GemfireCacheTest extends CommonTests {
+
+  @Before
+  public void setUp() throws Exception {
+    super.setUp();
+    getWebMockObjectFactory().getMockRequest().setRequestURL("/test/foo/bar");
+    getWebMockObjectFactory().getMockRequest().setContextPath(CONTEXT_PATH);
+    MockFilterConfig config = getWebMockObjectFactory().getMockFilterConfig();
+
+    config.setInitParameter("gemfire.property.mcast-port", "19991");
+    config.setInitParameter("cache-type", "peer-to-peer");
+    System.setProperty("gemfire.logdir", "/tmp");
+
+    getWebMockObjectFactory().getMockServletContext().setContextPath(
+        CONTEXT_PATH);
+
+    setDoChain(true);
+
+    createFilter(SessionCachingFilter.class);
+    createServlet(CallbackServlet.class);
+
+    MockServletConfig servletConfig = getWebMockObjectFactory().getMockServletConfig();
+    ContextManager.getInstance().putContext(servletConfig.getServletContext());
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/4b56f5e4/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/GemfireLocalCacheTest.java
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/GemfireLocalCacheTest.java b/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/GemfireLocalCacheTest.java
new file mode 100644
index 0000000..df01899
--- /dev/null
+++ b/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/GemfireLocalCacheTest.java
@@ -0,0 +1,67 @@
+/*=========================================================================
+ * 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.mockrunner.mock.web.MockFilterConfig;
+import com.mockrunner.mock.web.MockHttpServletRequest;
+import com.mockrunner.mock.web.MockHttpServletResponse;
+import com.mockrunner.mock.web.MockServletConfig;
+import com.mockrunner.servlet.BasicServletTestCaseAdapter;
+import org.junit.After;
+import org.junit.Before;
+
+import javax.servlet.Filter;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+/**
+ * This servlet tests the effects of the downstream SessionCachingFilter filter.
+ * When these tests are performed, the filter would already have taken effect.
+ */
+public class GemfireLocalCacheTest extends BasicServletTestCaseAdapter {
+
+  Filter filter;
+
+  protected static final String CONTEXT_PATH = "/test";
+
+  @Before
+  public void setUp() throws Exception {
+    super.setUp();
+    getWebMockObjectFactory().getMockRequest().setRequestURL("/test/foo/bar");
+    getWebMockObjectFactory().getMockRequest().setContextPath(CONTEXT_PATH);
+    MockFilterConfig config = getWebMockObjectFactory().getMockFilterConfig();
+
+    config.setInitParameter("gemfire.property.mcast-port", "19991");
+    config.setInitParameter("cache-type", "peer-to-peer");
+    config.setInitParameter("gemfire.cache.enable_local_cache", "true");
+    System.setProperty("gemfire.logdir", "/tmp");
+
+    getWebMockObjectFactory().getMockServletContext().setContextPath(
+        CONTEXT_PATH);
+
+    setDoChain(true);
+
+    filter = createFilter(SessionCachingFilter.class);
+    createServlet(CallbackServlet.class);
+
+    MockServletConfig servletConfig = getWebMockObjectFactory().getMockServletConfig();
+    ContextManager.getInstance().putContext(servletConfig.getServletContext());
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    super.tearDown();
+    filter.destroy();
+  }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/4b56f5e4/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/HttpSessionAttributeListenerImpl.java
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/HttpSessionAttributeListenerImpl.java b/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/HttpSessionAttributeListenerImpl.java
new file mode 100644
index 0000000..484d8f7
--- /dev/null
+++ b/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/HttpSessionAttributeListenerImpl.java
@@ -0,0 +1,37 @@
+/*=========================================================================
+ * 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.filter;
+
+import javax.servlet.http.HttpSessionAttributeListener;
+import javax.servlet.http.HttpSessionBindingEvent;
+
+/**
+ *
+ */
+public class HttpSessionAttributeListenerImpl extends AbstractListener
+    implements HttpSessionAttributeListener {
+
+  @Override
+  public synchronized void attributeAdded(HttpSessionBindingEvent se) {
+    events.add(ListenerEventType.SESSION_ATTRIBUTE_ADDED);
+    latch.countDown();
+  }
+
+  @Override
+  public synchronized void attributeRemoved(HttpSessionBindingEvent se) {
+    events.add(ListenerEventType.SESSION_ATTRIBUTE_REMOVED);
+    latch.countDown();
+  }
+
+  @Override
+  public synchronized void attributeReplaced(HttpSessionBindingEvent se) {
+    events.add(ListenerEventType.SESSION_ATTRIBUTE_REPLACED);
+    latch.countDown();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/4b56f5e4/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/HttpSessionBindingListenerImpl.java
----------------------------------------------------------------------
diff --git a/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/HttpSessionBindingListenerImpl.java b/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/HttpSessionBindingListenerImpl.java
new file mode 100644
index 0000000..2aa7b4b
--- /dev/null
+++ b/modules/gemfire-modules-session-external/src/test/java/com/gemstone/gemfire/modules/session/filter/HttpSessionBindingListenerImpl.java
@@ -0,0 +1,40 @@
+/*=========================================================================
+ * 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.Serializable;
+import javax.servlet.http.HttpSessionBindingEvent;
+import javax.servlet.http.HttpSessionBindingListener;
+
+/**
+ * @author jdeppe
+ */
+public class HttpSessionBindingListenerImpl extends AbstractListener implements
+    HttpSessionBindingListener, Serializable {
+
+  public HttpSessionBindingListenerImpl(int i) {
+    super(i);
+  }
+
+  @Override
+  public synchronized void valueBound(HttpSessionBindingEvent event) {
+    events.add(ListenerEventType.SESSION_VALUE_BOUND);
+    latch.countDown();
+  }
+
+  @Override
+  public synchronized void valueUnbound(HttpSessionBindingEvent event) {
+    events.add(ListenerEventType.SESSION_VALUE_UNBOUND);
+    latch.countDown();
+  }
+}



Mime
View raw message