You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ji...@apache.org on 2016/06/21 03:14:27 UTC

[6/9] incubator-geode git commit: client server

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c6e7a3bd/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/command/Put65.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/command/Put65.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/command/Put65.java
index 4ccc03a..156fbbc 100755
--- a/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/command/Put65.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/command/Put65.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 /**
- * 
+ *
  */
 package com.gemstone.gemfire.internal.cache.tier.sockets.command;
 
@@ -35,7 +35,6 @@ import com.gemstone.gemfire.internal.HeapDataOutputStream;
 import com.gemstone.gemfire.internal.InternalDataSerializer;
 import com.gemstone.gemfire.internal.Version;
 import com.gemstone.gemfire.internal.cache.CachedDeserializable;
-import com.gemstone.gemfire.internal.cache.EntryEventImpl;
 import com.gemstone.gemfire.internal.cache.EventID;
 import com.gemstone.gemfire.internal.cache.EventIDHolder;
 import com.gemstone.gemfire.internal.cache.LocalRegion;
@@ -54,6 +53,7 @@ import com.gemstone.gemfire.internal.cache.versions.VersionTag;
 import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
 import com.gemstone.gemfire.internal.logging.log4j.LocalizedMessage;
 import com.gemstone.gemfire.internal.security.AuthorizeRequest;
+import com.gemstone.gemfire.internal.security.GeodeSecurityUtil;
 import com.gemstone.gemfire.internal.util.Breadcrumbs;
 import com.gemstone.gemfire.security.GemFireSecurityException;
 
@@ -73,7 +73,7 @@ public class Put65 extends BaseCommand {
 
   @Override
   public void cmdExecute(Message msg, ServerConnection servConn, long p_start)
-      throws IOException, InterruptedException {
+    throws IOException, InterruptedException {
     long start = p_start;
     Part regionNamePart = null, keyPart = null, valuePart = null, callbackArgPart = null;
     String regionName = null;
@@ -87,11 +87,9 @@ public class Put65 extends BaseCommand {
       boolean interrupted = Thread.interrupted();
       try {
         Thread.sleep(crHelper.emulateSlowServer());
-      }
-      catch (InterruptedException ugh) {
+      } catch (InterruptedException ugh) {
         interrupted = true;
-      }
-      finally {
+      } finally {
         if (interrupted) {
           Thread.currentThread().interrupt();
         }
@@ -110,7 +108,7 @@ public class Put65 extends BaseCommand {
     regionNamePart = msg.getPart(idx++);
     Operation operation;
     try {
-      operation = (Operation)msg.getPart(idx++).getObject();
+      operation = (Operation) msg.getPart(idx++).getObject();
       if (operation == null) { // native clients send a null since the op is java-serialized
         operation = Operation.UPDATE;
       }
@@ -134,10 +132,9 @@ public class Put65 extends BaseCommand {
     }
     keyPart = msg.getPart(idx++);
     try {
-      isDelta = ((Boolean)msg.getPart(idx).getObject()).booleanValue();
+      isDelta = ((Boolean) msg.getPart(idx).getObject()).booleanValue();
       idx += 1;
-    }
-    catch (Exception e) {
+    } catch (Exception e) {
       writeException(msg, MessageType.PUT_DELTA_ERROR, e, false, servConn);
       servConn.setAsTrue(RESPONDED);
       // CachePerfStats not available here.
@@ -149,19 +146,17 @@ public class Put65 extends BaseCommand {
       callbackArgPart = msg.getPart(idx++);
       try {
         callbackArg = callbackArgPart.getObject();
-      }
-      catch (Exception e) {
+      } catch (Exception e) {
         writeException(msg, e, false, servConn);
         servConn.setAsTrue(RESPONDED);
         return;
       }
     }
     regionName = regionNamePart.getString();
-    
+
     try {
       key = keyPart.getStringOrObject();
-    }
-    catch (Exception e) {
+    } catch (Exception e) {
       writeException(msg, e, false, servConn);
       servConn.setAsTrue(RESPONDED);
       return;
@@ -169,7 +164,8 @@ public class Put65 extends BaseCommand {
 
     final boolean isDebugEnabled = logger.isDebugEnabled();
     if (isDebugEnabled) {
-      logger.debug("{}: Received {}put request ({} bytes) from {} for region {} key {} txId {} posdup: {}", servConn.getName(), (isDelta ? " delta " : " "), msg.getPayloadLength(), servConn.getSocketString(), regionName, key, msg.getTransactionId(), msg.isRetry());
+      logger.debug("{}: Received {}put request ({} bytes) from {} for region {} key {} txId {} posdup: {}", servConn.getName(), (isDelta ? " delta " : " "), msg
+        .getPayloadLength(), servConn.getSocketString(), regionName, key, msg.getTransactionId(), msg.isRetry());
     }
 
     // Process the put request
@@ -188,325 +184,304 @@ public class Put65 extends BaseCommand {
         }
         errMessage.append(putMsg);
       }
-      writeErrorResponse(msg, MessageType.PUT_DATA_ERROR,
-          errMessage.toString(), servConn);
+      writeErrorResponse(msg, MessageType.PUT_DATA_ERROR, errMessage.toString(), servConn);
       servConn.setAsTrue(RESPONDED);
+      return;
     }
-    else {
-      LocalRegion region = (LocalRegion)crHelper.getRegion(regionName);
-      if (region == null) {
-        String reason = " was not found during put request";
-        writeRegionDestroyedEx(msg, regionName, reason, servConn);
-        servConn.setAsTrue(RESPONDED);
+
+    LocalRegion region = (LocalRegion) crHelper.getRegion(regionName);
+    if (region == null) {
+      String reason = " was not found during put request";
+      writeRegionDestroyedEx(msg, regionName, reason, servConn);
+      servConn.setAsTrue(RESPONDED);
+      return;
+    }
+
+    if (valuePart.isNull() && operation != Operation.PUT_IF_ABSENT && region.containsKey(key)) {
+      // Invalid to 'put' a null value in an existing key
+      String putMsg = " Attempted to put a null value for existing key " + key;
+      if (isDebugEnabled) {
+        logger.debug("{}:{}", servConn.getName(), putMsg);
       }
-      else if (valuePart.isNull() && operation != Operation.PUT_IF_ABSENT && region.containsKey(key)) {
-        // Invalid to 'put' a null value in an existing key
-        String putMsg = " Attempted to put a null value for existing key "
-            + key;
-        if (isDebugEnabled) {
-          logger.debug("{}:{}", servConn.getName(), putMsg);
+      errMessage.append(putMsg);
+      writeErrorResponse(msg, MessageType.PUT_DATA_ERROR, errMessage.toString(), servConn);
+      servConn.setAsTrue(RESPONDED);
+      return;
+    }
+
+
+    ByteBuffer eventIdPartsBuffer = ByteBuffer.wrap(eventPart.getSerializedForm());
+    long threadId = EventID.readEventIdPartsFromOptmizedByteArray(eventIdPartsBuffer);
+    long sequenceId = EventID.readEventIdPartsFromOptmizedByteArray(eventIdPartsBuffer);
+
+    EventIDHolder clientEvent = new EventIDHolder(new EventID(servConn.getEventMemberIDByteArray(), threadId, sequenceId));
+
+    Breadcrumbs.setEventId(clientEvent.getEventId());
+
+    // msg.isRetry might be set by v7.0 and later clients
+    if (msg.isRetry()) {
+      //          if (logger.isDebugEnabled()) {
+      //            logger.debug("DEBUG: encountered isRetry in Put65");
+      //          }
+      clientEvent.setPossibleDuplicate(true);
+      if (region.getAttributes().getConcurrencyChecksEnabled()) {
+        // recover the version tag from other servers
+        clientEvent.setRegion(region);
+        if (!recoverVersionTagForRetriedOperation(clientEvent)) {
+          clientEvent.setPossibleDuplicate(false); // no-one has seen this event
         }
-        errMessage.append(putMsg);
-        writeErrorResponse(msg, MessageType.PUT_DATA_ERROR, errMessage
-            .toString(), servConn);
-        servConn.setAsTrue(RESPONDED);
       }
-      else {
-        // try {
-        // this.eventId = (EventID)eventPart.getObject();
-        ByteBuffer eventIdPartsBuffer = ByteBuffer.wrap(eventPart
-            .getSerializedForm());
-        long threadId = EventID
-            .readEventIdPartsFromOptmizedByteArray(eventIdPartsBuffer);
-        long sequenceId = EventID
-            .readEventIdPartsFromOptmizedByteArray(eventIdPartsBuffer);
+    }
 
-        EventIDHolder clientEvent = new EventIDHolder(
-            new EventID(servConn.getEventMemberIDByteArray(),
-              threadId, sequenceId));
-        
-        Breadcrumbs.setEventId(clientEvent.getEventId());
+    boolean result = false;
+    boolean sendOldValue = false;
+    boolean oldValueIsObject = true;
+    Object oldValue = null;
 
-        // msg.isRetry might be set by v7.0 and later clients
-        if (msg.isRetry()) {
-//          if (logger.isDebugEnabled()) {
-//            logger.debug("DEBUG: encountered isRetry in Put65");
-//          }
-          clientEvent.setPossibleDuplicate(true);
-          if (region.getAttributes().getConcurrencyChecksEnabled()) {
-            // recover the version tag from other servers
-            clientEvent.setRegion(region);
-            if (!recoverVersionTagForRetriedOperation(clientEvent)) {
-              clientEvent.setPossibleDuplicate(false); // no-one has seen this event
-            }
-          }
+    try {
+      Object value = null;
+      if (!isDelta) {
+        value = valuePart.getSerializedForm();
+      }
+      boolean isObject = valuePart.isObject();
+      boolean isMetaRegion = region.isUsedForMetaRegion();
+      msg.setMetaRegion(isMetaRegion);
+      AuthorizeRequest authzRequest = null;
+      if (!isMetaRegion) {
+        authzRequest = servConn.getAuthzRequest();
+      }
+      if (authzRequest != null) {
+        // TODO SW: This is to handle DynamicRegionFactory create
+        // calls. Rework this when the semantics of DynamicRegionFactory are
+        // cleaned up.
+        if (DynamicRegionFactory.regionIsDynamicRegionList(regionName)) {
+          authzRequest.createRegionAuthorize((String) key);
+        }
+        // Allow PUT operations on meta regions (bug #38961)
+        else {
+          PutOperationContext putContext = authzRequest.putAuthorize(regionName, key, value, isObject, callbackArg);
+          value = putContext.getValue();
+          isObject = putContext.isObject();
+          callbackArg = putContext.getCallbackArg();
         }
-        
-        boolean result = false;
-        boolean sendOldValue = false;
-        boolean oldValueIsObject = true;
-        Object oldValue = null;
+      }
+      if (isDebugEnabled) {
+        logger.debug("processing put65 with operation={}", operation);
+      }
 
-        try {
-          Object value = null;
-          if (!isDelta) {
-            value = valuePart.getSerializedForm();
-          }
-          boolean isObject = valuePart.isObject();
-          boolean isMetaRegion = region.isUsedForMetaRegion();
-          msg.setMetaRegion(isMetaRegion);
-          AuthorizeRequest authzRequest = null;
-          if (!isMetaRegion) {
-            authzRequest = servConn.getAuthzRequest();
-          }
-          if (authzRequest != null) {
-            // TODO SW: This is to handle DynamicRegionFactory create
-            // calls. Rework this when the semantics of DynamicRegionFactory are
-            // cleaned up.
-            if (DynamicRegionFactory.regionIsDynamicRegionList(regionName)) {
-              authzRequest.createRegionAuthorize((String)key);
-            }
-            // Allow PUT operations on meta regions (bug #38961)
-            else {
-              PutOperationContext putContext = authzRequest.putAuthorize(
-                  regionName, key, value, isObject, callbackArg);
-              value = putContext.getValue();
-              isObject = putContext.isObject();
-              callbackArg = putContext.getCallbackArg();
-            }
-          }
+      GeodeSecurityUtil.authorizeRegionWrite(regionName, key.toString());
+
+      // If the value is 1 byte and the byte represents null,
+      // attempt to create the entry. This test needs to be
+      // moved to DataSerializer or DataSerializer.NULL needs
+      // to be publicly accessible.
+      if (operation == Operation.PUT_IF_ABSENT) {
+        //            try {
+        if (msg.isRetry() && clientEvent.getVersionTag() != null) {
+          // bug #46590 the operation was successful the last time since it
+          // was applied to the cache, so return success and the recovered
+          // version tag
           if (isDebugEnabled) {
-            logger.debug("processing put65 with operation={}", operation);
+            logger.debug("putIfAbsent operation was successful last time with version {}", clientEvent.getVersionTag());
           }
-          // If the value is 1 byte and the byte represents null,
-          // attempt to create the entry. This test needs to be
-          // moved to DataSerializer or DataSerializer.NULL needs
-          // to be publicly accessible.
-          if (operation == Operation.PUT_IF_ABSENT) {
-//            try {
-            if (msg.isRetry() && clientEvent.getVersionTag() != null) {
-              // bug #46590 the operation was successful the last time since it
-              // was applied to the cache, so return success and the recovered
-              // version tag
-              if (isDebugEnabled) {
-                logger.debug("putIfAbsent operation was successful last time with version {}", clientEvent.getVersionTag());
-              }
-              // invoke basicBridgePutIfAbsent anyway to ensure that the event is distributed to all
-              // servers - bug #51664
-              region.basicBridgePutIfAbsent(key, value, isObject,
-                  callbackArg, servConn.getProxyID(), true, clientEvent);
-              oldValue = null;
-            } else {
-              oldValue = region.basicBridgePutIfAbsent(key, value, isObject,
-                callbackArg, servConn.getProxyID(), true, clientEvent);
-            }
-            sendOldValue = true;
-            oldValueIsObject = true;
-            Version clientVersion = servConn.getClientVersion();
-            if (oldValue instanceof CachedDeserializable) {
-              oldValue = ((CachedDeserializable)oldValue).getSerializedValue();
-            } else if (oldValue instanceof byte[]) {
-              oldValueIsObject = false;
-            } else if ((oldValue instanceof Token)
-                && clientVersion.compareTo(Version.GFE_651) <= 0) {
-              // older clients don't know that Token is now a DSFID class, so we
-              // put the token in a serialized form they can consume
-              HeapDataOutputStream str = new HeapDataOutputStream(Version.CURRENT);
-              DataOutput dstr = new DataOutputStream(str);
-              InternalDataSerializer.writeSerializableObject(oldValue, dstr);
-              oldValue = str.toByteArray();
-            }
-            result = true;
-//            } catch (Exception e) {
-//              writeException(msg, e, false, servConn);
-//              servConn.setAsTrue(RESPONDED);
-//              return;
-//            }
-            
-          } else if (operation == Operation.REPLACE) {
-//            try {
-              if (requireOldValue) { // <V> replace(<K>, <V>)
-                if (msg.isRetry() && clientEvent.isConcurrencyConflict()
-                    && clientEvent.getVersionTag() != null) {
-                  if (isDebugEnabled) {
-                    logger.debug("replace(k,v) operation was successful last time with version {}", clientEvent.getVersionTag());
-                  }
-                }
-                oldValue = region.basicBridgeReplace(key, value, isObject,
-                  callbackArg, servConn.getProxyID(), true, clientEvent);
-                sendOldValue = !clientEvent.isConcurrencyConflict();
-                oldValueIsObject = true;
-                Version clientVersion = servConn.getClientVersion();
-                if (oldValue instanceof CachedDeserializable) {
-                  oldValue = ((CachedDeserializable)oldValue).getSerializedValue();
-                } else if (oldValue instanceof byte[]) {
-                  oldValueIsObject = false;
-                } else if ((oldValue instanceof Token)
-                    && clientVersion.compareTo(Version.GFE_651) <= 0) {
-                  // older clients don't know that Token is now a DSFID class, so we
-                  // put the token in a serialized form they can consume
-                  HeapDataOutputStream str = new HeapDataOutputStream(Version.CURRENT);
-                  DataOutput dstr = new DataOutputStream(str);
-                  InternalDataSerializer.writeSerializableObject(oldValue, dstr);
-                  oldValue = str.toByteArray();
-                }
-                if (isDebugEnabled) {
-                  logger.debug("returning {} from replace(K,V)", oldValue);
-                }
-                result = true;
-              } else { // boolean replace(<K>, <V>, <V>) {
-                boolean didPut;
-                didPut = region.basicBridgeReplace(key, expectedOldValue,
-                    value, isObject, callbackArg, servConn.getProxyID(), true, clientEvent);
-                if (msg.isRetry() && clientEvent.getVersionTag() != null) {
-                  if (isDebugEnabled) {
-                    logger.debug("replace(k,v,v) operation was successful last time with version {}", clientEvent.getVersionTag());
-                  }
-                  didPut = true;
-                }
-                sendOldValue = true;
-                oldValueIsObject = true;
-                oldValue = didPut? Boolean.TRUE : Boolean.FALSE;
-                if (isDebugEnabled) {
-                  logger.debug("returning {} from replace(K,V,V)", oldValue);
-                }
-                result = true;
-              }
-//            } catch (Exception e) {
-//              writeException(msg, e, false, servConn);
-//              servConn.setAsTrue(RESPONDED);
-//              return;
-//            }
-            
-          } else if (value == null && !isDelta) {
-            // Create the null entry. Since the value is null, the value of the
-            // isObject
-            // the true after null doesn't matter and is not used.
-            result = region.basicBridgeCreate(key, null, true, callbackArg,
-                servConn.getProxyID(), true, clientEvent, false);
-            if (msg.isRetry() && clientEvent.isConcurrencyConflict()
-                && clientEvent.getVersionTag() != null) {
-              result = true;
-              if (isDebugEnabled) {
-                logger.debug("create(k,null) operation was successful last time with version {}", clientEvent.getVersionTag());
-              }
+          // invoke basicBridgePutIfAbsent anyway to ensure that the event is distributed to all
+          // servers - bug #51664
+          region.basicBridgePutIfAbsent(key, value, isObject, callbackArg, servConn.getProxyID(), true, clientEvent);
+          oldValue = null;
+        } else {
+          oldValue = region.basicBridgePutIfAbsent(key, value, isObject, callbackArg, servConn.getProxyID(), true, clientEvent);
+        }
+        sendOldValue = true;
+        oldValueIsObject = true;
+        Version clientVersion = servConn.getClientVersion();
+        if (oldValue instanceof CachedDeserializable) {
+          oldValue = ((CachedDeserializable) oldValue).getSerializedValue();
+        } else if (oldValue instanceof byte[]) {
+          oldValueIsObject = false;
+        } else if ((oldValue instanceof Token) && clientVersion.compareTo(Version.GFE_651) <= 0) {
+          // older clients don't know that Token is now a DSFID class, so we
+          // put the token in a serialized form they can consume
+          HeapDataOutputStream str = new HeapDataOutputStream(Version.CURRENT);
+          DataOutput dstr = new DataOutputStream(str);
+          InternalDataSerializer.writeSerializableObject(oldValue, dstr);
+          oldValue = str.toByteArray();
+        }
+        result = true;
+        //            } catch (Exception e) {
+        //              writeException(msg, e, false, servConn);
+        //              servConn.setAsTrue(RESPONDED);
+        //              return;
+        //            }
+
+      } else if (operation == Operation.REPLACE) {
+        //            try {
+        if (requireOldValue) { // <V> replace(<K>, <V>)
+          if (msg.isRetry() && clientEvent.isConcurrencyConflict() && clientEvent.getVersionTag() != null) {
+            if (isDebugEnabled) {
+              logger.debug("replace(k,v) operation was successful last time with version {}", clientEvent.getVersionTag());
             }
           }
-          else {
-            // Put the entry
-            byte[] delta = null;
-            if (isDelta) {
-              delta = valuePart.getSerializedForm();              
-            }
-            TXManagerImpl txMgr = (TXManagerImpl)servConn.getCache().getCacheTransactionManager();
-            // bug 43068 - use create() if in a transaction and op is CREATE
-            if (txMgr.getTXState() != null && operation.isCreate()) {
-              result = region.basicBridgeCreate(key, (byte[])value, isObject, callbackArg,
-                  servConn.getProxyID(), true, clientEvent, true);
-            } else {
-              result = region.basicBridgePut(key, value, delta, isObject,
-                callbackArg, servConn.getProxyID(), true, clientEvent);
-            }
-            if (msg.isRetry() && clientEvent.isConcurrencyConflict()
-                && clientEvent.getVersionTag() != null) {
-              if (isDebugEnabled) {
-                logger.debug("put(k,v) operation was successful last time with version {}", clientEvent.getVersionTag());
-              }
-              result = true;
-            }
+          oldValue = region.basicBridgeReplace(key, value, isObject, callbackArg, servConn.getProxyID(), true, clientEvent);
+          sendOldValue = !clientEvent.isConcurrencyConflict();
+          oldValueIsObject = true;
+          Version clientVersion = servConn.getClientVersion();
+          if (oldValue instanceof CachedDeserializable) {
+            oldValue = ((CachedDeserializable) oldValue).getSerializedValue();
+          } else if (oldValue instanceof byte[]) {
+            oldValueIsObject = false;
+          } else if ((oldValue instanceof Token) && clientVersion.compareTo(Version.GFE_651) <= 0) {
+            // older clients don't know that Token is now a DSFID class, so we
+            // put the token in a serialized form they can consume
+            HeapDataOutputStream str = new HeapDataOutputStream(Version.CURRENT);
+            DataOutput dstr = new DataOutputStream(str);
+            InternalDataSerializer.writeSerializableObject(oldValue, dstr);
+            oldValue = str.toByteArray();
           }
-          if (result) {
-            servConn.setModificationInfo(true, regionName, key);
+          if (isDebugEnabled) {
+            logger.debug("returning {} from replace(K,V)", oldValue);
           }
-          else {
-            String message = servConn.getName()
-                + ": Failed to put entry for region " + regionName
-                + " key " + key + " value " + valuePart;
+          result = true;
+        } else { // boolean replace(<K>, <V>, <V>) {
+          boolean didPut;
+          didPut = region.basicBridgeReplace(key, expectedOldValue, value, isObject, callbackArg, servConn.getProxyID(), true, clientEvent);
+          if (msg.isRetry() && clientEvent.getVersionTag() != null) {
             if (isDebugEnabled) {
-              logger.debug(message);
+              logger.debug("replace(k,v,v) operation was successful last time with version {}", clientEvent.getVersionTag());
             }
-            throw new Exception(message);
+            didPut = true;
           }
+          sendOldValue = true;
+          oldValueIsObject = true;
+          oldValue = didPut ? Boolean.TRUE : Boolean.FALSE;
+          if (isDebugEnabled) {
+            logger.debug("returning {} from replace(K,V,V)", oldValue);
+          }
+          result = true;
         }
-        catch (RegionDestroyedException rde) {
-          writeException(msg, rde, false, servConn);
-          servConn.setAsTrue(RESPONDED);
-          return;
-        }
-        catch (ResourceException re) {
-          writeException(msg, re, false, servConn);
-          servConn.setAsTrue(RESPONDED);
-          return;
-        }
-        catch (InvalidDeltaException ide) {
-          logger.info(LocalizedMessage.create(LocalizedStrings.UpdateOperation_ERROR_APPLYING_DELTA_FOR_KEY_0_OF_REGION_1,new Object[] { key, regionName }));
-          writeException(msg, MessageType.PUT_DELTA_ERROR, ide, false, servConn);
-          servConn.setAsTrue(RESPONDED);
-          region.getCachePerfStats().incDeltaFullValuesRequested();
-          return;
-        }
-        catch (Exception ce) {
-          // If an interrupted exception is thrown , rethrow it
-          checkForInterrupt(servConn, ce);
+        //            } catch (Exception e) {
+        //              writeException(msg, e, false, servConn);
+        //              servConn.setAsTrue(RESPONDED);
+        //              return;
+        //            }
 
-          // If an exception occurs during the put, preserve the connection
-          writeException(msg, ce, false, servConn);
-          servConn.setAsTrue(RESPONDED);
-          if (ce instanceof GemFireSecurityException) {
-            // Fine logging for security exceptions since these are already
-            // logged by the security logger
-            if (isDebugEnabled) {
-              logger.debug("{}: Unexpected Security exception", servConn.getName(), ce);
-            }
-          }
-          else if (isDebugEnabled) {
-            logger.debug("{}: Unexpected Exception", servConn.getName(), ce);
+      } else if (value == null && !isDelta) {
+        // Create the null entry. Since the value is null, the value of the
+        // isObject
+        // the true after null doesn't matter and is not used.
+        result = region.basicBridgeCreate(key, null, true, callbackArg, servConn.getProxyID(), true, clientEvent, false);
+        if (msg.isRetry() && clientEvent.isConcurrencyConflict() && clientEvent.getVersionTag() != null) {
+          result = true;
+          if (isDebugEnabled) {
+            logger.debug("create(k,null) operation was successful last time with version {}", clientEvent.getVersionTag());
           }
-          return;
         }
-        finally {
-          long oldStart = start;
-          start = DistributionStats.getStatTime();
-          stats.incProcessPutTime(start - oldStart);
+      } else {
+        // Put the entry
+        byte[] delta = null;
+        if (isDelta) {
+          delta = valuePart.getSerializedForm();
         }
-
-        // Increment statistics and write the reply
-        if (region instanceof PartitionedRegion) {
-          PartitionedRegion pr = (PartitionedRegion)region;
-          if (pr.isNetworkHop().byteValue() != (byte)0) {
-            writeReplyWithRefreshMetadata(msg, servConn, pr, sendOldValue, oldValueIsObject, 
-                oldValue, pr.isNetworkHop().byteValue(), clientEvent.getVersionTag());
-            pr.setIsNetworkHop((byte)0);
-            pr.setMetadataVersion(Byte.valueOf((byte)0));
-          }
-          else {
-            writeReply(msg, servConn, sendOldValue, oldValueIsObject, oldValue, clientEvent.getVersionTag());
+        TXManagerImpl txMgr = (TXManagerImpl) servConn.getCache().getCacheTransactionManager();
+        // bug 43068 - use create() if in a transaction and op is CREATE
+        if (txMgr.getTXState() != null && operation.isCreate()) {
+          result = region.basicBridgeCreate(key, (byte[]) value, isObject, callbackArg, servConn.getProxyID(), true, clientEvent, true);
+        } else {
+          result = region.basicBridgePut(key, value, delta, isObject, callbackArg, servConn.getProxyID(), true, clientEvent);
+        }
+        if (msg.isRetry() && clientEvent.isConcurrencyConflict() && clientEvent.getVersionTag() != null) {
+          if (isDebugEnabled) {
+            logger.debug("put(k,v) operation was successful last time with version {}", clientEvent.getVersionTag());
           }
+          result = true;
         }
-        else {
-          writeReply(msg, servConn, sendOldValue, oldValueIsObject, oldValue, clientEvent.getVersionTag());
+      }
+      if (result) {
+        servConn.setModificationInfo(true, regionName, key);
+      } else {
+        String message = servConn.getName() + ": Failed to put entry for region " + regionName + " key " + key + " value " + valuePart;
+        if (isDebugEnabled) {
+          logger.debug(message);
         }
-        servConn.setAsTrue(RESPONDED);
+        throw new Exception(message);
+      }
+    } catch (RegionDestroyedException rde) {
+      writeException(msg, rde, false, servConn);
+      servConn.setAsTrue(RESPONDED);
+      return;
+    } catch (ResourceException re) {
+      writeException(msg, re, false, servConn);
+      servConn.setAsTrue(RESPONDED);
+      return;
+    } catch (InvalidDeltaException ide) {
+      logger.info(LocalizedMessage.create(LocalizedStrings.UpdateOperation_ERROR_APPLYING_DELTA_FOR_KEY_0_OF_REGION_1, new Object[] {
+        key,
+        regionName
+      }));
+      writeException(msg, MessageType.PUT_DELTA_ERROR, ide, false, servConn);
+      servConn.setAsTrue(RESPONDED);
+      region.getCachePerfStats().incDeltaFullValuesRequested();
+      return;
+    } catch (Exception ce) {
+      // If an interrupted exception is thrown , rethrow it
+      checkForInterrupt(servConn, ce);
+
+      // If an exception occurs during the put, preserve the connection
+      writeException(msg, ce, false, servConn);
+      servConn.setAsTrue(RESPONDED);
+      if (ce instanceof GemFireSecurityException) {
+        // Fine logging for security exceptions since these are already
+        // logged by the security logger
         if (isDebugEnabled) {
-          logger.debug("{}: Sent put response back to {} for region {} key {} value {}", servConn.getName(), servConn.getSocketString(), regionName, key, valuePart);
+          logger.debug("{}: Unexpected Security exception", servConn.getName(), ce);
         }
-        stats.incWritePutResponseTime(DistributionStats.getStatTime() - start);
+      } else if (isDebugEnabled) {
+        logger.debug("{}: Unexpected Exception", servConn.getName(), ce);
       }
+      return;
+    } finally {
+      long oldStart = start;
+      start = DistributionStats.getStatTime();
+      stats.incProcessPutTime(start - oldStart);
     }
 
+    // Increment statistics and write the reply
+    if (region instanceof PartitionedRegion) {
+      PartitionedRegion pr = (PartitionedRegion) region;
+      if (pr.isNetworkHop().byteValue() != (byte) 0) {
+        writeReplyWithRefreshMetadata(msg, servConn, pr, sendOldValue, oldValueIsObject, oldValue, pr.isNetworkHop()
+                                                                                                     .byteValue(), clientEvent
+          .getVersionTag());
+        pr.setIsNetworkHop((byte) 0);
+        pr.setMetadataVersion(Byte.valueOf((byte) 0));
+      } else {
+        writeReply(msg, servConn, sendOldValue, oldValueIsObject, oldValue, clientEvent.getVersionTag());
+      }
+    } else {
+      writeReply(msg, servConn, sendOldValue, oldValueIsObject, oldValue, clientEvent.getVersionTag());
+    }
+    servConn.setAsTrue(RESPONDED);
+    if (isDebugEnabled) {
+      logger.debug("{}: Sent put response back to {} for region {} key {} value {}", servConn.getName(), servConn.getSocketString(), regionName, key, valuePart);
+    }
+    stats.incWritePutResponseTime(DistributionStats.getStatTime() - start);
+
+
   }
-  protected void writeReply(Message origMsg, ServerConnection servConn,
-      boolean sendOldValue, boolean oldValueIsObject, Object oldValue,
-      VersionTag tag)
-  throws IOException {
+
+  protected void writeReply(Message origMsg,
+                            ServerConnection servConn,
+                            boolean sendOldValue,
+                            boolean oldValueIsObject,
+                            Object oldValue,
+                            VersionTag tag) throws IOException {
     Message replyMsg = servConn.getReplyMessage();
     servConn.getCache().getCancelCriterion().checkCancelInProgress(null);
     replyMsg.setMessageType(MessageType.REPLY);
-    replyMsg.setNumberOfParts(sendOldValue? 3 : 1);
+    replyMsg.setNumberOfParts(sendOldValue ? 3 : 1);
     replyMsg.setTransactionId(origMsg.getTransactionId());
     replyMsg.addBytesPart(OK_BYTES);
     if (sendOldValue) {
-      replyMsg.addIntPart(oldValueIsObject?1:0);
+      replyMsg.addIntPart(oldValueIsObject ? 1 : 0);
       replyMsg.addObjPart(oldValue);
     }
     replyMsg.send(servConn);
@@ -514,25 +489,30 @@ public class Put65 extends BaseCommand {
       logger.trace("{}: rpl tx: {} parts={}", servConn.getName(), origMsg.getTransactionId(), replyMsg.getNumberOfParts());
     }
   }
+
   protected void writeReplyWithRefreshMetadata(Message origMsg,
-      ServerConnection servConn, PartitionedRegion pr,
-      boolean sendOldValue, boolean oldValueIsObject, Object oldValue, byte nwHopType,
-      VersionTag tag)
-  throws IOException {
+                                               ServerConnection servConn,
+                                               PartitionedRegion pr,
+                                               boolean sendOldValue,
+                                               boolean oldValueIsObject,
+                                               Object oldValue,
+                                               byte nwHopType,
+                                               VersionTag tag) throws IOException {
     Message replyMsg = servConn.getReplyMessage();
     servConn.getCache().getCancelCriterion().checkCancelInProgress(null);
     replyMsg.setMessageType(MessageType.REPLY);
-    replyMsg.setNumberOfParts(sendOldValue? 3 : 1);
+    replyMsg.setNumberOfParts(sendOldValue ? 3 : 1);
     replyMsg.setTransactionId(origMsg.getTransactionId());
-    replyMsg.addBytesPart(new byte[]{pr.getMetadataVersion().byteValue(), nwHopType});
+    replyMsg.addBytesPart(new byte[] { pr.getMetadataVersion().byteValue(), nwHopType });
     if (sendOldValue) {
-      replyMsg.addIntPart(oldValueIsObject?1:0);
+      replyMsg.addIntPart(oldValueIsObject ? 1 : 0);
       replyMsg.addObjPart(oldValue);
     }
     replyMsg.send(servConn);
     pr.getPrStats().incPRMetaDataSentCount();
     if (logger.isTraceEnabled()) {
-      logger.trace("{}: rpl with REFRESH_METADAT tx: {} parts={}", servConn.getName(), origMsg.getTransactionId(), replyMsg.getNumberOfParts());
+      logger.trace("{}: rpl with REFRESH_METADAT tx: {} parts={}", servConn.getName(), origMsg.getTransactionId(), replyMsg
+        .getNumberOfParts());
     }
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c6e7a3bd/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/command/PutAll80.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/command/PutAll80.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/command/PutAll80.java
index 4552c95..0c2a86c 100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/command/PutAll80.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/command/PutAll80.java
@@ -52,6 +52,7 @@ import com.gemstone.gemfire.internal.cache.versions.VersionTag;
 import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
 import com.gemstone.gemfire.internal.logging.log4j.LocalizedMessage;
 import com.gemstone.gemfire.internal.security.AuthorizeRequest;
+import com.gemstone.gemfire.internal.security.GeodeSecurityUtil;
 import com.gemstone.gemfire.internal.util.Breadcrumbs;
 
 public class PutAll80 extends BaseCommand {
@@ -140,7 +141,9 @@ public class PutAll80 extends BaseCommand {
         servConn.setAsTrue(RESPONDED);
         return;
       }
-      
+
+      GeodeSecurityUtil.authorizeRegionWrite(regionName);
+
       final int BASE_PART_COUNT = getBasePartCount();
       
       // part 1: eventID

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c6e7a3bd/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/command/Query.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/command/Query.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/command/Query.java
index 68f6a51..1b5265e 100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/command/Query.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/command/Query.java
@@ -23,14 +23,12 @@ import java.io.IOException;
 import java.util.Set;
 
 import com.gemstone.gemfire.cache.operations.QueryOperationContext;
-import com.gemstone.gemfire.cache.query.QueryException;
 import com.gemstone.gemfire.cache.query.QueryExecutionLowMemoryException;
 import com.gemstone.gemfire.cache.query.QueryInvalidException;
 import com.gemstone.gemfire.cache.query.QueryService;
 import com.gemstone.gemfire.cache.query.internal.DefaultQuery;
 import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
 import com.gemstone.gemfire.internal.cache.tier.Command;
-import com.gemstone.gemfire.internal.cache.tier.sockets.BaseCommand;
 import com.gemstone.gemfire.internal.cache.tier.sockets.BaseCommandQuery;
 import com.gemstone.gemfire.internal.cache.tier.sockets.Message;
 import com.gemstone.gemfire.internal.cache.tier.sockets.ServerConnection;
@@ -71,31 +69,31 @@ public class Query extends BaseCommandQuery {
       logger.debug("{}: Received query request from {} queryString: {}", servConn.getName(), servConn.getSocketString(), queryString);
     }
     try {
-    // Create query
+      // Create query
       QueryService queryService = ((GemFireCacheImpl)servConn.getCachedRegionHelper().getCache())
-        .getLocalQueryService();
-    com.gemstone.gemfire.cache.query.Query query = queryService
-        .newQuery(queryString);
-    Set regionNames = ((DefaultQuery)query).getRegionsInQuery(null);
+          .getLocalQueryService();
+      com.gemstone.gemfire.cache.query.Query query = queryService
+          .newQuery(queryString);
+      Set regionNames = ((DefaultQuery)query).getRegionsInQuery(null);
 
-    // Authorization check
-    QueryOperationContext queryContext = null;
-    AuthorizeRequest authzRequest = servConn.getAuthzRequest();
-    if (authzRequest != null) {
-      queryContext = authzRequest.queryAuthorize(queryString, regionNames);
-      String newQueryString = queryContext.getQuery();
-      if (queryString != null && !queryString.equals(newQueryString)) {
-        query = queryService.newQuery(newQueryString);
-        queryString = newQueryString;
-        regionNames = queryContext.getRegionNames();
-        if (regionNames == null) {
-          regionNames = ((DefaultQuery)query).getRegionsInQuery(null);
+      // Authorization check
+      QueryOperationContext queryContext = null;
+      AuthorizeRequest authzRequest = servConn.getAuthzRequest();
+      if (authzRequest != null) {
+        queryContext = authzRequest.queryAuthorize(queryString, regionNames);
+        String newQueryString = queryContext.getQuery();
+        if (queryString != null && !queryString.equals(newQueryString)) {
+          query = queryService.newQuery(newQueryString);
+          queryString = newQueryString;
+          regionNames = queryContext.getRegionNames();
+          if (regionNames == null) {
+            regionNames = ((DefaultQuery)query).getRegionsInQuery(null);
+          }
         }
       }
-    }
 
-    processQuery(msg, query, queryString, regionNames, start, null,
-        queryContext, servConn, true);
+      processQuery(msg, query, queryString, regionNames, start, null,
+          queryContext, servConn, true);
     } catch (QueryInvalidException e) {
       throw new QueryInvalidException(e.getMessage()
           + queryString );

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c6e7a3bd/geode-core/src/main/java/com/gemstone/gemfire/internal/security/GeodeSecurityUtil.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/security/GeodeSecurityUtil.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/security/GeodeSecurityUtil.java
index fa499d9..17bfec0 100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/internal/security/GeodeSecurityUtil.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/security/GeodeSecurityUtil.java
@@ -21,6 +21,7 @@ import static com.gemstone.gemfire.distributed.ConfigurationProperties.*;
 
 import java.lang.reflect.Method;
 import java.security.AccessController;
+import java.security.Principal;
 import java.util.Properties;
 import java.util.Set;
 import java.util.concurrent.Callable;
@@ -54,6 +55,7 @@ import com.gemstone.gemfire.security.GeodePermission;
 import com.gemstone.gemfire.security.GeodePermission.Operation;
 import com.gemstone.gemfire.security.GeodePermission.Resource;
 import com.gemstone.gemfire.security.NotAuthorizedException;
+import com.gemstone.gemfire.security.PostProcessor;
 
 public class GeodeSecurityUtil {
 
@@ -212,21 +214,37 @@ public class GeodeSecurityUtil {
     authorize("DATA", "MANAGE", regionName);
   }
 
+  public static void authorizeRegionManage(String regionName, String key) {
+    authorize("DATA", "MANAGE", regionName, key);
+  }
+
   public static void authorizeRegionWrite(String regionName) {
     authorize("DATA", "WRITE", regionName);
   }
 
+  public static void authorizeRegionWrite(String regionName, String key) {
+    authorize("DATA", "WRITE", regionName, key);
+  }
+
   public static void authorizeRegionRead(String regionName) {
     authorize("DATA", "READ", regionName);
   }
 
+  public static void authorizeRegionRead(String regionName, String key) {
+    authorize("DATA", "READ", regionName, key);
+  }
+
   public static void authorize(String resource, String operation) {
     authorize(resource, operation, null);
   }
 
-  private static void authorize(String resource, String operation, String regionName) {
+  private static void authorize(String resource, String operation, String regionName){
+    authorize(resource, operation, regionName, null);
+  }
+
+  private static void authorize(String resource, String operation, String regionName, String key) {
     regionName = StringUtils.stripStart(regionName, "/");
-    authorize(new GeodePermission(resource, operation, regionName));
+    authorize(new GeodePermission(resource, operation, regionName, key));
   }
 
   public static void authorize(GeodePermission context) {
@@ -247,8 +265,8 @@ public class GeodeSecurityUtil {
       currentUser.checkPermission(context);
     }
     catch (ShiroException e) {
-      logger.info(currentUser.getPrincipal() + " not authorized for " + context);
-      throw new NotAuthorizedException(e.getMessage(), e);
+      String msg = currentUser.getPrincipal() + " not authorized for " + context;
+      throw new NotAuthorizedException(msg, e);
     }
   }
 
@@ -262,6 +280,8 @@ public class GeodeSecurityUtil {
     return true;
   }
 
+  private static PostProcessor postProcessor;
+
   /**
    * initialize Shiro's Security Manager and Security Utilities
    * @param securityProps
@@ -274,8 +294,7 @@ public class GeodeSecurityUtil {
     String shiroConfig = securityProps.getProperty(SECURITY_SHIRO_INIT);
     String customAuthenticator = securityProps.getProperty(SECURITY_CLIENT_AUTHENTICATOR);
 
-    Object auth = getAuthenticatorObject(customAuthenticator);
-
+    Object authenticatorObject = getObject(customAuthenticator);
     if (!com.gemstone.gemfire.internal.lang.StringUtils.isBlank(shiroConfig)) {
       IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:" + shiroConfig);
 
@@ -289,26 +308,46 @@ public class GeodeSecurityUtil {
       SecurityManager securityManager = factory.getInstance();
       SecurityUtils.setSecurityManager(securityManager);
     }
+
     // only set up shiro realm if user has implemented ExternalSecurity
-    else if (auth != null && auth instanceof ExternalSecurity) {
-      ExternalSecurity externalSecurity = (ExternalSecurity) auth;
-      externalSecurity.init(securityProps);
-      Realm realm = new CustomAuthRealm(externalSecurity);
+    else if (authenticatorObject != null && authenticatorObject instanceof ExternalSecurity) {
+      ExternalSecurity authenticator = (ExternalSecurity) authenticatorObject;
+      authenticator.init(securityProps);
+      Realm realm = new CustomAuthRealm(authenticator);
       SecurityManager securityManager = new DefaultSecurityManager(realm);
       SecurityUtils.setSecurityManager(securityManager);
     }
     else {
       SecurityUtils.setSecurityManager(null);
     }
+
+    // this initializes the post processor
+    String customPostProcessor = securityProps.getProperty(SECURITY_CLIENT_ACCESSOR_PP);
+    Object postProcessObject = getObject(customPostProcessor);
+    if(postProcessObject instanceof PostProcessor){
+      postProcessor = (PostProcessor) postProcessObject;
+      postProcessor.init(securityProps);
+    }
   }
 
-  public static Object getAuthenticatorObject(String authenticatorFactoryName) {
-    if (StringUtils.isBlank(authenticatorFactoryName)) {
+  public static Object postProcess(String regionPath, Object key, Object result){
+    if(postProcessor == null)
+      return result;
+
+    Subject subject = getSubject();
+
+    if(subject == null)
+      return result;
+
+    return postProcessor.processRegionValue((Principal)subject.getPrincipal(), regionPath, key,  result);
+  }
+
+  public static Object getObject(String factoryName) {
+    if (StringUtils.isBlank(factoryName)) {
       return null;
     }
-
     try {
-      Method instanceGetter = ClassLoadUtil.methodFromName(authenticatorFactoryName);
+      Method instanceGetter = ClassLoadUtil.methodFromName(factoryName);
       return instanceGetter.invoke(null, (Object[]) null);
     }
     catch (Exception ex) {
@@ -317,7 +356,7 @@ public class GeodeSecurityUtil {
   }
 
   public static boolean isIntegratedSecurity(String authenticatorFactoryName) {
-    Object auth = getAuthenticatorObject(authenticatorFactoryName);
+    Object auth = getObject(authenticatorFactoryName);
     return (auth instanceof ExternalSecurity);
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c6e7a3bd/geode-core/src/main/java/com/gemstone/gemfire/internal/security/shiro/CustomAuthRealm.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/security/shiro/CustomAuthRealm.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/security/shiro/CustomAuthRealm.java
index 060878d..cb3b116 100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/internal/security/shiro/CustomAuthRealm.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/security/shiro/CustomAuthRealm.java
@@ -19,12 +19,6 @@ package com.gemstone.gemfire.internal.security.shiro;
 import java.security.Principal;
 import java.util.Properties;
 
-import com.gemstone.gemfire.internal.security.GeodeSecurityUtil;
-import com.gemstone.gemfire.management.internal.security.ResourceConstants;
-import com.gemstone.gemfire.security.ExternalSecurity;
-import com.gemstone.gemfire.security.GemFireSecurityException;
-import com.gemstone.gemfire.security.GeodePermission;
-
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.apache.shiro.authc.AuthenticationException;
@@ -37,6 +31,12 @@ import org.apache.shiro.authz.Permission;
 import org.apache.shiro.realm.AuthorizingRealm;
 import org.apache.shiro.subject.PrincipalCollection;
 
+import com.gemstone.gemfire.internal.security.GeodeSecurityUtil;
+import com.gemstone.gemfire.management.internal.security.ResourceConstants;
+import com.gemstone.gemfire.security.ExternalSecurity;
+import com.gemstone.gemfire.security.GemFireSecurityException;
+import com.gemstone.gemfire.security.GeodePermission;
+
 public class CustomAuthRealm extends AuthorizingRealm{
   public static final String REALM_NAME = "CUSTOMAUTHREALM";
 
@@ -49,7 +49,7 @@ public class CustomAuthRealm extends AuthorizingRealm{
 
 
   public CustomAuthRealm (String authenticatorFactory) {
-    Object auth = GeodeSecurityUtil.getAuthenticatorObject(authenticatorFactory);
+    Object auth = GeodeSecurityUtil.getObject(authenticatorFactory);
 
     if(!(auth instanceof ExternalSecurity)){
       throw new GemFireSecurityException("Integrated Security requires ExternalSecurity interface.");
@@ -57,7 +57,7 @@ public class CustomAuthRealm extends AuthorizingRealm{
     externalSecurity = (ExternalSecurity) auth;
   }
 
-    @Override
+  @Override
   protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
     UsernamePasswordToken authToken = (UsernamePasswordToken) token;
     String username = authToken.getUsername();

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c6e7a3bd/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/DataCommands.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/DataCommands.java b/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/DataCommands.java
index cd802a9..a727b5c 100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/DataCommands.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/DataCommands.java
@@ -30,6 +30,11 @@ import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
+import org.springframework.shell.core.CommandMarker;
+import org.springframework.shell.core.annotation.CliAvailabilityIndicator;
+import org.springframework.shell.core.annotation.CliCommand;
+import org.springframework.shell.core.annotation.CliOption;
+
 import com.gemstone.gemfire.LogWriter;
 import com.gemstone.gemfire.cache.Cache;
 import com.gemstone.gemfire.cache.CacheClosedException;
@@ -75,11 +80,6 @@ import com.gemstone.gemfire.management.internal.security.ResourceOperation;
 import com.gemstone.gemfire.security.GeodePermission.Operation;
 import com.gemstone.gemfire.security.GeodePermission.Resource;
 
-import org.springframework.shell.core.CommandMarker;
-import org.springframework.shell.core.annotation.CliAvailabilityIndicator;
-import org.springframework.shell.core.annotation.CliCommand;
-import org.springframework.shell.core.annotation.CliOption;
-
 /**
  * 
  * @since GemFire 7.0
@@ -1027,7 +1027,7 @@ public class DataCommands implements CommandMarker {
       @CliOption(key = { CliStrings.GET__VALUEKLASS }, help = CliStrings.GET__VALUEKLASS__HELP) String valueClass,
       @CliOption(key = CliStrings.GET__LOAD, unspecifiedDefaultValue = "true", specifiedDefaultValue = "true", help = CliStrings.GET__LOAD__HELP) Boolean loadOnCacheMiss)
   {
-    GeodeSecurityUtil.authorizeRegionRead(regionPath);
+    GeodeSecurityUtil.authorizeRegionRead(regionPath, key);
 
     Cache cache = CacheFactory.getAnyInstance();
     DataCommandResult dataResult = null;
@@ -1069,6 +1069,10 @@ public class DataCommands implements CommandMarker {
     dataResult.setKeyClass(keyClass);
     if (valueClass != null)
       dataResult.setValueClass(valueClass);
+
+    Object result = GeodeSecurityUtil.postProcess(regionPath, key, dataResult.getGetResult());
+    dataResult.setGetResult(result);
+
     return makePresentationResult(dataResult);
   }
 
@@ -1083,8 +1087,8 @@ public class DataCommands implements CommandMarker {
       @CliOption(key = { CliStrings.LOCATE_ENTRY__VALUEKLASS }, help = CliStrings.LOCATE_ENTRY__VALUEKLASS__HELP) String valueClass,
       @CliOption(key = { CliStrings.LOCATE_ENTRY__RECURSIVE }, help = CliStrings.LOCATE_ENTRY__RECURSIVE__HELP, unspecifiedDefaultValue = "false") boolean recursive) {
 
-    GeodeSecurityUtil.authorizeRegionRead(regionPath);
-    // Cache cache = CacheFactory.getAnyInstance();
+    GeodeSecurityUtil.authorizeRegionRead(regionPath, key);
+
     DataCommandResult dataResult = null;
 
     if (regionPath == null || regionPath.isEmpty()) {
@@ -1118,6 +1122,7 @@ public class DataCommands implements CommandMarker {
     dataResult.setKeyClass(keyClass);
     if (valueClass != null)
       dataResult.setValueClass(valueClass);
+
     return makePresentationResult(dataResult);
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c6e7a3bd/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/functions/DataCommandFunction.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/functions/DataCommandFunction.java b/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/functions/DataCommandFunction.java
index 48cc83a..3f1eb21 100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/functions/DataCommandFunction.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/functions/DataCommandFunction.java
@@ -26,6 +26,10 @@ import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import org.apache.commons.lang.StringUtils;
+import org.apache.logging.log4j.Logger;
+import org.json.JSONArray;
+
 import com.gemstone.gemfire.cache.Cache;
 import com.gemstone.gemfire.cache.CacheClosedException;
 import com.gemstone.gemfire.cache.CacheFactory;
@@ -77,10 +81,6 @@ import com.gemstone.gemfire.management.internal.cli.shell.Gfsh;
 import com.gemstone.gemfire.management.internal.cli.util.JsonUtil;
 import com.gemstone.gemfire.pdx.PdxInstance;
 
-import org.apache.commons.lang.StringUtils;
-import org.apache.logging.log4j.Logger;
-import org.json.JSONArray;
-
 /***
  * 
  * since 7.0
@@ -930,6 +930,21 @@ public class DataCommandFunction extends FunctionAdapter implements  InternalEnt
             request.setQuery(query);
             dataResult = DataCommands.callFunctionForRegion(request, function, members);
             dataResult.setInputQuery(query);
+
+            // post process, iterate through the result for post processing
+            List<SelectResultRow> rows = dataResult.getSelectResult();
+            for(Iterator<SelectResultRow> itr = rows.iterator(); itr.hasNext();){
+              SelectResultRow row = itr.next();
+              Object newValue = GeodeSecurityUtil.postProcess(null, null, row.getValue());
+              // user is not supposed to see this row
+              if(newValue==null){
+                itr.remove();
+              }
+              else{
+                row.setValue(newValue);
+              }
+            }
+
             return (dataResult);
           } else {
             return (dataResult = DataCommandResult.createSelectInfoResult(null, null, -1, null,

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c6e7a3bd/geode-core/src/main/java/com/gemstone/gemfire/security/GeodePermission.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/security/GeodePermission.java b/geode-core/src/main/java/com/gemstone/gemfire/security/GeodePermission.java
index 95ef2c8..fab8b74 100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/security/GeodePermission.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/security/GeodePermission.java
@@ -22,6 +22,7 @@ import org.apache.shiro.authz.permission.WildcardPermission;
 public class GeodePermission extends WildcardPermission {
 
   public static String ALL_REGIONS = "*";
+  public static String ALL_KEYS = "*";
 
   public enum Resource {
     NULL,
@@ -48,45 +49,61 @@ public class GeodePermission extends WildcardPermission {
     return regionName;
   }
 
+  public String getKey() {
+    return key;
+  }
+
   // these default values are used when creating a lock around an operation
   private Resource resource = Resource.NULL;
   private Operation operation = Operation.NULL;
   private String regionName = ALL_REGIONS;
+  private String key = ALL_KEYS;
 
   public GeodePermission() {
     this(Resource.NULL, Operation.NULL);
   }
 
   public GeodePermission(String resource, String operation) {
-    this(Resource.valueOf(resource), Operation.valueOf(operation));
-  }
-
-  public GeodePermission(Resource resource, Operation operation){
     this(resource, operation, ALL_REGIONS);
   }
 
   public GeodePermission(String resource, String operation, String regionName) {
-    if(resource != null) this.resource = Resource.valueOf(resource);
-    if(operation != null) this.operation = Operation.valueOf(operation);
-    if(regionName != null) this.regionName = regionName;
+    this(resource, operation, regionName, ALL_KEYS);
+  }
 
-    setParts(this.resource+":"+this.operation+":"+this.regionName, true);
+  public GeodePermission(String resource, String operation, String regionName, String key) {
+    this((resource==null) ? Resource.NULL : Resource.valueOf(resource),
+      (operation == null) ? Operation.NULL : Operation.valueOf(operation),
+      regionName,
+      key);
+  }
+
+  public GeodePermission(Resource resource, Operation operation){
+    this(resource, operation, ALL_REGIONS);
   }
 
   public GeodePermission(Resource resource, Operation operation, String regionName){
+    this(resource, operation, regionName, ALL_KEYS);
+  }
+
+  public GeodePermission(Resource resource, Operation operation, String regionName, String key){
     if(resource != null) this.resource = resource;
     if(operation != null) this.operation = operation;
     if(regionName != null) this.regionName = regionName;
+    if(key != null) this.key = key;
 
-    setParts(this.resource+":"+this.operation+":"+this.regionName, true);
+    setParts(this.resource+":"+this.operation+":"+this.regionName+":"+this.key, true);
   }
 
   @Override
   public String toString() {
-    if (ALL_REGIONS.equals(getRegionName())) {
+    if (ALL_REGIONS.equals(regionName)) {
       return getResource() + ":" + getOperation();
-    } else {
-      return getResource() + ":" + getOperation() + ":" + getRegionName();
+    } else if(ALL_KEYS.equals(key)) {
+      return resource + ":" + operation + ":" + regionName;
+    }
+    else{
+      return resource + ":" + operation + ":" + regionName + ":" + key;
     }
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c6e7a3bd/geode-core/src/main/java/com/gemstone/gemfire/security/PostProcessor.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/security/PostProcessor.java b/geode-core/src/main/java/com/gemstone/gemfire/security/PostProcessor.java
new file mode 100644
index 0000000..7f959e9
--- /dev/null
+++ b/geode-core/src/main/java/com/gemstone/gemfire/security/PostProcessor.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.gemstone.gemfire.security;
+
+import java.security.Principal;
+import java.util.Properties;
+
+public interface PostProcessor {
+  void init(Properties securityProps);
+  Object processRegionValue(Principal principal, String regionPath, Object key,  Object value);
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c6e7a3bd/geode-core/src/main/java/com/gemstone/gemfire/security/templates/SampleJsonAuthorization.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/security/templates/SampleJsonAuthorization.java b/geode-core/src/main/java/com/gemstone/gemfire/security/templates/SampleJsonAuthorization.java
index 3922d99..a86c871 100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/security/templates/SampleJsonAuthorization.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/security/templates/SampleJsonAuthorization.java
@@ -31,11 +31,14 @@ import java.util.Properties;
 import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.StreamSupport;
+
 import javax.management.remote.JMXPrincipal;
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.gemstone.gemfire.internal.logging.LogService;
+import org.apache.commons.io.IOUtils;
+import org.apache.shiro.authz.Permission;
+
 import com.gemstone.gemfire.management.internal.security.ResourceConstants;
 import com.gemstone.gemfire.security.AccessControl;
 import com.gemstone.gemfire.security.AuthenticationFailedException;
@@ -44,9 +47,6 @@ import com.gemstone.gemfire.security.ExternalSecurity;
 import com.gemstone.gemfire.security.GeodePermission;
 import com.gemstone.gemfire.security.NotAuthorizedException;
 
-import org.apache.commons.io.IOUtils;
-import org.apache.shiro.authz.Permission;
-
 /**
  * This class provides a sample implementation for authentication and authorization via the {@link AccessControl}
  * and {@link Authenticator} interfaces.
@@ -163,6 +163,7 @@ public class SampleJsonAuthorization implements ExternalSecurity {
       Role role = new Role();
       role.name = r.get("name").asText();
       String regionNames = null;
+      String keys = null;
 
       JsonNode regions = r.get("regions");
       if (regions != null) {
@@ -179,8 +180,16 @@ public class SampleJsonAuthorization implements ExternalSecurity {
         String[] parts = op.asText().split(":");
         String resourcePart = (parts.length > 0) ? parts[0] : null;
         String operationPart = (parts.length > 1) ? parts[1] : null;
+        if(parts.length>2){
+          regionNames = parts[2];
+        }
+        if(parts.length>3){
+          keys = parts[3];
+        }
         String regionPart = (regionNames != null) ? regionNames : "*";
-        role.permissions.add(new GeodePermission(resourcePart, operationPart, regionPart));
+        String keyPart = (keys !=null) ? keys : "*";
+
+        role.permissions.add(new GeodePermission(resourcePart, operationPart, regionPart, keyPart));
       }
 
       roleMap.put(role.name, role);
@@ -232,7 +241,6 @@ public class SampleJsonAuthorization implements ExternalSecurity {
       throw new AuthenticationFailedException("Wrong username/password");
     }
 
-    LogService.getLogger().info("User=" + user + " pwd=" + pwd);
     if (user != null && !userObj.pwd.equals(pwd) && !"".equals(user)) {
       throw new AuthenticationFailedException("Wrong username/password");
     }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c6e7a3bd/geode-core/src/main/java/com/gemstone/gemfire/security/templates/SamplePostProcessor.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/security/templates/SamplePostProcessor.java b/geode-core/src/main/java/com/gemstone/gemfire/security/templates/SamplePostProcessor.java
new file mode 100644
index 0000000..1adfb9f
--- /dev/null
+++ b/geode-core/src/main/java/com/gemstone/gemfire/security/templates/SamplePostProcessor.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.gemstone.gemfire.security.templates;
+
+import java.security.Principal;
+import java.util.Properties;
+
+import com.gemstone.gemfire.security.PostProcessor;
+
+public class SamplePostProcessor implements PostProcessor{
+  public static String MASK = "****";
+
+  public static SamplePostProcessor create(){
+    return new SamplePostProcessor();
+  }
+
+  @Override
+  public void init(final Properties securityProps) {
+
+  }
+
+  @Override
+  public Object processRegionValue(Principal principal,
+                                   String regionPath,
+                                   Object key,
+                                   Object value) {
+    return MASK;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c6e7a3bd/geode-core/src/test/java/com/gemstone/gemfire/management/internal/cli/GfshParserJUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/com/gemstone/gemfire/management/internal/cli/GfshParserJUnitTest.java b/geode-core/src/test/java/com/gemstone/gemfire/management/internal/cli/GfshParserJUnitTest.java
index 95e4943..852c230 100644
--- a/geode-core/src/test/java/com/gemstone/gemfire/management/internal/cli/GfshParserJUnitTest.java
+++ b/geode-core/src/test/java/com/gemstone/gemfire/management/internal/cli/GfshParserJUnitTest.java
@@ -16,7 +16,6 @@
  */
 package com.gemstone.gemfire.management.internal.cli;
 
-import static com.gemstone.gemfire.cache.operations.OperationContext.*;
 import static org.junit.Assert.*;
 
 import java.lang.reflect.Method;
@@ -49,6 +48,8 @@ import com.gemstone.gemfire.management.internal.cli.i18n.CliStrings;
 import com.gemstone.gemfire.management.internal.cli.parser.SyntaxConstants;
 import com.gemstone.gemfire.management.internal.cli.result.ResultBuilder;
 import com.gemstone.gemfire.management.internal.security.ResourceOperation;
+import com.gemstone.gemfire.security.GeodePermission.Operation;
+import com.gemstone.gemfire.security.GeodePermission.Resource;
 import com.gemstone.gemfire.test.junit.categories.UnitTest;
 
 /**
@@ -688,7 +689,7 @@ public class GfshParserJUnitTest {
   static class Commands implements CommandMarker {
 
     @CliCommand(value = { COMMAND1_NAME, COMMAND1_NAME_ALIAS }, help = COMMAND1_HELP)
-    @ResourceOperation(resource = Resource.CLUSTER, operation = OperationCode.READ)
+    @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.READ)
     public static String command1(@CliArgument(name = ARGUMENT1_NAME, argumentContext = ARGUMENT1_CONTEXT, help = ARGUMENT1_HELP, mandatory = true) String argument1,
                                   @CliArgument(name = ARGUMENT2_NAME, argumentContext = ARGUMENT2_CONTEXT, help = ARGUMENT2_HELP, mandatory = false, unspecifiedDefaultValue = ARGUMENT2_UNSPECIFIED_DEFAULT_VALUE, systemProvided = false) String argument2,
                                   @CliOption(key = {
@@ -704,13 +705,13 @@ public class GfshParserJUnitTest {
     }
 
     @CliCommand(value = { COMMAND2_NAME })
-    @ResourceOperation(resource = Resource.CLUSTER, operation = OperationCode.READ)
+    @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.READ)
     public static String command2() {
       return null;
     }
 
     @CliCommand(value = { "testParamConcat" })
-    @ResourceOperation(resource = Resource.CLUSTER, operation = OperationCode.READ)
+    @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.READ)
     public static Result testParamConcat(@CliOption(key = { "string" }) String string,
                                          @CliOption(key = { "stringArray" }) @CliMetaData(valueSeparator = ",") String[] stringArray,
                                          @CliOption(key = { "stringList" }, optionContext = ConverterHint.STRING_LIST) @CliMetaData(valueSeparator = ",") List<String> stringList,
@@ -720,7 +721,7 @@ public class GfshParserJUnitTest {
     }
 
     @CliCommand(value = { "testMultiWordArg" })
-    @ResourceOperation(resource = Resource.CLUSTER, operation = OperationCode.READ)
+    @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.READ)
     public static Result testMultiWordArg(@CliArgument(name = "arg1") String arg1,
                                           @CliArgument(name = "arg2") String arg2) {
       return null;
@@ -778,13 +779,13 @@ public class GfshParserJUnitTest {
     static final String C2_MSG_AVAILABLE = C2_NAME + " is available.";
 
     @CliCommand(value = { C1_NAME })
-    @ResourceOperation(resource = Resource.CLUSTER, operation = OperationCode.READ)
+    @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.READ)
     public Result command1() {
       return ResultBuilder.createInfoResult(C1_MSG_AVAILABLE);
     }
 
     @CliCommand(value = { C2_NAME })
-    @ResourceOperation(resource = Resource.CLUSTER, operation = OperationCode.READ)
+    @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.READ)
     public Result command2() {
       return ResultBuilder.createInfoResult(C2_MSG_AVAILABLE);
     }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c6e7a3bd/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/CliCommandsSecurityTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/CliCommandsSecurityTest.java b/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/CliCommandsSecurityTest.java
index 5edca36..55284b4 100644
--- a/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/CliCommandsSecurityTest.java
+++ b/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/CliCommandsSecurityTest.java
@@ -21,18 +21,18 @@ import static org.junit.Assert.*;
 
 import java.util.List;
 
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
 import com.gemstone.gemfire.internal.AvailablePort;
 import com.gemstone.gemfire.internal.logging.LogService;
 import com.gemstone.gemfire.management.MemberMXBean;
 import com.gemstone.gemfire.security.NotAuthorizedException;
 import com.gemstone.gemfire.test.junit.categories.IntegrationTest;
-
 import com.gemstone.gemfire.test.junit.categories.SecurityTest;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
 
 /**
  */
@@ -88,5 +88,4 @@ public class CliCommandsSecurityTest {
     }
   }
 
-
 }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c6e7a3bd/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/GfshCommandsPostProcessorTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/GfshCommandsPostProcessorTest.java b/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/GfshCommandsPostProcessorTest.java
new file mode 100644
index 0000000..2cfd496
--- /dev/null
+++ b/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/GfshCommandsPostProcessorTest.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.gemstone.gemfire.management.internal.security;
+
+import static com.gemstone.gemfire.internal.Assert.assertTrue;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import com.gemstone.gemfire.internal.AvailablePortHelper;
+import com.gemstone.gemfire.management.internal.cli.HeadlessGfsh;
+import com.gemstone.gemfire.security.templates.SamplePostProcessor;
+import com.gemstone.gemfire.test.junit.categories.IntegrationTest;
+
+@Category(IntegrationTest.class)
+public class GfshCommandsPostProcessorTest {
+  protected static int jmxPort = AvailablePortHelper.getRandomAvailableTCPPort();
+
+  private HeadlessGfsh gfsh = null;
+
+  @ClassRule
+  public static JsonAuthorizationCacheStartRule serverRule = new JsonAuthorizationCacheStartRule(
+      jmxPort, "cacheServer.json", SamplePostProcessor.class);
+
+  @Rule
+  public GfshShellConnectionRule gfshConnection;
+
+  public GfshCommandsPostProcessorTest(){
+    gfshConnection = new GfshShellConnectionRule(jmxPort);
+  }
+
+  @Before
+  public void before(){
+    gfsh = gfshConnection.getGfsh();
+  }
+
+  @Test
+  @JMXConnectionConfiguration(user = "data-user", password = "1234567")
+  public void testGetPostProcess() throws Exception {
+    gfsh.executeCommand("put --region=region1 --key=key1 --value=value1");
+    gfsh.executeCommand("put --region=region1 --key=key2 --value=value2");
+    gfsh.executeCommand("put --region=region1 --key=key3 --value=value3");
+
+    // for get command, assert the return value is processed
+    gfsh.executeCommand("get --region=region1 --key=key1");
+    assertTrue(gfsh.outputString.contains("Value       : ****"), gfsh.outputString);
+
+    // for query command, assert the return values are processed
+    gfsh.executeCommand("query --query=\"select * from /region1\"");
+    assertTrue(gfsh.outputString.contains("****\n****\n****"), gfsh.outputString);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c6e7a3bd/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/GfshCommandsSecurityTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/GfshCommandsSecurityTest.java b/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/GfshCommandsSecurityTest.java
index 9e24317..dda844e 100644
--- a/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/GfshCommandsSecurityTest.java
+++ b/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/GfshCommandsSecurityTest.java
@@ -21,6 +21,13 @@ import static org.junit.Assert.*;
 
 import java.util.List;
 
+import org.apache.shiro.authz.permission.WildcardPermission;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
 import com.gemstone.gemfire.internal.AvailablePortHelper;
 import com.gemstone.gemfire.internal.logging.LogService;
 import com.gemstone.gemfire.management.cli.Result;
@@ -30,13 +37,6 @@ import com.gemstone.gemfire.management.internal.cli.result.ErrorResultData;
 import com.gemstone.gemfire.management.internal.cli.result.ResultBuilder;
 import com.gemstone.gemfire.test.junit.categories.IntegrationTest;
 
-import org.apache.shiro.authz.permission.WildcardPermission;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
 @Category(IntegrationTest.class)
 public class GfshCommandsSecurityTest {
   protected static int[] ports = AvailablePortHelper.getRandomAvailableTCPPorts(2);
@@ -172,5 +172,17 @@ public class GfshCommandsSecurityTest {
     }
   }
 
+  @Test
+  @JMXConnectionConfiguration(user = "data-user", password = "1234567")
+  public void testGetPostProcess() throws Exception {
+    gfsh.executeCommand("put --region=region1 --key=key2 --value=value2");
+    gfsh.executeCommand("put --region=region1 --key=key2 --value=value2");
+    gfsh.executeCommand("put --region=region1 --key=key3 --value=value3");
+
+    //gfsh.executeCommand("get --region=region1 --key=key1");
+    gfsh.executeCommand("query --query=\"select * from /region1\"");
+  }
+
+
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c6e7a3bd/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/GfshShellConnectionRule.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/GfshShellConnectionRule.java b/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/GfshShellConnectionRule.java
index d0f33d9..5183e7a 100644
--- a/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/GfshShellConnectionRule.java
+++ b/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/GfshShellConnectionRule.java
@@ -48,6 +48,10 @@ public class GfshShellConnectionRule extends DescribedExternalResource {
     this.useHttp = useHttp;
   }
 
+  public GfshShellConnectionRule(int jmxPort) {
+    this.jmxPort = jmxPort;
+  }
+
   protected void before(Description description) throws Throwable {
     JMXConnectionConfiguration config = description.getAnnotation(JMXConnectionConfiguration.class);
     if(config==null)

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c6e7a3bd/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/JsonAuthorizationCacheStartRule.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/JsonAuthorizationCacheStartRule.java b/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/JsonAuthorizationCacheStartRule.java
index 223ff91..4714016 100644
--- a/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/JsonAuthorizationCacheStartRule.java
+++ b/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/JsonAuthorizationCacheStartRule.java
@@ -16,21 +16,31 @@
  */
 package com.gemstone.gemfire.management.internal.security;
 
-import com.gemstone.gemfire.cache.Cache;
-import com.gemstone.gemfire.cache.CacheFactory;
-import org.junit.rules.ExternalResource;
+import static com.gemstone.gemfire.distributed.ConfigurationProperties.*;
 
 import java.util.Properties;
 
-import static com.gemstone.gemfire.distributed.ConfigurationProperties.*;
+import org.junit.rules.ExternalResource;
+
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache.CacheFactory;
 
 public class JsonAuthorizationCacheStartRule extends ExternalResource {
   private Cache cache;
   private int jmxManagerPort = 0;
   private int httpPort = 0;
   private String jsonFile;
+  private Class postProcessor;
   private boolean doAuthorization;
 
+  public JsonAuthorizationCacheStartRule(int jmxManagerPort, String jsonFile, Class postProcessor) {
+    this.jmxManagerPort = jmxManagerPort;
+    this.jsonFile = jsonFile;
+    this.doAuthorization = true;
+    this.postProcessor = postProcessor;
+  }
+
+
   public JsonAuthorizationCacheStartRule(int jmxManagerPort, String jsonFile) {
     this.jmxManagerPort = jmxManagerPort;
     this.jsonFile = jsonFile;
@@ -64,10 +74,16 @@ public class JsonAuthorizationCacheStartRule extends ExternalResource {
     if (doAuthorization) {
       properties.put(SECURITY_CLIENT_ACCESSOR, JSONAuthorization.class.getName() + ".create");
     }
+    if(postProcessor!=null){
+      properties.put(SECURITY_CLIENT_ACCESSOR_PP, postProcessor.getName()+".create");
+    }
+
     JSONAuthorization.setUpWithJsonFile(jsonFile);
 
     cache = new CacheFactory(properties).create();
     cache.addCacheServer().start();
+
+    cache.createRegionFactory().create("region1");
   }
 
   public Cache getCache(){

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c6e7a3bd/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/MultiUserDUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/MultiUserDUnitTest.java b/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/MultiUserDUnitTest.java
index e6dd1d5..644e9f8 100644
--- a/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/MultiUserDUnitTest.java
+++ b/geode-core/src/test/java/com/gemstone/gemfire/management/internal/security/MultiUserDUnitTest.java
@@ -17,6 +17,19 @@
 
 package com.gemstone.gemfire.management.internal.security;
 
+import static com.gemstone.gemfire.distributed.ConfigurationProperties.*;
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.TimeUnit;
+
+import com.jayway.awaitility.Awaitility;
+import org.json.JSONException;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
 import com.gemstone.gemfire.internal.logging.LogService;
 import com.gemstone.gemfire.management.cli.Result.Status;
 import com.gemstone.gemfire.management.internal.cli.HeadlessGfsh;
@@ -30,18 +43,6 @@ import com.gemstone.gemfire.test.dunit.IgnoredException;
 import com.gemstone.gemfire.test.dunit.VM;
 import com.gemstone.gemfire.test.junit.categories.DistributedTest;
 import com.gemstone.gemfire.test.junit.categories.SecurityTest;
-import com.jayway.awaitility.Awaitility;
-import org.json.JSONException;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Properties;
-import java.util.concurrent.TimeUnit;
-
-import static org.junit.Assert.*;
-import static com.gemstone.gemfire.distributed.ConfigurationProperties.*;
 
 @Category({ DistributedTest.class, SecurityTest.class })
 public class MultiUserDUnitTest extends CliCommandTestBase {
@@ -97,7 +98,7 @@ public class MultiUserDUnitTest extends CliCommandTestBase {
           ((ErrorResultData) result.getResultData()).getErrorCode());
         String resultMessage = result.getContent().toString();
         String permString = command.getPermission().toString();
-        assertTrue(resultMessage + " does not contain " + permString, resultMessage.contains("[" + permString + "]"));
+        assertTrue(resultMessage + " does not contain " + permString, resultMessage.contains(permString));
       }
       LogService.getLogger().info("vm 2 done!");
     });
@@ -136,6 +137,9 @@ public class MultiUserDUnitTest extends CliCommandTestBase {
     vm2Invoke.join();
     vm3Invoke.join();
 
+    vm2Invoke.checkException();
+    vm3Invoke.checkException();
+
     IgnoredException.removeAllExpectedExceptions();
   }