You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by je...@apache.org on 2015/12/22 22:08:17 UTC

[05/17] incubator-geode git commit: GEODE-14: Initial integration of gemfire-modules subproject

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionAttributeEvent.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionAttributeEvent.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionAttributeEvent.java
new file mode 100644
index 0000000..70f5376
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionAttributeEvent.java
@@ -0,0 +1,9 @@
+package com.gemstone.gemfire.modules.session.catalina.internal;
+
+import com.gemstone.gemfire.DataSerializable;
+import com.gemstone.gemfire.modules.session.catalina.DeltaSession;
+
+public interface DeltaSessionAttributeEvent extends DataSerializable {
+
+  public void apply(DeltaSession session);
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionAttributeEventBatch.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionAttributeEventBatch.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionAttributeEventBatch.java
new file mode 100644
index 0000000..b0d8681
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionAttributeEventBatch.java
@@ -0,0 +1,85 @@
+/*=========================================================================
+ * 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.catalina.internal;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.gemstone.gemfire.DataSerializer;
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.modules.gatewaydelta.AbstractGatewayDeltaEvent;
+import com.gemstone.gemfire.modules.session.catalina.DeltaSession;
+
+@SuppressWarnings("serial")
+public class DeltaSessionAttributeEventBatch extends AbstractGatewayDeltaEvent {
+
+  private List<DeltaSessionAttributeEvent> eventQueue;
+  
+  public DeltaSessionAttributeEventBatch() {
+  }
+
+  public DeltaSessionAttributeEventBatch(String regionName, String sessionId, List<DeltaSessionAttributeEvent> eventQueue) {
+    super(regionName, sessionId);
+    this.eventQueue = eventQueue;
+  }
+  
+  public List<DeltaSessionAttributeEvent> getEventQueue() {
+    return this.eventQueue;
+  }
+
+  public void apply(Cache cache) {
+    Region<String,DeltaSession> region = getRegion(cache);
+    DeltaSession session = region.get(this.key);
+    if (session == null) {
+      StringBuilder builder = new StringBuilder();
+      builder
+        .append("Session ")
+        .append(this.key)
+        .append(" was not found while attempting to apply ")
+        .append(this);
+      cache.getLogger().warning(builder.toString());
+    } else {
+      session.applyAttributeEvents(region, this.eventQueue);
+      if (cache.getLogger().fineEnabled()) {
+        StringBuilder builder = new StringBuilder();
+          builder
+            .append("Applied ")
+            .append(this);
+        cache.getLogger().fine(builder.toString());
+      }
+    }
+  }
+
+  public void fromData(DataInput in) throws IOException, ClassNotFoundException {
+    super.fromData(in);
+    this.eventQueue = DataSerializer.readArrayList(in);
+  }
+
+  public void toData(DataOutput out) throws IOException {
+    super.toData(out);
+    DataSerializer.writeArrayList((ArrayList) this.eventQueue, out);
+  }
+
+  public String toString() {
+    return new StringBuilder()
+      .append("DeltaSessionAttributeEventBatch[")
+      .append("regionName=")
+      .append(this.regionName)
+      .append("; sessionId=")
+      .append(this.key)
+      .append("; numberOfEvents=")
+      .append(this.eventQueue.size())
+      .append("]")
+      .toString();
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionDestroyAttributeEvent.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionDestroyAttributeEvent.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionDestroyAttributeEvent.java
new file mode 100644
index 0000000..a8ee4fa
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionDestroyAttributeEvent.java
@@ -0,0 +1,65 @@
+/*=========================================================================
+ * 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.catalina.internal;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import com.gemstone.gemfire.DataSerializable;
+import com.gemstone.gemfire.DataSerializer;
+import com.gemstone.gemfire.Instantiator;
+import com.gemstone.gemfire.modules.session.catalina.DeltaSession;
+
+
+@SuppressWarnings("serial")
+public class DeltaSessionDestroyAttributeEvent implements DeltaSessionAttributeEvent {
+
+  private String attributeName;
+  
+  public DeltaSessionDestroyAttributeEvent() {
+  }
+
+  public DeltaSessionDestroyAttributeEvent(String attributeName) {
+    this.attributeName = attributeName;
+  }
+  
+  public String getAttributeName() {
+    return this.attributeName;
+  }
+
+  public void apply(DeltaSession session) {
+    session.localDestroyAttribute(this.attributeName);
+  }
+
+  public void fromData(DataInput in) throws IOException, ClassNotFoundException {
+    this.attributeName = DataSerializer.readString(in);
+  }
+
+  public void toData(DataOutput out) throws IOException {
+    DataSerializer.writeString(this.attributeName, out);
+  }
+  
+  public static void registerInstantiator(int id) {
+    Instantiator.register(new Instantiator(DeltaSessionDestroyAttributeEvent.class, id) {
+      public DataSerializable newInstance() {
+        return new DeltaSessionDestroyAttributeEvent();
+      }
+    });
+  }
+  
+  public String toString() {
+    return new StringBuilder()
+      .append("DeltaSessionDestroyAttributeEvent[")
+      .append("attributeName=")
+      .append(this.attributeName)
+      .append("]")
+      .toString();
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionStatistics.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionStatistics.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionStatistics.java
new file mode 100644
index 0000000..43c8df5
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionStatistics.java
@@ -0,0 +1,81 @@
+/*=========================================================================
+ * 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.catalina.internal;
+
+import com.gemstone.gemfire.StatisticDescriptor;
+import com.gemstone.gemfire.Statistics;
+import com.gemstone.gemfire.StatisticsFactory;
+import com.gemstone.gemfire.StatisticsType;
+import com.gemstone.gemfire.StatisticsTypeFactory;
+import com.gemstone.gemfire.internal.StatisticsTypeFactoryImpl;
+
+public class DeltaSessionStatistics {
+
+  public static final String typeName = "SessionStatistics";
+
+  private static final StatisticsType type;
+
+  private static final String SESSIONS_CREATED = "sessionsCreated";
+  private static final String SESSIONS_INVALIDATED= "sessionsInvalidated";
+  private static final String SESSIONS_EXPIRED= "sessionsExpired";
+
+  private static final int sessionsCreatedId;
+  private static final int sessionsInvalidatedId;
+  private static final int sessionsExpiredId;
+
+  static {
+    // Initialize type
+    StatisticsTypeFactory f = StatisticsTypeFactoryImpl.singleton();
+    type = f.createType(typeName, typeName,
+      new StatisticDescriptor[] {
+        f.createIntCounter(SESSIONS_CREATED, "The number of sessions created", "operations"),
+        f.createIntCounter(SESSIONS_INVALIDATED, "The number of sessions invalidated by invoking invalidate", "operations"),
+        f.createIntCounter(SESSIONS_EXPIRED, "The number of sessions invalidated by timeout", "operations"),
+      }
+    );
+
+    // Initialize id fields
+    sessionsCreatedId = type.nameToId(SESSIONS_CREATED);
+    sessionsInvalidatedId = type.nameToId(SESSIONS_INVALIDATED);
+    sessionsExpiredId = type.nameToId(SESSIONS_EXPIRED);
+  }
+
+  private final Statistics stats;
+
+  public DeltaSessionStatistics(StatisticsFactory factory, String applicationName) {
+    this.stats = factory.createAtomicStatistics(type, typeName + "_" + applicationName);
+  }
+
+  public void close() {
+    this.stats.close();
+  }
+
+  public int getSessionsCreated() {
+    return this.stats.getInt(sessionsCreatedId);
+  }
+
+  public void incSessionsCreated() {
+    this.stats.incInt(sessionsCreatedId, 1);
+  }
+
+  public int getSessionsInvalidated() {
+    return this.stats.getInt(sessionsInvalidatedId);
+  }
+
+  public void incSessionsInvalidated() {
+    this.stats.incInt(sessionsInvalidatedId, 1);
+  }
+
+  public int getSessionsExpired() {
+    return this.stats.getInt(sessionsExpiredId);
+  }
+
+  public void incSessionsExpired() {
+    this.stats.incInt(sessionsExpiredId, 1);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionUpdateAttributeEvent.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionUpdateAttributeEvent.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionUpdateAttributeEvent.java
new file mode 100644
index 0000000..93fdac4
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionUpdateAttributeEvent.java
@@ -0,0 +1,75 @@
+/*=========================================================================
+ * 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.catalina.internal;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import com.gemstone.gemfire.DataSerializable;
+import com.gemstone.gemfire.DataSerializer;
+import com.gemstone.gemfire.Instantiator;
+import com.gemstone.gemfire.modules.session.catalina.DeltaSession;
+
+@SuppressWarnings("serial")
+public class DeltaSessionUpdateAttributeEvent implements DeltaSessionAttributeEvent {
+
+  private String attributeName;
+
+  private Object attributeValue;
+  
+  public DeltaSessionUpdateAttributeEvent() {
+  }
+
+  public DeltaSessionUpdateAttributeEvent(String attributeName, Object attributeValue) {
+    this.attributeName = attributeName;
+    this.attributeValue = attributeValue;
+  }
+  
+  public String getAttributeName() {
+    return this.attributeName;
+  }
+
+  public Object getAttributeValue() {
+    return this.attributeValue;
+  }
+
+  public void apply(DeltaSession session) {
+    session.localUpdateAttribute(this.attributeName, this.attributeValue);
+  }
+
+  public void fromData(DataInput in) throws IOException, ClassNotFoundException {
+    this.attributeName = DataSerializer.readString(in);
+    this.attributeValue = DataSerializer.readObject(in);
+  }
+
+  public void toData(DataOutput out) throws IOException {
+    DataSerializer.writeString(this.attributeName, out);
+    DataSerializer.writeObject(this.attributeValue, out);
+  }
+  
+  public static void registerInstantiator(int id) {
+    Instantiator.register(new Instantiator(DeltaSessionUpdateAttributeEvent.class, id) {
+      public DataSerializable newInstance() {
+        return new DeltaSessionUpdateAttributeEvent();
+      }
+    });
+  }
+  
+  public String toString() {
+    return new StringBuilder()
+      .append("DeltaSessionUpdateAttributeEvent[")
+      .append("attributeName=")
+      .append(this.attributeName)
+      .append("; attributeValue=")
+      .append(this.attributeValue)
+      .append("]")
+      .toString();
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/Banner.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/Banner.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/Banner.java
new file mode 100644
index 0000000..9e3332d
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/Banner.java
@@ -0,0 +1,49 @@
+/*=========================================================================
+ * 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.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Properties;
+
+import com.gemstone.gemfire.internal.GemFireVersion;
+
+public class Banner {
+
+  private static String VERSION = "unknown";
+
+  private static Properties props = new Properties();
+
+  static {
+    InputStream is = Banner.class.getResourceAsStream("/modules-version.properties");
+    try {
+      props.load(is);
+      VERSION = props.getProperty("version");
+    } catch (IOException e) {
+    }
+  }
+	
+  public static String getString() {
+    StringWriter sw = new StringWriter();
+    PrintWriter pw = new PrintWriter(sw);
+    print(pw);
+    pw.close();
+    return sw.toString();
+  }
+  
+  private static void print(PrintWriter pw) {
+    pw.println("GemFire Modules");
+    pw.print("Modules version: ");
+    pw.println(VERSION);
+    GemFireVersion.print(pw);
+  }
+  
+  private Banner() {}
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/BootstrappingFunction.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/BootstrappingFunction.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/BootstrappingFunction.java
new file mode 100644
index 0000000..0a68ae6
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/BootstrappingFunction.java
@@ -0,0 +1,180 @@
+/*=========================================================================
+ * 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.util;
+
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache.CacheFactory;
+import com.gemstone.gemfire.cache.execute.Execution;
+import com.gemstone.gemfire.cache.execute.Function;
+import com.gemstone.gemfire.cache.execute.FunctionContext;
+import com.gemstone.gemfire.cache.execute.FunctionService;
+import com.gemstone.gemfire.cache.execute.ResultCollector;
+import com.gemstone.gemfire.distributed.internal.DM;
+import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
+import com.gemstone.gemfire.distributed.internal.MembershipListener;
+import com.gemstone.gemfire.distributed.internal.membership.InternalDistributedMember;
+
+import java.util.List;
+import java.util.Set;
+
+public class BootstrappingFunction implements Function, MembershipListener {
+
+  private static final long serialVersionUID = 1856043174458190605L;
+    
+  public static final String ID = "bootstrapping-function";
+  
+  private static final int TIME_TO_WAIT_FOR_CACHE = Integer.getInteger("gemfiremodules.timeToWaitForCache", 30000);
+  
+  @Override
+  public void execute(FunctionContext context) {
+    // Verify that the cache exists before continuing.
+    // When this function is executed by a remote membership listener, it is
+    // being invoked before the cache is started.
+    Cache cache = verifyCacheExists();
+    
+    // Register as membership listener
+    registerAsMembershipListener(cache);
+
+    // Register functions
+    registerFunctions();
+    
+    // Return status
+    context.getResultSender().lastResult(Boolean.TRUE);
+  }
+  
+  private Cache verifyCacheExists() {
+    int timeToWait = 0;
+    Cache cache = null;
+    while (timeToWait < TIME_TO_WAIT_FOR_CACHE) {
+      try {
+        cache = CacheFactory.getAnyInstance();
+        break;
+      } catch (Exception ignore) {
+        //keep trying and hope for the best
+      }
+      try {
+        Thread.sleep(250);
+      } catch (InterruptedException ie) {
+        Thread.currentThread().interrupt();
+        break;
+      }
+      timeToWait += 250;
+    }
+    
+    if (cache == null) {
+      cache = new CacheFactory().create();
+    }
+    
+    return cache;
+  }
+
+  private void registerAsMembershipListener(Cache cache) {
+    DM dm = ((InternalDistributedSystem) cache.getDistributedSystem()).getDistributionManager();
+    dm.addMembershipListener(this);
+  }
+
+  private void registerFunctions() {
+    // Synchronize so that these functions aren't registered twice. The
+    // constructor for the CreateRegionFunction creates a meta region.
+    synchronized (ID) {
+      // Register the create region function if it is not already registered
+      if (!FunctionService.isRegistered(CreateRegionFunction.ID)) {
+        FunctionService.registerFunction(new CreateRegionFunction());
+      }
+      
+      // Register the touch partitioned region entries function if it is not already registered
+      if (!FunctionService.isRegistered(TouchPartitionedRegionEntriesFunction.ID)) {
+        FunctionService.registerFunction(new TouchPartitionedRegionEntriesFunction());
+      }
+      
+      // Register the touch replicated region entries function if it is not already registered
+      if (!FunctionService.isRegistered(TouchReplicatedRegionEntriesFunction.ID)) {
+        FunctionService.registerFunction(new TouchReplicatedRegionEntriesFunction());
+      }
+      
+      // Register the region size function if it is not already registered
+      if (!FunctionService.isRegistered(RegionSizeFunction.ID)) {
+      	FunctionService.registerFunction(new RegionSizeFunction());
+      }
+    }
+  }
+
+  private void bootstrapMember(InternalDistributedMember member) {
+    // Create and execute the function
+    Cache cache = CacheFactory.getAnyInstance();
+    Execution execution = FunctionService.onMember(cache.getDistributedSystem(), member);
+    ResultCollector collector = execution.execute(this);
+
+    // Get the result. Nothing is being done with it.
+    try {
+      collector.getResult();
+    } catch (Exception e) {
+      // If an exception occurs in the function, log it.
+      cache.getLogger().warning("Caught unexpected exception:", e);
+    }
+  }
+
+  @Override
+  public String getId() {
+    return ID;
+  }
+
+  @Override
+  public boolean hasResult() {
+    return true;
+  }
+
+  @Override
+  public boolean isHA() {
+    return false;
+  }
+
+  @Override
+  public boolean optimizeForWrite() {
+    return false;
+  }
+  
+  public int hashCode() {
+    // This method is only implemented so that multiple instances of this class
+    // don't get added as membership listeners.
+    return ID.hashCode();
+  }
+  
+  public boolean equals(Object obj) {
+    // This method is only implemented so that multiple instances of this class
+    // don't get added as membership listeners.
+    if (this == obj) {
+      return true;
+    }
+
+    if (obj == null || !(obj instanceof BootstrappingFunction)) {
+      return false;
+    }
+    
+    return true;
+  }
+
+  @Override
+  public void memberDeparted(InternalDistributedMember id, boolean crashed) {
+  }
+
+  @Override
+  public void memberJoined(InternalDistributedMember id) {
+    bootstrapMember(id);
+  }
+
+  @Override
+  public void memberSuspect(InternalDistributedMember id,
+      InternalDistributedMember whoSuspected, String reason) {
+  }
+
+  @Override
+  public void quorumLost(Set<InternalDistributedMember> internalDistributedMembers,
+      List<InternalDistributedMember> internalDistributedMembers2) {
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ClassLoaderObjectInputStream.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ClassLoaderObjectInputStream.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ClassLoaderObjectInputStream.java
new file mode 100644
index 0000000..6dc991a
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ClassLoaderObjectInputStream.java
@@ -0,0 +1,34 @@
+/*=========================================================================
+ * 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.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectStreamClass;
+
+/**
+ * This class is used when session attributes need to be reconstructed with a
+ * new classloader.
+ */
+public class ClassLoaderObjectInputStream extends ObjectInputStream {
+
+  private final ClassLoader loader;
+
+  public ClassLoaderObjectInputStream(InputStream in,
+      ClassLoader loader) throws IOException {
+    super(in);
+    this.loader = loader;
+  }
+
+  @Override
+  public Class<?> resolveClass(
+      ObjectStreamClass desc) throws ClassNotFoundException {
+    return Class.forName(desc.getName(), false, loader);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ContextMapper.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ContextMapper.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ContextMapper.java
new file mode 100644
index 0000000..d1a5404
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ContextMapper.java
@@ -0,0 +1,41 @@
+package com.gemstone.gemfire.modules.util;
+
+import com.gemstone.gemfire.modules.session.catalina.DeltaSessionManager;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This basic singleton class maps context paths to manager instances.
+ *
+ * This class exists for a particular corner case described here. Consider a
+ * client-server environment with empty client regions *and* the need to fire
+ * HttpSessionListener destroy events. When a session expires, in this scenario,
+ * the Gemfire destroy events originate on the server and, with some Gemfire
+ * hackery, the destroyed object ends up as the event's callback argument. At
+ * the point that the CacheListener then gets the event, the re-constituted
+ * session object has no manager associated and so we need to re-attach a
+ * manager to it so that events can be fired correctly.
+ */
+
+public class ContextMapper {
+
+  private static Map<String, DeltaSessionManager> managers =
+      new HashMap<String, DeltaSessionManager>();
+
+  private ContextMapper() {
+    // This is a singleton
+  }
+
+  public static void addContext(String path, DeltaSessionManager manager) {
+    managers.put(path, manager);
+  }
+
+  public static DeltaSessionManager getContext(String path) {
+    return managers.get(path);
+  }
+
+  public static DeltaSessionManager removeContext(String path) {
+    return managers.remove(path);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/CreateRegionFunction.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/CreateRegionFunction.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/CreateRegionFunction.java
new file mode 100644
index 0000000..65c2c51
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/CreateRegionFunction.java
@@ -0,0 +1,248 @@
+/*=========================================================================
+ * 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.util;
+
+import com.gemstone.gemfire.cache.*;
+
+import com.gemstone.gemfire.cache.client.ClientCache;
+import com.gemstone.gemfire.cache.execute.*;
+import com.gemstone.gemfire.cache.partition.PartitionRegionHelper;
+
+import com.gemstone.gemfire.distributed.DistributedLockService;
+
+import com.gemstone.gemfire.distributed.internal.locks.DistributedMemberLock;
+
+import com.gemstone.gemfire.internal.cache.PartitionedRegion;
+
+import com.gemstone.gemfire.internal.cache.xmlcache.CacheXmlGenerator;
+import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import java.util.Properties;
+
+public class CreateRegionFunction implements Function, Declarable {
+
+  private static final long serialVersionUID = -9210226844302128969L;
+
+  private final Cache cache;
+  
+  private final Region<String,RegionConfiguration> regionConfigurationsRegion;
+  
+  public static final String ID = "create-region-function";
+  
+  private static final boolean DUMP_SESSION_CACHE_XML = 
+    Boolean.getBoolean("gemfiremodules.dumpSessionCacheXml");
+
+  private static final String REGION_CONFIGURATION_METADATA_REGION = "__regionConfigurationMetadata";
+  
+  public CreateRegionFunction() {
+    this(CacheFactory.getAnyInstance());
+  }
+  
+  public CreateRegionFunction(Cache cache) {
+    this.cache = cache;
+    this.regionConfigurationsRegion = createRegionConfigurationMetadataRegion();
+  }
+  
+  public CreateRegionFunction(ClientCache cache) {
+    this.cache = null;
+    this.regionConfigurationsRegion = null;
+  }
+
+  public void execute(FunctionContext context) {
+    RegionConfiguration configuration = (RegionConfiguration) context.getArguments();
+    if (this.cache.getLogger().fineEnabled()) {
+      StringBuilder builder = new StringBuilder();
+      builder
+        .append("Function ")
+        .append(ID)
+        .append(" received request: ")
+        .append(configuration);
+      this.cache.getLogger().fine(builder.toString());
+    }
+
+    // Create or retrieve region
+    RegionStatus status = createOrRetrieveRegion(configuration);
+    
+    // Dump XML
+    if (DUMP_SESSION_CACHE_XML) {
+      writeCacheXml();
+    }
+    // Return status
+    context.getResultSender().lastResult(status);
+  }
+  
+  private RegionStatus createOrRetrieveRegion(RegionConfiguration configuration) {
+    RegionStatus status = null;
+    String regionName = configuration.getRegionName();
+    if (this.cache.getLogger().fineEnabled()) {
+      this.cache.getLogger().fine("Function " + ID + " retrieving region named: " + regionName);
+    }
+    Region region = this.cache.getRegion(regionName);
+    if (region == null) {
+      status = createRegion(configuration);
+    } else {
+      status = RegionStatus.VALID;
+      try {
+        RegionHelper.validateRegion(this.cache, configuration, region);
+      } catch (Exception e) {
+        if (!e.getMessage()
+            .equals(
+                LocalizedStrings.RegionAttributesCreation_CACHELISTENERS_ARE_NOT_THE_SAME
+                    .toLocalizedString())) {
+          this.cache.getLogger().warning(e);
+        }
+        status = RegionStatus.INVALID;
+      }
+    }
+    return status;
+  }
+
+  public String getId() {
+    return ID;
+  }
+
+  public boolean optimizeForWrite() {
+    return false;
+  }
+
+  public boolean isHA() {
+    return true;
+  }
+
+  public boolean hasResult() {
+    return true;
+  }
+
+  public void init(Properties properties) {
+  }
+  
+  private RegionStatus createRegion(RegionConfiguration configuration) {
+    // Get a distributed lock
+    DistributedMemberLock dml = getDistributedLock();
+    if (this.cache.getLogger().fineEnabled()) {
+      this.cache.getLogger().fine(this + ": Attempting to lock " + dml);
+    }
+    long start=0, end=0;    
+    RegionStatus status = null;
+    try {
+      if (this.cache.getLogger().fineEnabled()) {
+        start = System.currentTimeMillis();
+      }
+      // Obtain a lock on the distributed lock
+      dml.lockInterruptibly();
+      if (this.cache.getLogger().fineEnabled()) {
+        end = System.currentTimeMillis();
+        this.cache.getLogger().fine(this + ": Obtained lock on " + dml + " in " + (end-start) + " ms");
+      }
+      
+      // Attempt to get the region again after the lock has been obtained
+      String regionName = configuration.getRegionName();
+      Region region = this.cache.getRegion(regionName);
+      
+      // If it exists now, validate it.
+      // Else put an entry into the sessionRegionConfigurationsRegion
+      // while holding the lock. This will create the region in all VMs.
+      if (region == null) {
+        this.regionConfigurationsRegion.put(regionName, configuration);
+        
+        // Retrieve the region after creating it
+        region = this.cache.getRegion(regionName);
+        // If the region is null now, it wasn't created for some reason
+        // (e.g. the region attributes id were invalid)
+        if (region == null) {
+          status = RegionStatus.INVALID;          
+        } else {
+          // Create the PR buckets if necessary)
+          if (region instanceof PartitionedRegion) {
+            PartitionedRegion pr = (PartitionedRegion) region;
+            createBuckets(pr);
+          }
+          status = RegionStatus.VALID;
+        }
+      } else {
+        status = RegionStatus.VALID;
+        try {
+          RegionHelper.validateRegion(this.cache, configuration, region);
+        } catch (Exception e) {
+          if (!e.getMessage()
+              .equals(
+                  LocalizedStrings.RegionAttributesCreation_CACHELISTENERS_ARE_NOT_THE_SAME
+                      .toLocalizedString())) {
+            this.cache.getLogger().warning(e);
+          }
+          status = RegionStatus.INVALID;
+        }
+      }
+    } catch(Exception e) {
+      StringBuilder builder = new StringBuilder();
+      builder
+        .append(this)
+        .append(": Caught Exception attempting to create region named ")
+        .append(configuration.getRegionName())
+        .append(":");
+      this.cache.getLogger().warning(builder.toString(), e);
+      status = RegionStatus.INVALID;
+    }
+    finally {
+      // Unlock the distributed lock
+      try {
+        dml.unlock();
+      }
+      catch (Exception e) {}
+    }
+    return status;
+  }
+  
+  private void createBuckets(PartitionedRegion region) {
+    PartitionRegionHelper.assignBucketsToPartitions(region);
+  }
+  
+  private Region<String,RegionConfiguration> createRegionConfigurationMetadataRegion() {
+    // a sessionFactory in hibernate could have been re-started
+    // so, it is possible that this region exists already
+    Region<String, RegionConfiguration> r = this.cache
+        .getRegion(REGION_CONFIGURATION_METADATA_REGION);
+    if (r != null) {
+      return r;
+    }
+    RegionFactory<String, RegionConfiguration> factory = this.cache
+        .createRegionFactory(RegionShortcut.REPLICATE);
+    factory.addCacheListener(new RegionConfigurationCacheListener());
+    return factory.create(REGION_CONFIGURATION_METADATA_REGION);
+  }
+  
+  private void writeCacheXml() {
+    File file = new File("cache-" + System.currentTimeMillis() + ".xml");
+    try {
+      PrintWriter pw = new PrintWriter(new FileWriter(file), true);
+      CacheXmlGenerator.generate(this.cache, pw);
+      pw.close();
+    } catch (IOException e) {}
+  }
+
+  private DistributedMemberLock getDistributedLock() {
+    String dlsName = this.regionConfigurationsRegion.getName();
+    DistributedLockService lockService = initializeDistributedLockService(dlsName);
+    String lockToken = dlsName + "_token";
+    return new DistributedMemberLock(lockService, lockToken);
+  }
+
+  private DistributedLockService initializeDistributedLockService(String dlsName) {
+    DistributedLockService lockService = DistributedLockService.getServiceNamed(dlsName);
+    if (lockService == null) {
+      lockService = DistributedLockService.create(dlsName, this.cache.getDistributedSystem());
+    }
+    return lockService;
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/DebugCacheListener.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/DebugCacheListener.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/DebugCacheListener.java
new file mode 100644
index 0000000..8f1d4d3
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/DebugCacheListener.java
@@ -0,0 +1,65 @@
+/*=========================================================================
+ * 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.util;
+
+import java.util.Properties;
+
+import com.gemstone.gemfire.cache.Declarable;
+import com.gemstone.gemfire.cache.EntryEvent;
+import com.gemstone.gemfire.cache.util.CacheListenerAdapter;
+
+@SuppressWarnings("unchecked")
+public class DebugCacheListener extends CacheListenerAdapter implements Declarable {
+
+  public void afterCreate(EntryEvent event) {
+    log(event);
+  }
+
+  public void afterUpdate(EntryEvent event) {
+    log(event);
+  }
+
+  public void afterInvalidate(EntryEvent event) {
+    log(event);
+  }
+  
+  public void afterDestroy(EntryEvent event) {
+    log(event);
+  }
+  
+  private void log(EntryEvent event) {
+    StringBuilder builder = new StringBuilder();
+    builder
+      .append("DebugCacheListener: Received ")
+      .append(event.getOperation())
+      .append(" for key=")
+      .append(event.getKey());
+    if (event.getNewValue() != null) {
+      builder
+        .append("; value=")
+        .append(event.getNewValue());
+    }
+    event.getRegion().getCache().getLogger().info(builder.toString());
+  }
+
+  public void init(Properties p) {}
+  
+  public boolean equals(Object obj) {
+    // This method is only implemented so that RegionCreator.validateRegion works properly.
+    // The CacheListener comparison fails because two of these instances are not equal.
+    if (this == obj) {
+      return true;
+    }
+
+    if (obj == null || !(obj instanceof DebugCacheListener)) {
+      return false;
+    }
+    
+    return true;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ModuleStatistics.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ModuleStatistics.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ModuleStatistics.java
new file mode 100644
index 0000000..5b3a9fe
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ModuleStatistics.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.util;
+
+import com.gemstone.gemfire.StatisticDescriptor;
+import com.gemstone.gemfire.Statistics;
+import com.gemstone.gemfire.StatisticsFactory;
+import com.gemstone.gemfire.StatisticsType;
+import com.gemstone.gemfire.StatisticsTypeFactory;
+import com.gemstone.gemfire.distributed.DistributedSystem;
+import com.gemstone.gemfire.internal.StatisticsTypeFactoryImpl;
+
+/**
+ * Statistics for modules.
+ *
+ * @author sbawaska
+ */
+public class ModuleStatistics {
+
+  private static final StatisticsType type;
+
+  private static final int cacheHitsId;
+
+  private static final int cacheMissesId;
+
+  private static final int hibernateEntityDestroyJobsScheduledId;
+
+  static {
+    StatisticsTypeFactory f = StatisticsTypeFactoryImpl.singleton();
+    type = f
+        .createType(
+            "pluginStats",
+            "statistics for hibernate plugin and hibernate L2 cache",
+            new StatisticDescriptor[]{
+                f.createLongCounter("cacheHits",
+                    "number of times an entity was found in L2 cache", "count"),
+                f.createLongCounter("cacheMisses",
+                    "number of times an entity was NOT found in l2 cache",
+                    "count"),
+                f.createLongCounter(
+                    "hibernateEntityDestroyJobsScheduled",
+                    "number of entities scheduled for destroy because of version conflict with a remote member",
+                    "jobs")});
+
+    cacheHitsId = type.nameToId("cacheHits");
+    cacheMissesId = type.nameToId("cacheMisses");
+    hibernateEntityDestroyJobsScheduledId = type
+        .nameToId("hibernateEntityDestroyJobsScheduled");
+  }
+
+  private final Statistics stats;
+
+  private static ModuleStatistics instance;
+
+  private ModuleStatistics(StatisticsFactory factory) {
+    this.stats = factory.createAtomicStatistics(type, "PluginStatistics");
+  }
+
+  public static ModuleStatistics getInstance(DistributedSystem system) {
+    synchronized (ModuleStatistics.class) {
+      if (instance == null) {
+        instance = new ModuleStatistics(system);
+      }
+    }
+    return instance;
+  }
+
+  public void incCacheHit() {
+    stats.incLong(cacheHitsId, 1);
+  }
+
+  public long getCacheHits() {
+    return stats.getLong(cacheHitsId);
+  }
+
+  public void incCacheMiss() {
+    stats.incLong(cacheMissesId, 1);
+  }
+
+  public long getCacheMiss() {
+    return stats.getLong(cacheMissesId);
+  }
+
+  public void incHibernateDestroyJobsScheduled() {
+    stats.incLong(hibernateEntityDestroyJobsScheduledId, 1);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionConfiguration.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionConfiguration.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionConfiguration.java
new file mode 100644
index 0000000..6a82cbb
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionConfiguration.java
@@ -0,0 +1,308 @@
+/*=========================================================================
+ * 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.util;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.InputStream;
+
+import com.gemstone.gemfire.DataSerializable;
+import com.gemstone.gemfire.DataSerializer;
+import com.gemstone.gemfire.Instantiator;
+import com.gemstone.gemfire.cache.CacheWriter;
+import com.gemstone.gemfire.cache.CustomExpiry;
+
+/**
+ * Class <code>RegionConfiguration</code> encapsulates the configuration
+ * attributes for a <code>Region</code> to be created on the server.
+ *
+ * @author Barry Oglesby
+ *
+ * @since 6.5
+ */
+@SuppressWarnings({"serial","unchecked"})
+public class RegionConfiguration implements DataSerializable {
+
+  /**
+   * The name of the <code>Region</code> to be created
+   */
+  private String regionName;
+  
+  /**
+   * The id of the <code>RegionAttributes</code> to be used
+   */
+  private String regionAttributesId;
+  
+  /**
+   * The default max inactive interval. The default value is -1.
+   */
+  public static final int DEFAULT_MAX_INACTIVE_INTERVAL = -1;
+
+  /**
+   * The maximum time interval in seconds before entries are expired
+   */
+  private int maxInactiveInterval = DEFAULT_MAX_INACTIVE_INTERVAL;
+  
+  /**
+   * The <code>CustomExpiry</code> to be used
+   */
+  private CustomExpiry customExpiry;
+  
+  /**
+   * Whether delta replication across a <code>Gateway</code> is enabled.
+   */
+  private boolean enableGatewayDeltaReplication = false;
+  
+  /**
+   * Whether replication across a <code>Gateway</code> is enabled.
+   */
+  private boolean enableGatewayReplication = false;
+  
+  /**
+   * Whether to add a <code>DebugCacheListener</code> to the <code>Region</code>.
+   */
+  private boolean enableDebugListener = false;
+
+  /**
+   * Whether to add a cache listener for session expiration events
+   */
+  private boolean enableSessionExpirationCacheListener = false;
+  
+  /**
+   * name for the CacheWriter to be associated with this region. This cache writer must have a
+   * zero arg constructor and must be present on the classpath on the server.
+   */
+  private String cacheWriterName;
+  
+  /**
+   * Default constructor used by the <code>DataSerialiable</code> interface
+   */
+  public RegionConfiguration() {}
+  
+  /**
+   * Sets the name of the <code>Region</code> to be created
+   * 
+   * @param regionName
+   *          The name of the <code>Region</code> to be created
+   */
+  public void setRegionName(String regionName) {
+    this.regionName = regionName;
+  }
+  
+  /**
+   * Returns the name of the <code>Region</code> to be created
+   * 
+   * @return the name of the <code>Region</code> to be created
+   */
+  public String getRegionName() {
+    return this.regionName;
+  }
+  
+  /**
+   * Sets the id of the <code>RegionAttributes</code> to be used
+   * 
+   * @param regionAttributesId
+   *          The id of the <code>RegionAttributes</code> to be used
+   */
+  public void setRegionAttributesId(String regionAttributesId) {
+    this.regionAttributesId = regionAttributesId;
+  }
+
+  /**
+   * Returns the id of the <code>RegionAttributes</code> to be used
+   * 
+   * @return the id of the <code>RegionAttributes</code> to be used
+   */
+  public String getRegionAttributesId() {
+    return this.regionAttributesId;
+  }
+  
+  /**
+   * Sets the maximum time interval in seconds before entries are expired
+   * 
+   * @param maxInactiveInterval
+   *          The maximum time interval in seconds before entries are expired
+   */
+  public void setMaxInactiveInterval(int maxInactiveInterval) {
+    this.maxInactiveInterval = maxInactiveInterval;
+  }
+  
+  /**
+   * Returns the maximum time interval in seconds entries are expired
+   * 
+   * @return the maximum time interval in seconds before entries are expired
+   */
+  public int getMaxInactiveInterval() {
+    return this.maxInactiveInterval;
+  }
+
+  /**
+   * Sets the <code>CustomExpiry</code> to be used
+   * 
+   * @param customExpiry
+   *          The <code>CustomExpiry</code> to be used
+   */
+  public void setCustomExpiry(CustomExpiry customExpiry) {
+    this.customExpiry = customExpiry;
+  }
+  
+  /**
+   * Returns the <code>CustomExpiry</code> to be used
+   * 
+   * @return the <code>CustomExpiry</code> to be used
+   */
+  public CustomExpiry getCustomExpiry() {
+    return this.customExpiry;
+  }
+  
+  /**
+   * Enables/disables delta replication across a <code>Gateway</code>.
+   * 
+   * @param enableGatewayDeltaReplication
+   *          true to enable, false to disable gateway delta replication.
+   */
+  public void setEnableGatewayDeltaReplication(boolean enableGatewayDeltaReplication) {
+    this.enableGatewayDeltaReplication = enableGatewayDeltaReplication;
+  }
+
+  /**
+   * Returns whether delta replication across a <code>Gateway</code> is enabled.
+   *
+   * @return whether delta replication across a <code>Gateway</code> is enabled
+   */
+  public boolean getEnableGatewayDeltaReplication() {
+    return this.enableGatewayDeltaReplication;
+  }
+
+  /**
+   * Enables/disables replication across a <code>Gateway</code>.
+   * 
+   * @param enableGatewayReplication
+   *          true to enable, false to disable gateway replication.
+   */
+  public void setEnableGatewayReplication(boolean enableGatewayReplication) {
+    this.enableGatewayReplication = enableGatewayReplication;
+  }
+
+  /**
+   * Returns whether replication across a <code>Gateway</code> is enabled.
+   *
+   * @return whether replication across a <code>Gateway</code> is enabled
+   */
+  public boolean getEnableGatewayReplication() {
+    return this.enableGatewayReplication;
+  }
+
+  /**
+   * Enables/disables a debug <code>CacheListener</code>.
+   * 
+   * @param enableDebugListener
+   *          true to enable, false to disable debug <code>CacheListener</code>.
+   */
+  public void setEnableDebugListener(boolean enableDebugListener) {
+    this.enableDebugListener = enableDebugListener;
+  }
+  
+  /**
+   * Returns whether a debug <code>CacheListener</code> is enabled.
+   * 
+   * @return whether a debug <code>CacheListener</code> is enabled
+   */
+  public boolean getEnableDebugListener() {
+    return this.enableDebugListener;
+  }
+
+  public void setSessionExpirationCacheListener(boolean enableSessionExpirationCacheListener) {
+    this.enableSessionExpirationCacheListener = enableSessionExpirationCacheListener;
+  }
+
+  public boolean getSessionExpirationCacheListener() {
+    return this.enableSessionExpirationCacheListener;
+  }
+
+  public void toData(DataOutput out) throws IOException {
+    DataSerializer.writeString(this.regionName, out);
+    DataSerializer.writeString(this.regionAttributesId, out);
+    DataSerializer.writePrimitiveInt(this.maxInactiveInterval, out);
+    DataSerializer.writeObject(this.customExpiry, out);
+    DataSerializer.writeBoolean(this.enableGatewayDeltaReplication, out);
+    DataSerializer.writeBoolean(this.enableGatewayReplication, out);
+    DataSerializer.writeBoolean(this.enableDebugListener, out);
+    DataSerializer.writeString(this.cacheWriterName, out);
+    DataSerializer.writeBoolean(this.enableSessionExpirationCacheListener, out);
+  }
+
+  public void fromData(DataInput in) throws IOException, ClassNotFoundException {
+    this.regionName = DataSerializer.readString(in);
+    this.regionAttributesId = DataSerializer.readString(in);
+    this.maxInactiveInterval = DataSerializer.readPrimitiveInt(in);
+    this.customExpiry = DataSerializer.readObject(in);
+    this.enableGatewayDeltaReplication = DataSerializer.readBoolean(in);
+    this.enableGatewayReplication = DataSerializer.readBoolean(in);
+    this.enableDebugListener = DataSerializer.readBoolean(in);
+    this.cacheWriterName = DataSerializer.readString(in);
+
+    // This allows for backwards compatibility with 2.1 clients
+    if (((InputStream)in).available() > 0) {
+      this.enableSessionExpirationCacheListener = DataSerializer.readBoolean(in);
+    } else {
+      this.enableSessionExpirationCacheListener = false;
+    }
+  }
+
+  /**
+   * Registers an <code>Instantiator</code> for the
+   * <code>SessionConfiguration</code> class
+   */
+  public static void registerInstantiator(int id) {
+    Instantiator.register(new Instantiator(RegionConfiguration.class, id) {
+      public DataSerializable newInstance() {
+        return new RegionConfiguration();
+      }
+    });
+  }
+  
+  public String toString() {
+    return new StringBuilder()
+      .append("RegionConfiguration[")
+      .append("regionName=")
+      .append(this.regionName)
+      .append("; regionAttributesId=")
+      .append(this.regionAttributesId)
+      .append("; maxInactiveInterval=")
+      .append(this.maxInactiveInterval)
+      .append("; enableGatewayDeltaReplication=")
+      .append(this.enableGatewayDeltaReplication)
+      .append("; enableGatewayReplication=")
+      .append(this.enableGatewayReplication)
+      .append("; enableDebugListener=")
+      .append(this.enableDebugListener)
+      .append("; enableSessionExpirationCacheListener=")
+      .append(this.enableSessionExpirationCacheListener)
+      .append("; cacheWriter=")
+      .append(this.cacheWriterName)
+      .append("]")
+      .toString();
+  }
+
+  /**
+   * set the fully qualified name of the {@link CacheWriter} to be created on
+   * the server. The cacheWriter must have a zero arg constructor, and must be
+   * present on the classpath on the server.
+   * @param cacheWriterName fully qualified class name of the cacheWriter
+   */
+  public void setCacheWriterName(String cacheWriterName) {
+    this.cacheWriterName = cacheWriterName;
+  }
+
+  public String getCacheWriterName() {
+    return cacheWriterName;
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionConfigurationCacheListener.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionConfigurationCacheListener.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionConfigurationCacheListener.java
new file mode 100644
index 0000000..2883b0a
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionConfigurationCacheListener.java
@@ -0,0 +1,106 @@
+/*=========================================================================
+ * 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.util;
+
+import com.gemstone.gemfire.cache.*;
+
+import com.gemstone.gemfire.cache.util.CacheListenerAdapter;
+import java.util.Properties;
+
+public class RegionConfigurationCacheListener extends CacheListenerAdapter<String,RegionConfiguration> implements Declarable {
+
+  private Cache cache;
+  
+  public RegionConfigurationCacheListener() {
+    this.cache = CacheFactory.getAnyInstance();
+  }
+
+  public void afterCreate(EntryEvent<String,RegionConfiguration> event) {
+    RegionConfiguration configuration = event.getNewValue();
+    if (this.cache.getLogger().fineEnabled()) {
+      this.cache.getLogger().fine("RegionConfigurationCacheListener received afterCreate for region " + event.getKey());
+    }
+    // Create region
+    // this is a replicate region, and many VMs can be doing create region
+    // simultaneously, so ignore the RegionExistsException
+    try {
+      Region region = RegionHelper.createRegion(this.cache, configuration);
+      if (this.cache.getLogger().fineEnabled()) {
+        this.cache.getLogger().fine("RegionConfigurationCacheListener created region: " + region);
+      }
+    } catch (RegionExistsException exists) {
+      // ignore
+      this.cache.getLogger().fine("Region with configuration "+configuration+" existed");
+    }
+  }
+  
+  @Override
+  public void afterUpdate(EntryEvent<String, RegionConfiguration> event) {
+    // a region could have been destroyed and then
+    // re-created, we want to create region again
+    // on remote nodes
+    afterCreate(event);
+  }
+  
+  public void afterRegionCreate(RegionEvent<String,RegionConfiguration> event) {
+    StringBuilder builder1=null, builder2=null;
+    Region<String,RegionConfiguration> region = event.getRegion();
+    if (this.cache.getLogger().fineEnabled()) {
+      builder1 = new StringBuilder();
+      int regionSize = region.size();
+      if (regionSize > 0) {
+        builder1
+          .append("RegionConfigurationCacheListener region ")
+          .append(region.getName())
+          .append(" has been initialized with the following ")
+          .append(regionSize)
+          .append(" region configurations:\n");
+        builder2 = new StringBuilder();
+        builder2
+          .append("RegionConfigurationCacheListener created the following ")
+          .append(regionSize)
+          .append(" regions:\n");
+      } else {
+        builder1
+          .append("RegionConfigurationCacheListener region ")
+          .append(region.getName())
+          .append(" has been initialized with no region configurations");
+      }
+    }
+    for (RegionConfiguration configuration : region.values()) {
+      if (this.cache.getLogger().fineEnabled()) {
+        builder1
+          .append("\t")
+          .append(configuration);
+      }
+      try {
+        Region createRegion = RegionHelper.createRegion(this.cache, configuration);
+        if (this.cache.getLogger().fineEnabled()) {
+          builder2
+            .append("\t")
+            .append(createRegion);
+        }
+      } catch (RegionExistsException exists) {
+        // could have been concurrently created by another function
+        if (this.cache.getLogger().fineEnabled()) {
+          builder2.append("\t").append(" region existed");
+        }
+      }
+    
+    }
+    if (this.cache.getLogger().fineEnabled()) {
+      this.cache.getLogger().fine(builder1.toString());
+      if (builder2 != null) {
+        this.cache.getLogger().fine(builder2.toString());
+      }
+    }
+  }
+
+  public void init(Properties p) {
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionHelper.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionHelper.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionHelper.java
new file mode 100644
index 0000000..91d1222
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionHelper.java
@@ -0,0 +1,238 @@
+/*=========================================================================
+ * 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.util;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.CancellationException;
+
+import com.gemstone.gemfire.cache.AttributesFactory;
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache.CacheWriter;
+import com.gemstone.gemfire.cache.ExpirationAction;
+import com.gemstone.gemfire.cache.ExpirationAttributes;
+import com.gemstone.gemfire.cache.GemFireCache;
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.cache.RegionAttributes;
+import com.gemstone.gemfire.cache.control.RebalanceFactory;
+import com.gemstone.gemfire.cache.control.RebalanceOperation;
+import com.gemstone.gemfire.cache.control.RebalanceResults;
+import com.gemstone.gemfire.cache.control.ResourceManager;
+import com.gemstone.gemfire.cache.partition.PartitionMemberInfo;
+import com.gemstone.gemfire.cache.partition.PartitionRebalanceInfo;
+import com.gemstone.gemfire.cache.partition.PartitionRegionHelper;
+import com.gemstone.gemfire.internal.cache.xmlcache.CacheXmlGenerator;
+import com.gemstone.gemfire.internal.cache.xmlcache.RegionAttributesCreation;
+import com.gemstone.gemfire.modules.gatewaydelta.GatewayDeltaForwarderCacheListener;
+import com.gemstone.gemfire.modules.session.catalina.callback.SessionExpirationCacheListener;
+
+@SuppressWarnings({"deprecation","unchecked"})
+public class RegionHelper {
+  
+  public static final String NAME = "gemfire_modules";
+
+  public static Region createRegion(Cache cache, RegionConfiguration configuration) {
+    // Use the createRegion method so that the RegionAttributes creation can be reused by validate.
+    RegionAttributes requestedRegionAttributes = getRegionAttributes(cache, configuration);
+    Region region = cache.createRegion(configuration.getRegionName(), requestedRegionAttributes);
+    
+    // Log the cache xml if debugging is enabled. I'd like to be able to just
+    // log the region, but that API is not available.
+    if (configuration.getEnableDebugListener()) {
+      cache.getLogger().info("Created new session region: " + region);
+    	cache.getLogger().info(generateCacheXml(cache));
+    }
+    return region;
+  }
+  
+  public static void validateRegion(Cache cache, RegionConfiguration configuration, Region region) {
+    // Get the attributes of the existing region
+    RegionAttributes existingAttributes = region.getAttributes();
+
+    // Create region attributes creation on existing region attributes.
+    // The RAC is created to execute the sameAs method.
+    RegionAttributesCreation existingRACreation = new RegionAttributesCreation(existingAttributes, false);
+
+    // Create requested region attributes
+    RegionAttributes requestedRegionAttributes = getRegionAttributes(cache, configuration);
+
+    // Compare the two region attributes. This method either returns true or throws a RuntimeException.
+    existingRACreation.sameAs(requestedRegionAttributes);
+  }
+  
+  public static RebalanceResults rebalanceRegion(Region region)
+      throws CancellationException, InterruptedException {
+    String regionName = region.getName(); // FilterByName only looks at name and not full path
+    if (!PartitionRegionHelper.isPartitionedRegion(region)) {
+      StringBuilder builder = new StringBuilder();
+      builder
+        .append("Region ")
+        .append(regionName)
+        .append(" is not partitioned. Instead, it is ")
+        .append(region.getAttributes().getDataPolicy())
+        .append(". It can't be rebalanced.");
+      throw new IllegalArgumentException(builder.toString());
+    }
+
+    // Rebalance the region
+    ResourceManager resourceManager = region.getCache().getResourceManager();
+    RebalanceFactory rebalanceFactory = resourceManager.createRebalanceFactory();
+    Set<String> regionsToRebalance = new HashSet<String>();
+    regionsToRebalance.add(regionName);
+    rebalanceFactory.includeRegions(regionsToRebalance);
+    RebalanceOperation rebalanceOperation = rebalanceFactory.start();
+    
+    // Return the results
+    return rebalanceOperation.getResults();
+  }
+  
+  public static RebalanceResults rebalanceCache(GemFireCache cache)
+      throws CancellationException, InterruptedException {
+    ResourceManager resourceManager = cache.getResourceManager();
+    RebalanceFactory rebalanceFactory = resourceManager.createRebalanceFactory();
+    RebalanceOperation rebalanceOperation = rebalanceFactory.start();
+    return rebalanceOperation.getResults();
+  }
+
+  public static String generateCacheXml(Cache cache) {
+    try {
+	  StringWriter sw = new StringWriter();
+      PrintWriter pw = new PrintWriter(sw, true);
+      CacheXmlGenerator.generate(cache, pw);
+      pw.close();
+      return sw.toString();
+    } catch (Exception ex) {
+      return "";
+    }
+  }
+
+  private static RegionAttributes getRegionAttributes(Cache cache, RegionConfiguration configuration) {
+    // Create the requested attributes
+    RegionAttributes baseRequestedAttributes = cache.getRegionAttributes(configuration.getRegionAttributesId());
+    if (baseRequestedAttributes == null) {
+      throw new IllegalArgumentException("No region attributes named " + configuration.getRegionAttributesId() + " are defined.");
+    }
+    AttributesFactory requestedFactory = new AttributesFactory(baseRequestedAttributes);
+
+    // Set the expiration time and action if necessary
+    int maxInactiveInterval = configuration.getMaxInactiveInterval();
+    if (maxInactiveInterval != RegionConfiguration.DEFAULT_MAX_INACTIVE_INTERVAL) {
+      requestedFactory.setStatisticsEnabled(true);
+      if (configuration.getCustomExpiry() == null) {
+        requestedFactory.setEntryIdleTimeout(new ExpirationAttributes(maxInactiveInterval, ExpirationAction.DESTROY));
+      } else {
+        requestedFactory.setCustomEntryIdleTimeout(configuration.getCustomExpiry());
+      }
+    }
+    
+    // Add the gateway delta region cache listener if necessary
+    if (configuration.getEnableGatewayDeltaReplication()) {
+      // Add the listener that forwards created/destroyed deltas to the gateway
+      requestedFactory.addCacheListener(new GatewayDeltaForwarderCacheListener(cache));
+    }
+    
+    // Enable gateway replication if necessary
+    // TODO: Disabled for WAN
+//    requestedFactory.setEnableGateway(configuration.getEnableGatewayReplication());
+    
+    // Add the debug cache listener if necessary
+    if (configuration.getEnableDebugListener()) {
+      requestedFactory.addCacheListener(new DebugCacheListener());
+    }
+
+    if (configuration.getSessionExpirationCacheListener()) {
+      requestedFactory.addCacheListener(new SessionExpirationCacheListener());
+    }
+
+    // Add the cacheWriter if necessary
+    if (configuration.getCacheWriterName() != null) {
+      try {
+        CacheWriter writer = (CacheWriter)Class.forName(
+            configuration.getCacheWriterName()).newInstance();
+        requestedFactory.setCacheWriter(writer);
+      } catch (InstantiationException e) {
+        throw new RuntimeException("Could not set a cacheWriter for the region", e);
+      } catch (IllegalAccessException e) {
+        throw new RuntimeException("Could not set a cacheWriter for the region", e);
+      } catch (ClassNotFoundException e) {
+        throw new RuntimeException("Could not set a cacheWriter for the region", e);
+      }
+    }
+    return requestedFactory.create();
+  }
+
+  private RegionHelper() {}
+
+  public static String getRebalanceResultsMessage(RebalanceResults results) {
+    StringBuilder builder = new StringBuilder();
+    for (PartitionRebalanceInfo rebalanceInfo : results.getPartitionRebalanceDetails()) {
+      // Log the overall results
+      fillInRebalanceResultsSummary(builder, rebalanceInfo);
+      
+      // Log the 'Before' results
+      fillInRebalanceResultsMemberDetails(builder, rebalanceInfo.getPartitionMemberDetailsBefore(), "Before");
+       
+      // Log the 'After' results
+      fillInRebalanceResultsMemberDetails(builder, rebalanceInfo.getPartitionMemberDetailsAfter(), "After");
+    }
+    return builder.toString();
+  }
+  
+  private static void fillInRebalanceResultsSummary(StringBuilder builder, PartitionRebalanceInfo rebalanceInfo) {
+    builder
+      .append("\nRebalanced region ")
+      .append(rebalanceInfo.getRegionPath())
+      .append(" in ")
+      .append(rebalanceInfo.getTime())
+      .append(" ms")
+      
+      .append("\nCreated ")
+      .append(rebalanceInfo.getBucketCreatesCompleted())
+      .append(" buckets containing ")
+      .append(rebalanceInfo.getBucketCreateBytes())
+      .append(" bytes in ")
+      .append(rebalanceInfo.getBucketCreateTime())
+      .append(" ms")
+      
+      .append("\nTransferred ")
+      .append(rebalanceInfo.getBucketTransfersCompleted())
+      .append(" buckets containing ")
+      .append(rebalanceInfo.getBucketTransferBytes())
+      .append(" bytes in ")
+      .append(rebalanceInfo.getBucketTransferTime())
+      .append(" ms")
+      
+      .append("\nTransferred ")
+      .append(rebalanceInfo.getPrimaryTransfersCompleted())
+      .append(" primary buckets in ")
+      .append(rebalanceInfo.getPrimaryTransferTime())
+      .append(" ms");
+  }
+
+  private static void fillInRebalanceResultsMemberDetails(StringBuilder builder, Set<PartitionMemberInfo> memberInfoSet, String when) {
+    builder
+      .append("\nMember Info ")
+      .append(when)
+      .append(" Rebalance:\n");
+    for (PartitionMemberInfo info : memberInfoSet) {
+      builder
+        .append("\tdistributedMember=")
+        .append(info.getDistributedMember())
+        .append(", configuredMaxMemory=")
+        .append(info.getConfiguredMaxMemory())
+        .append(", size=")
+        .append(info.getSize())
+        .append(", bucketCount=")
+        .append(info.getBucketCount())
+        .append(", primaryCount=")
+        .append(info.getPrimaryCount());
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionSizeFunction.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionSizeFunction.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionSizeFunction.java
new file mode 100644
index 0000000..7207ce4
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionSizeFunction.java
@@ -0,0 +1,47 @@
+/*=========================================================================
+ * 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.util;
+
+import java.util.Properties;
+
+import com.gemstone.gemfire.cache.Declarable;
+import com.gemstone.gemfire.cache.execute.Function;
+import com.gemstone.gemfire.cache.execute.FunctionContext;
+import com.gemstone.gemfire.cache.execute.RegionFunctionContext;
+
+public class RegionSizeFunction implements Function, Declarable {
+
+  private static final long serialVersionUID = -2791590491585777990L;
+  
+  public static final String ID = "region-size-function";
+
+	public void execute(FunctionContext context) {
+		RegionFunctionContext rfc = (RegionFunctionContext) context;
+		context.getResultSender().lastResult(rfc.getDataSet().size());
+	}
+
+	public String getId() {
+		return ID;
+	}
+
+	public boolean hasResult() {
+		return true;
+	}
+
+	public boolean optimizeForWrite() {
+		return true;
+	}
+
+	public boolean isHA() {
+		return true;
+	}
+
+  @Override
+  public void init(Properties arg0) {
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionStatus.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionStatus.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionStatus.java
new file mode 100644
index 0000000..076456b
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionStatus.java
@@ -0,0 +1,5 @@
+package com.gemstone.gemfire.modules.util;
+
+public enum RegionStatus {
+  VALID, INVALID
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ResourceManagerValidator.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ResourceManagerValidator.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ResourceManagerValidator.java
new file mode 100644
index 0000000..0090c4e
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ResourceManagerValidator.java
@@ -0,0 +1,146 @@
+/*=========================================================================
+ * 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.util;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.gemstone.gemfire.cache.GemFireCache;
+import com.gemstone.gemfire.cache.control.ResourceManager;
+
+public class ResourceManagerValidator {
+  
+  private static final Pattern DIGIT_PATTERN = Pattern.compile("(\\d+|[^\\d]+)");
+
+  public static void validateJavaStartupParameters(GemFireCache cache) {
+    // Get the input arguments
+    ResourceManager rm = cache.getResourceManager();
+    RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
+    List<String> inputArguments = runtimeBean.getInputArguments();
+    if (cache.getLogger().fineEnabled()) {
+      cache.getLogger().fine("Full input java arguments: " + inputArguments);
+    }
+    
+    // Validate the arguments based on VM vendor
+    String vmVendor = runtimeBean.getVmVendor();
+    if (vmVendor.startsWith("Sun") || vmVendor.startsWith("Apple")) {
+      // java.vm.vendor = Sun Microsystems Inc. || java.vm.vendor = Apple Inc.
+      validateSunArguments(cache, rm, inputArguments);
+    } else if (vmVendor.startsWith("IBM")) {
+      // java.vm.vendor = IBM Corporation
+      // TODO validate IBM input arguments
+    } else if (vmVendor.startsWith("BEA")) {
+      // java.vm.vendor = BEA Systems, Inc.
+      // TODO validate JRockit input arguments
+    }
+  }
+  
+  private static void validateSunArguments(GemFireCache cache, ResourceManager rm, List<String> inputArguments) {
+    // Retrieve the -Xms, -Xmx, UseConcMarkSweepGC and CMSInitiatingOccupancyFraction arguments
+    String dashXms=null, dashXmx=null, useCMS=null, cmsIOF=null;
+    for (String argument : inputArguments) {
+      if (argument.startsWith("-Xms")) {
+        dashXms = argument;
+      } else if (argument.startsWith("-Xmx")) {
+        dashXmx = argument;
+      } else if (argument.equals("-XX:+UseConcMarkSweepGC")) {
+        useCMS = argument;
+      } else if (argument.startsWith("-XX:CMSInitiatingOccupancyFraction")) {
+        cmsIOF = argument;
+      }
+    }
+    if (cache.getLogger().fineEnabled()) {
+      StringBuilder builder = new StringBuilder();
+      builder
+        .append("Relevant input java arguments: ")
+        .append("dashXms=")
+        .append(dashXms)
+        .append("; dashXmx=")
+        .append(dashXmx)
+        .append("; useCMS=")
+        .append(useCMS)
+        .append("; cmsIOF=")
+        .append(cmsIOF);
+      cache.getLogger().fine(builder.toString());
+    }
+    
+    // Validate the heap parameters
+    validateJavaHeapParameters(cache, dashXms, dashXmx);
+    
+    // Verify CMS is specified
+    verifyCMSGC(cache, useCMS);
+    
+    // Verify CMSInitiatingOccupancyFraction is specified
+    verifyCMSInitiatingOccupancyFraction(cache, rm, cmsIOF);
+  }
+  
+  private static void validateJavaHeapParameters(GemFireCache cache, String dashXms, String dashXmx) {
+    if (dashXms == null) {
+      cache.getLogger().warning("Setting the initial size of the heap (configured using -Xms) is recommended so that GemFire cache eviction is optimal");
+    } else if (dashXmx == null) {
+      cache.getLogger().warning("Setting the maximum size of the heap (configured using -Xmx) is recommended so that GemFire cache eviction is optimal");
+    } else {
+      // Neither heap parameter is null. Parse them and verify they are the same.
+      List<String> dashXmsList = splitAtDigits(dashXms);
+      String dashXmsStr = dashXmsList.get(1);
+      List<String> dashXmxList = splitAtDigits(dashXmx);
+      String dashXmxStr = dashXmxList.get(1);
+      if (!dashXmsStr.equals(dashXmxStr)) {
+        StringBuilder builder = new StringBuilder();
+        builder
+          .append("Setting the initial (")
+          .append(dashXmsStr)
+          .append(dashXmsList.get(2))
+          .append(") and maximum (")
+          .append(dashXmxStr)
+          .append(dashXmxList.get(2))
+          .append(") sizes of the heap the same is recommended so that GemFire cache eviction is optimal");
+        cache.getLogger().warning(builder.toString());
+      }
+    }
+  }
+  
+  private static void verifyCMSGC(GemFireCache cache, String useCMS) {
+    if (useCMS == null) {
+      cache.getLogger().warning("Using the concurrent garbage collector (configured using -XX:+UseConcMarkSweepGC) is recommended so that GemFire cache eviction is optimal");
+    }  
+  }
+  
+  private static void verifyCMSInitiatingOccupancyFraction(GemFireCache cache, ResourceManager rm, String cmsIOF) {
+    if (cmsIOF == null) {
+      cache.getLogger().warning("Setting the CMS initiating occupancy fraction (configured using -XX:CMSInitiatingOccupancyFraction=N) is recommended so that GemFire cache eviction is optimal");
+    } else {
+      // Parse the CMSInitiatingOccupancyFraction. Verify it is less than both eviction and critical thresholds.
+      int cmsIOFVal = Integer.parseInt(cmsIOF.split("=")[1]);
+      float currentEvictionHeapPercentage = rm.getEvictionHeapPercentage();
+      if (currentEvictionHeapPercentage !=0 && currentEvictionHeapPercentage < cmsIOFVal) {
+        cache.getLogger().warning("Setting the CMS initiating occupancy fraction (" + cmsIOFVal + ") less than the eviction heap percentage (" + currentEvictionHeapPercentage + ") is recommended so that GemFire cache eviction is optimal");
+      }
+      float currentCriticalHeapPercentage = rm.getCriticalHeapPercentage();
+      if (currentCriticalHeapPercentage !=0 && currentCriticalHeapPercentage < cmsIOFVal) {
+        cache.getLogger().warning("Setting the CMS initiating occupancy fraction (" + cmsIOFVal + ") less than the critical heap percentage (" + currentCriticalHeapPercentage + ") is recommended so that GemFire cache eviction is optimal");
+      }
+    }
+  }
+  
+  private static List<String> splitAtDigits(String input) {
+    Matcher matcher = DIGIT_PATTERN.matcher(input);
+    List<String> result = new ArrayList<String>();
+    while (matcher.find()) {
+      result.add(matcher.group());
+    }
+    return result;
+  }
+
+  private ResourceManagerValidator() {}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/SessionCustomExpiry.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/SessionCustomExpiry.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/SessionCustomExpiry.java
new file mode 100644
index 0000000..f6ddece
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/SessionCustomExpiry.java
@@ -0,0 +1,53 @@
+/*=========================================================================
+ * 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.util;
+
+import java.io.Serializable;
+import java.util.Properties;
+
+import com.gemstone.gemfire.cache.CustomExpiry;
+import com.gemstone.gemfire.cache.Declarable;
+import com.gemstone.gemfire.cache.ExpirationAction;
+import com.gemstone.gemfire.cache.ExpirationAttributes;
+import com.gemstone.gemfire.cache.Region;
+import javax.servlet.http.HttpSession;
+
+@SuppressWarnings("serial")
+public class SessionCustomExpiry implements CustomExpiry<String, HttpSession>, Serializable, Declarable {
+
+  private static final long serialVersionUID = 182735509690640051L;
+
+  private static final ExpirationAttributes EXPIRE_NOW = new ExpirationAttributes(1, ExpirationAction.DESTROY);
+
+  public ExpirationAttributes getExpiry(Region.Entry<String, HttpSession> entry) {
+    HttpSession session = entry.getValue();
+    if (session != null) {
+      return new ExpirationAttributes(entry.getValue().getMaxInactiveInterval(), ExpirationAction.DESTROY);
+    } else {
+      return EXPIRE_NOW;
+    }
+  }
+
+  public void close() {}
+  
+  public void init(Properties props) {}
+  
+  public boolean equals(Object obj) {
+    // This method is only implemented so that RegionCreator.validateRegion works properly.
+    // The EntryIdleTimeout comparison fails because two of these instances are not equal.
+    if (this == obj) {
+      return true;
+    }
+
+    if (obj == null || !(obj instanceof SessionCustomExpiry)) {
+      return false;
+    }
+    
+    return true;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/TouchPartitionedRegionEntriesFunction.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/TouchPartitionedRegionEntriesFunction.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/TouchPartitionedRegionEntriesFunction.java
new file mode 100644
index 0000000..d3df675
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/TouchPartitionedRegionEntriesFunction.java
@@ -0,0 +1,89 @@
+/*=========================================================================
+ * 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.util;
+
+import com.gemstone.gemfire.cache.*;
+
+import com.gemstone.gemfire.cache.execute.*;
+import com.gemstone.gemfire.cache.partition.PartitionRegionHelper;
+
+import java.util.Properties;
+import java.util.Set;
+
+/**
+ * Touches the keys contained in the set of keys by performing a get on the
+ * partitioned region.
+ * 
+ * @author Barry Oglesby
+ */
+public class TouchPartitionedRegionEntriesFunction implements Function, Declarable {
+
+  private static final long serialVersionUID = -3700389655056961153L;
+
+  private final Cache cache;
+  
+  public static final String ID = "touch-partitioned-region-entries";
+  
+  public TouchPartitionedRegionEntriesFunction() {
+    this(CacheFactory.getAnyInstance());
+  }
+  
+  public TouchPartitionedRegionEntriesFunction(Cache cache) {
+    this.cache = cache;
+  }
+  
+  @SuppressWarnings("unchecked")
+  public void execute(FunctionContext context) {
+    RegionFunctionContext rfc = (RegionFunctionContext) context;
+    Set<String> keys = (Set<String>) rfc.getFilter();
+    
+    // Get local (primary) data for the context
+    Region primaryDataSet = PartitionRegionHelper.getLocalDataForContext(rfc);
+    
+    if (this.cache.getLogger().fineEnabled()) {
+      StringBuilder builder = new StringBuilder();
+      builder
+        .append("Function ")
+        .append(ID)
+        .append(" received request to touch ")
+        .append(primaryDataSet.getFullPath())
+        .append("->")
+        .append(keys);
+      this.cache.getLogger().fine(builder.toString());
+    }
+
+    // Retrieve each value to update the lastAccessedTime.
+    // Note: getAll is not supported on LocalDataSet.
+    for (String key : keys) {
+      primaryDataSet.get(key);
+    }
+    
+    // Return result to get around NPE in LocalResultCollectorImpl
+    context.getResultSender().lastResult(true);
+  }
+  
+  public String getId() {
+    return ID;
+  }
+
+  public boolean optimizeForWrite() {
+    return true;
+  }
+
+  public boolean isHA() {
+    return false;
+  }
+
+  public boolean hasResult() {
+    return true;
+  }
+
+  public void init(Properties properties) {
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/TouchReplicatedRegionEntriesFunction.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/TouchReplicatedRegionEntriesFunction.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/TouchReplicatedRegionEntriesFunction.java
new file mode 100644
index 0000000..a73c531
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/TouchReplicatedRegionEntriesFunction.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.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.modules.util;
+
+import com.gemstone.gemfire.cache.*;
+
+import com.gemstone.gemfire.cache.execute.*;
+import com.gemstone.gemfire.cache.partition.PartitionRegionHelper;
+
+import java.util.Properties;
+import java.util.Set;
+
+/**
+ * Touches the keys contained in the set of keys by performing a get on the
+ * replicated region. This is a non-data-aware function invoked using onMembers
+ * or onServers.
+ * 
+ * @author Barry Oglesby
+ */
+public class TouchReplicatedRegionEntriesFunction implements Function, Declarable {
+
+  private static final long serialVersionUID = -7424895036162243564L;
+
+  private final Cache cache;
+  
+  public static final String ID = "touch-replicated-region-entries";
+  
+  public TouchReplicatedRegionEntriesFunction() {
+    this(CacheFactory.getAnyInstance());
+  }
+  
+  public TouchReplicatedRegionEntriesFunction(Cache cache) {
+    this.cache = cache;
+  }
+  
+  public void execute(FunctionContext context) {
+    Object[] arguments = (Object[]) context.getArguments();
+    String regionName = (String) arguments[0];
+    Set<String> keys = (Set<String>) arguments[1];
+    if (this.cache.getLogger().fineEnabled()) {
+      StringBuilder builder = new StringBuilder();
+      builder
+        .append("Function ")
+        .append(ID)
+        .append(" received request to touch ")
+        .append(regionName)
+        .append("->")
+        .append(keys);
+      this.cache.getLogger().fine(builder.toString());
+    }
+
+    // Retrieve the appropriate Region and value to update the lastAccessedTime
+    Region region = this.cache.getRegion(regionName);
+    if (region != null) {
+      region.getAll(keys);
+    }
+    
+    // Return result to get around NPE in LocalResultCollectorImpl
+    context.getResultSender().lastResult(true);
+  }
+  
+  public String getId() {
+    return ID;
+  }
+
+  public boolean optimizeForWrite() {
+    return false;
+  }
+
+  public boolean isHA() {
+    return false;
+  }
+
+  public boolean hasResult() {
+    // Setting this to false caused the onServers method to only execute the
+    // function on one server.
+    return true;
+  }
+
+  public void init(Properties properties) {
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/resources/modules-version.properties
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/resources/modules-version.properties b/extensions/gemfire-modules/src/main/resources/modules-version.properties
new file mode 100644
index 0000000..7a73b41
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/resources/modules-version.properties
@@ -0,0 +1 @@
+version = @VERSION@
\ No newline at end of file