Repository: incubator-ranger
Updated Branches:
  refs/heads/master a50fcf116 -> 164d46fd1


RANGER-873: Ranger policy model update to support data masking


Project: http://git-wip-us.apache.org/repos/asf/incubator-ranger/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ranger/commit/164d46fd
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/164d46fd
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/164d46fd

Branch: refs/heads/master
Commit: 164d46fd188789fdae8f3f1f28e08941a1dc530e
Parents: a50fcf1
Author: Madhan Neethiraj <[email protected]>
Authored: Wed Mar 30 18:30:11 2016 -0700
Committer: Madhan Neethiraj <[email protected]>
Committed: Thu Mar 31 15:18:07 2016 -0700

----------------------------------------------------------------------
 .../ranger/plugin/model/RangerPolicy.java       |   2 +
 .../ranger/plugin/model/RangerServiceDef.java   | 115 ++++++++++-------
 .../model/validation/RangerPolicyValidator.java |   2 +-
 .../validation/RangerServiceDefHelper.java      | 111 ++++++++++------
 .../validation/RangerServiceDefValidator.java   |  13 +-
 .../model/validation/RangerValidator.java       |   4 +-
 .../policyengine/RangerPolicyRepository.java    |  11 +-
 .../RangerDefaultPolicyEvaluator.java           |   8 +-
 .../RangerOptimizedPolicyEvaluator.java         |   3 +-
 .../RangerDefaultPolicyResourceMatcher.java     |  14 ++-
 .../RangerPolicyResourceMatcher.java            |   3 +
 .../RangerAbstractResourceMatcher.java          |  12 +-
 .../ranger/plugin/service/RangerBasePlugin.java |  12 ++
 .../ranger/plugin/util/ServiceDefUtil.java      | 125 +++++++++++++++++++
 .../service-defs/ranger-servicedef-hive.json    |  80 +++++++++++-
 .../TestRangerPolicyResourceSignature.java      |   6 +-
 .../validation/TestRangerServiceDefHelper.java  |   7 +-
 .../test_policyengine_hive_masking.json         |  26 ++--
 .../db/mysql/patches/020-datamask-policy.sql    |  28 ++---
 .../db/postgres/patches/020-datamask-policy.sql |  97 ++++++++++++++
 .../org/apache/ranger/biz/ServiceDBStore.java   |  91 +++++++++-----
 .../java/org/apache/ranger/common/JSONUtil.java |  25 +++-
 .../apache/ranger/entity/XXAccessTypeDef.java   |  22 ++--
 .../org/apache/ranger/entity/XXResourceDef.java |  22 ++--
 .../service/RangerServiceDefServiceBase.java    |  48 ++++++-
 25 files changed, 689 insertions(+), 198 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicy.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicy.java 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicy.java
index 522d130..f022707 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicy.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicy.java
@@ -43,6 +43,8 @@ public class RangerPolicy extends RangerBaseModelObject 
implements java.io.Seria
        public static final int POLICY_TYPE_ACCESS   = 0;
        public static final int POLICY_TYPE_DATAMASK = 1;
 
+       public static final int[] POLICY_TYPES = new int[] { 
POLICY_TYPE_ACCESS, POLICY_TYPE_DATAMASK };
+
        // For future use
        private static final long serialVersionUID = 1L;
 

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java
index 8b919d0..febd85b 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java
@@ -1248,6 +1248,28 @@ public class RangerServiceDef extends 
RangerBaseModelObject implements java.io.S
                        this(null, null, null, null, null, null, null, null, 
null, null, null, null, null, null, null, null, null, null, null);
                }
 
+               public RangerResourceDef(RangerResourceDef other) {
+                       setItemId(other.getItemId());
+                       setName(other.getName());
+                       setType(other.getType());
+                       setLevel(other.getLevel());
+                       setParent(other.getParent());
+                       setMandatory(other.getMandatory());
+                       setLookupSupported(other.getLookupSupported());
+                       setRecursiveSupported(other.getRecursiveSupported());
+                       setExcludesSupported(other.getExcludesSupported());
+                       setMatcher(other.getMatcher());
+                       setMatcherOptions(other.getMatcherOptions());
+                       setValidationRegEx(other.getValidationRegEx());
+                       setValidationMessage(other.getValidationMessage());
+                       setUiHint(other.getUiHint());
+                       setLabel(other.getLabel());
+                       setDescription(other.getDescription());
+                       setRbKeyLabel(other.getRbKeyLabel());
+                       setRbKeyDescription(other.getRbKeyDescription());
+                       
setRbKeyValidationMessage(other.getRbKeyValidationMessage());
+               }
+
                public RangerResourceDef(Long itemId, String name, String type, 
Integer level, String parent, Boolean mandatory, Boolean lookupSupported, 
Boolean recursiveSupported, Boolean excludesSupported, String matcher, 
Map<String, String> matcherOptions, String validationRegEx, String 
validationMessage, String uiHint, String label, String description, String 
rbKeyLabel, String rbKeyDescription, String rbKeyValidationMessage) {
                        setItemId(itemId);
                        setName(name);
@@ -1421,7 +1443,7 @@ public class RangerServiceDef extends 
RangerBaseModelObject implements java.io.S
                 * @param matcherOptions the matcherOptions to set
                 */
                public void setMatcherOptions(Map<String, String> 
matcherOptions) {
-                       this.matcherOptions = matcherOptions == null ? new 
HashMap<String, String>() : matcherOptions;
+                       this.matcherOptions = matcherOptions == null ? new 
HashMap<String, String>() : new HashMap<String, String>(matcherOptions);
                }
 
                /**
@@ -1759,6 +1781,7 @@ public class RangerServiceDef extends 
RangerBaseModelObject implements java.io.S
                }
 
                public RangerAccessTypeDef(RangerAccessTypeDef other) {
+                       this.setItemId(other.getItemId());
                        this.setName(other.getName());
                        this.setLabel(other.getLabel());
                        this.setRbKeyLabel(other.getRbKeyLabel());
@@ -2451,26 +2474,26 @@ public class RangerServiceDef extends 
RangerBaseModelObject implements java.io.S
                private static final long serialVersionUID = 1L;
 
                private List<RangerDataMaskTypeDef> maskTypes;
-               private List<String>                supportedAccessTypes;
-               private List<String>                supportedResources;
+               private List<RangerAccessTypeDef>   accessTypes;
+               private List<RangerResourceDef>     resources;
 
 
                public RangerDataMaskDef() {
                        setMaskTypes(null);
-                       setSupportedAccessTypes(null);
-                       setSupportedResources(null);
+                       setAccessTypes(null);
+                       setResources(null);
                }
 
-               public RangerDataMaskDef(List<RangerDataMaskTypeDef> maskTypes, 
List<String> supportedAccessTypes, List<String> supportedResources) {
+               public RangerDataMaskDef(List<RangerDataMaskTypeDef> maskTypes, 
List<RangerAccessTypeDef> accessTypes, List<RangerResourceDef> resources) {
                        setMaskTypes(maskTypes);
-                       setSupportedAccessTypes(supportedAccessTypes);
-                       setSupportedResources(supportedResources);
+                       setAccessTypes(accessTypes);
+                       setResources(resources);
                }
 
                public RangerDataMaskDef(RangerDataMaskDef other) {
                        setMaskTypes(other.getMaskTypes());
-                       
setSupportedAccessTypes(other.getSupportedAccessTypes());
-                       setSupportedResources(other.getSupportedResources());
+                       setAccessTypes(other.getAccessTypes());
+                       setResources(other.getResources());
                }
 
                public List<RangerDataMaskTypeDef> getMaskTypes() {
@@ -2495,46 +2518,46 @@ public class RangerServiceDef extends 
RangerBaseModelObject implements java.io.S
                        }
                }
 
-               public List<String> getSupportedAccessTypes() {
-                       return supportedAccessTypes;
+               public List<RangerAccessTypeDef> getAccessTypes() {
+                       return accessTypes;
                }
 
-               public void setSupportedAccessTypes(List<String> 
supportedAccessTypes) {
-                       if(this.supportedAccessTypes == null) {
-                               this.supportedAccessTypes = new 
ArrayList<String>();
+               public void setAccessTypes(List<RangerAccessTypeDef> 
accessTypes) {
+                       if(this.accessTypes == null) {
+                               this.accessTypes = new 
ArrayList<RangerAccessTypeDef>();
                        }
 
-                       if(this.supportedAccessTypes == supportedAccessTypes) {
+                       if(this.accessTypes == accessTypes) {
                                return;
                        }
 
-                       this.supportedAccessTypes.clear();
+                       this.accessTypes.clear();
 
-                       if(supportedAccessTypes != null) {
-                               for(String accessType : supportedAccessTypes) {
-                                       
this.supportedAccessTypes.add(accessType);
+                       if(accessTypes != null) {
+                               for(RangerAccessTypeDef accessType : 
accessTypes) {
+                                       this.accessTypes.add(accessType);
                                }
                        }
                }
 
-               public List<String> getSupportedResources() {
-                       return supportedResources;
+               public List<RangerResourceDef> getResources() {
+                       return resources;
                }
 
-               public void setSupportedResources(List<String> 
supportedResources) {
-                       if(this.supportedResources == null) {
-                               this.supportedResources = new 
ArrayList<String>();
+               public void setResources(List<RangerResourceDef> resources) {
+                       if(this.resources == null) {
+                               this.resources = new 
ArrayList<RangerResourceDef>();
                        }
 
-                       if(this.supportedResources == supportedResources) {
+                       if(this.resources == resources) {
                                return;
                        }
 
-                       this.supportedResources.clear();
+                       this.resources.clear();
 
-                       if(supportedResources != null) {
-                               for(String resource : supportedResources) {
-                                       this.supportedResources.add(resource);
+                       if(resources != null) {
+                               for(RangerResourceDef resource : resources) {
+                                       this.resources.add(resource);
                                }
                        }
                }
@@ -2561,21 +2584,21 @@ public class RangerServiceDef extends 
RangerBaseModelObject implements java.io.S
                        }
                        sb.append("} ");
 
-                       sb.append("supportedAccessTypes={");
-                       if(supportedAccessTypes != null) {
-                               for(String accessType : supportedAccessTypes) {
+                       sb.append("accessTypes={");
+                       if(accessTypes != null) {
+                               for(RangerAccessTypeDef accessType : 
accessTypes) {
                                        if(accessType != null) {
-                                               sb.append(accessType).append(" 
");
+                                               
accessType.toString(sb).append(" ");
                                        }
                                }
                        }
                        sb.append("} ");
 
-                       sb.append("supportedResources={");
-                       if(supportedResources != null) {
-                               for(String resource : supportedResources) {
+                       sb.append("resources={");
+                       if(resources != null) {
+                               for(RangerResourceDef resource : resources) {
                                        if(resource != null) {
-                                               sb.append(resource).append(" ");
+                                               resource.toString(sb).append(" 
");
                                        }
                                }
                        }
@@ -2591,8 +2614,8 @@ public class RangerServiceDef extends 
RangerBaseModelObject implements java.io.S
                        final int prime = 31;
                        int result = 1;
                        result = prime * result + ((maskTypes == null) ? 0 : 
maskTypes.hashCode());
-                       result = prime * result + ((supportedAccessTypes == 
null) ? 0 : supportedAccessTypes.hashCode());
-                       result = prime * result + ((supportedResources == null) 
? 0 : supportedResources.hashCode());
+                       result = prime * result + ((accessTypes == null) ? 0 : 
accessTypes.hashCode());
+                       result = prime * result + ((resources == null) ? 0 : 
resources.hashCode());
                        return result;
                }
 
@@ -2611,15 +2634,15 @@ public class RangerServiceDef extends 
RangerBaseModelObject implements java.io.S
                        } else if (other.maskTypes == null || 
!maskTypes.equals(other.maskTypes))
                                return false;
 
-                       if (supportedAccessTypes == null) {
-                               if (other.supportedAccessTypes != null)
+                       if (accessTypes == null) {
+                               if (other.accessTypes != null)
                                        return false;
-                       } else if 
(!supportedAccessTypes.equals(other.supportedAccessTypes))
+                       } else if (!accessTypes.equals(other.accessTypes))
                                return false;
-                       if (supportedResources == null) {
-                               if (other.supportedResources != null)
+                       if (resources == null) {
+                               if (other.resources != null)
                                        return false;
-                       } else if 
(!supportedResources.equals(other.supportedResources))
+                       } else if (!resources.equals(other.resources))
                                return false;
                        return true;
                }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java
index cab7006..0bdaf87 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java
@@ -368,7 +368,7 @@ public class RangerPolicyValidator extends RangerValidator {
                Set<String> policyResources = getPolicyResources(policy);
 
                RangerServiceDefHelper defHelper = new 
RangerServiceDefHelper(serviceDef);
-               Set<List<RangerResourceDef>> hierarchies = 
defHelper.getResourceHierarchies(); // this can be empty but not null!
+               Set<List<RangerResourceDef>> hierarchies = 
defHelper.getResourceHierarchies(policy.getPolicyType()); // this can be empty 
but not null!
                if (hierarchies.isEmpty()) {
                        LOG.warn("RangerPolicyValidator.isValidResourceNames: 
serviceDef does not have any resource hierarchies, possibly due to a 
old/migrated service def!  Skipping this check!");
                } else {

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefHelper.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefHelper.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefHelper.java
index 53df193..101d911 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefHelper.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefHelper.java
@@ -30,9 +30,11 @@ import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
+import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.model.RangerPolicy;
 import org.apache.ranger.plugin.model.RangerServiceDef;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
 
@@ -97,18 +99,10 @@ public class RangerServiceDefHelper {
         *  
         * @return
         */
-       public Set<List<RangerResourceDef>> getResourceHierarchies() {
-               return _delegate.getResourceHierarchies();
+       public Set<List<RangerResourceDef>> getResourceHierarchies(Integer 
policyType) {
+               return _delegate.getResourceHierarchies(policyType);
        }
-       
-       /**
-        * Converts service-def resources from list to a map for constant time 
lookup
-        * @return
-        */
-       public Map<String, RangerResourceDef> getResorceMap() {
-               return _delegate.getResourceMap();
-       }
-       
+
        public Set<String> getMandatoryResourceNames(List<RangerResourceDef> 
hierarchy) {
                Set<String> result = new HashSet<String>(hierarchy.size());
                for (RangerResourceDef resourceDef : hierarchy) {
@@ -144,7 +138,7 @@ public class RangerServiceDefHelper {
                }
                return result;
        }
-       
+
        public boolean isResourceGraphValid() {
                return _delegate.isResourceGraphValid();
        }
@@ -154,30 +148,36 @@ public class RangerServiceDefHelper {
         */
        static class Delegate {
 
-               final Set<List<RangerResourceDef>> _hierarchies;
+               final Map<Integer, Set<List<RangerResourceDef>>> _hierarchies = 
new HashMap<Integer, Set<List<RangerResourceDef>>>();
                final Date _serviceDefFreshnessDate;
                final String _serviceName;
-               final Map<String, RangerResourceDef> _resourceMap;
                final boolean _valid;
-               
-               public Delegate(RangerServiceDef serviceDef) {
+               final static Set<List<RangerResourceDef>> 
EMPTY_RESOURCE_HIERARCHY = Collections.unmodifiableSet(new 
HashSet<List<RangerResourceDef>>());
+
 
+               public Delegate(RangerServiceDef serviceDef) {
                        // NOTE: we assume serviceDef, its name and update time 
are can never by null.
                        _serviceName = serviceDef.getName();
                        _serviceDefFreshnessDate = serviceDef.getUpdateTime();
 
-                       // NOTE: we assume resource collection on a service def 
would never be null
-                       List<RangerResourceDef> resourceDefs = 
serviceDef.getResources();
-                       _resourceMap = 
Collections.unmodifiableMap(getResourcesAsMap(resourceDefs));
-                       
-                       DirectedGraph graph = createGraph(resourceDefs);
-                       _valid = isValid(graph); 
-                       if (_valid) {
-                               Set<List<String>> hierarchies = 
getHierarchies(graph);
-                               _hierarchies = 
Collections.unmodifiableSet(convertHierarchies(hierarchies, _resourceMap));
-                       } else {
-                               _hierarchies = Collections.unmodifiableSet(new 
HashSet<List<RangerResourceDef>>());
+                       boolean isValid = true;
+                       for(Integer policyType : RangerPolicy.POLICY_TYPES) {
+                               List<RangerResourceDef> resources = 
getResourceDefs(serviceDef, policyType);
+                               DirectedGraph graph = createGraph(resources);
+
+                               if(graph != null) {
+                                       if (isValid(graph)) {
+                                               Set<List<String>> hierarchies = 
getHierarchies(graph);
+                                               _hierarchies.put(policyType, 
Collections.unmodifiableSet(convertHierarchies(hierarchies, 
getResourcesAsMap(resources))));
+                                       } else {
+                                               isValid = false;
+                                               _hierarchies.put(policyType, 
EMPTY_RESOURCE_HIERARCHY);
+                                       }
+                               } else {
+                                       _hierarchies.put(policyType, 
EMPTY_RESOURCE_HIERARCHY);
+                               }
                        }
+                       _valid = isValid;
                        if (LOG.isDebugEnabled()) {
                                String message = String.format("Found [%d] 
resource hierarchies for service [%s] update-date[%s]: %s", 
_hierarchies.size(), _serviceName, 
                                                _serviceDefFreshnessDate == 
null ? null : _serviceDefFreshnessDate.toString(), _hierarchies); 
@@ -185,12 +185,18 @@ public class RangerServiceDefHelper {
                        }
                }
                
-               public Set<List<RangerResourceDef>> getResourceHierarchies() {
-                       return _hierarchies;
-               }
-               
-               public Map<String, RangerResourceDef> getResourceMap() {
-                       return _resourceMap;
+               public Set<List<RangerResourceDef>> 
getResourceHierarchies(Integer policyType) {
+                       if(policyType == null) {
+                               policyType = RangerPolicy.POLICY_TYPE_ACCESS;
+                       }
+
+                       Set<List<RangerResourceDef>> ret = 
_hierarchies.get(policyType);
+
+                       if(ret == null) {
+                               ret = EMPTY_RESOURCE_HIERARCHY;
+                       }
+
+                       return ret;
                }
 
                public String getServiceName() {
@@ -211,21 +217,45 @@ public class RangerServiceDefHelper {
                 * @return
                 */
                DirectedGraph createGraph(List<RangerResourceDef> resourceDefs) 
{
-                       DirectedGraph graph = new DirectedGraph();
-                       for (RangerResourceDef resourceDef : resourceDefs) {
-                               String name = resourceDef.getName();
-                               graph.add(name);
-                               String parent = resourceDef.getParent();
-                               if (StringUtils.isNotEmpty(parent)) {
-                                       graph.addArc(parent, name);
+                       DirectedGraph graph = null;
+
+                       if(CollectionUtils.isNotEmpty(resourceDefs)) {
+                               graph = new DirectedGraph();
+
+                               for (RangerResourceDef resourceDef : 
resourceDefs) {
+                                       String name = resourceDef.getName();
+
+                                       graph.add(name);
+                                       String parent = resourceDef.getParent();
+                                       if (StringUtils.isNotEmpty(parent)) {
+                                               graph.addArc(parent, name);
+                                       }
                                }
                        }
+
                        if (LOG.isDebugEnabled()) {
                                LOG.debug("Created graph for resources: " + 
graph);
                        }
                        return graph;
                }
 
+               List<RangerResourceDef> getResourceDefs(RangerServiceDef 
serviceDef, Integer policyType) {
+                       final List<RangerResourceDef> resourceDefs;
+
+                       if(policyType == null || policyType == 
RangerPolicy.POLICY_TYPE_ACCESS) {
+                               resourceDefs = serviceDef.getResources();
+                       } else if(policyType == 
RangerPolicy.POLICY_TYPE_DATAMASK) {
+                               if(serviceDef.getDataMaskDef() != null) {
+                                       resourceDefs = 
serviceDef.getDataMaskDef().getResources();
+                               } else {
+                                       resourceDefs = null;
+                               }
+                       } else { // unknown policyType; use all resources
+                               resourceDefs = serviceDef.getResources();
+                       }
+
+                       return resourceDefs;
+               }
                /**
                 * A valid resource graph is a forest, i.e. a disjoint union of 
trees.  In our case, given that node can have only one "parent" node, we can 
detect this validity simply by ensuring that 
                 * the resource graph has:
@@ -249,7 +279,6 @@ public class RangerServiceDefHelper {
                /**
                 * Returns all valid resource hierarchies for the configured 
resource-defs. Behavior is undefined if it is called on and invalid graph. Use 
<code>isValid</code> to check validation first.
                 * 
-                * @param resourceDefs
                 * @param graph
                 * @return
                 */

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefValidator.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefValidator.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefValidator.java
index 0507fc4..0ed563a 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefValidator.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefValidator.java
@@ -32,6 +32,7 @@ import org.apache.commons.lang.StringUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.ranger.plugin.errors.ValidationErrorCode;
+import org.apache.ranger.plugin.model.RangerPolicy;
 import org.apache.ranger.plugin.model.RangerServiceDef;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
@@ -496,11 +497,13 @@ public class RangerServiceDefValidator extends 
RangerValidator {
                        valid = false;
                }
                // resource level should be unique within a hierarchy
-               Set<List<RangerResourceDef>> hierarchies = 
defHelper.getResourceHierarchies();
-               for (List<RangerResourceDef> aHierarchy : hierarchies) {
-                       Set<Integer> levels = new 
HashSet<Integer>(aHierarchy.size());
-                       for (RangerResourceDef resourceDef : aHierarchy) {
-                               valid = isUnique(resourceDef.getLevel(), 
levels, "resource level", "resources", failures) && valid;
+               for(int policyType : RangerPolicy.POLICY_TYPES) {
+                       Set<List<RangerResourceDef>> hierarchies = 
defHelper.getResourceHierarchies(policyType);
+                       for (List<RangerResourceDef> aHierarchy : hierarchies) {
+                               Set<Integer> levels = new 
HashSet<Integer>(aHierarchy.size());
+                               for (RangerResourceDef resourceDef : 
aHierarchy) {
+                                       valid = 
isUnique(resourceDef.getLevel(), levels, "resource level", "resources", 
failures) && valid;
+                               }
                        }
                }
 

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java
index 075a374..381864d 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java
@@ -292,7 +292,7 @@ public abstract class RangerValidator {
 
        Set<String> getAccessTypes(RangerServiceDef serviceDef) {
                if(LOG.isDebugEnabled()) {
-                       LOG.debug("==> 
RangerValidator.getSupportedAccessTypes(" + serviceDef + ")");
+                       LOG.debug("==> RangerValidator.getAccessTypes(" + 
serviceDef + ")");
                }
 
                Set<String> accessTypes = new HashSet<String>();
@@ -316,7 +316,7 @@ public abstract class RangerValidator {
                }
 
                if(LOG.isDebugEnabled()) {
-                       LOG.debug("<== 
RangerValidator.getSupportedAccessTypes(" + serviceDef + "): " + accessTypes);
+                       LOG.debug("<== RangerValidator.getAccessTypes(" + 
serviceDef + "): " + accessTypes);
                }
                return accessTypes;
        }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java
index 4a394d4..b1463bc 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java
@@ -32,6 +32,7 @@ import 
org.apache.ranger.plugin.policyevaluator.RangerOptimizedPolicyEvaluator;
 import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator;
 import org.apache.ranger.plugin.store.AbstractServiceStore;
 import org.apache.ranger.plugin.util.RangerPerfTracer;
+import org.apache.ranger.plugin.util.ServiceDefUtil;
 import org.apache.ranger.plugin.util.ServicePolicies;
 
 import java.util.*;
@@ -58,7 +59,7 @@ public class RangerPolicyRepository {
         super();
 
         this.componentServiceName = this.serviceName = 
servicePolicies.getServiceName();
-        this.componentServiceDef = this.serviceDef = 
servicePolicies.getServiceDef();
+        this.componentServiceDef = this.serviceDef = 
ServiceDefUtil.normalize(servicePolicies.getServiceDef());
 
         this.appId = appId;
 
@@ -91,7 +92,7 @@ public class RangerPolicyRepository {
         this.serviceName = tagPolicies.getServiceName();
         this.componentServiceName = componentServiceName;
 
-        this.serviceDef = normalizeAccessTypeDefs(tagPolicies.getServiceDef(), 
componentServiceDef.getName());
+        this.serviceDef = 
normalizeAccessTypeDefs(ServiceDefUtil.normalize(tagPolicies.getServiceDef()), 
componentServiceDef.getName());
         this.componentServiceDef = componentServiceDef;
 
         this.appId = appId;
@@ -203,12 +204,14 @@ public class RangerPolicyRepository {
                 normalizeAndPrunePolicyItems(policy.getDenyPolicyItems(), 
componentType);
                 normalizeAndPrunePolicyItems(policy.getAllowExceptions(), 
componentType);
                 normalizeAndPrunePolicyItems(policy.getDenyExceptions(), 
componentType);
+                normalizeAndPrunePolicyItems(policy.getDataMaskPolicyItems(), 
componentType);
 
                 if (!policy.getIsAuditEnabled() &&
                     CollectionUtils.isEmpty(policy.getPolicyItems()) &&
                     CollectionUtils.isEmpty(policy.getDenyPolicyItems()) &&
                     CollectionUtils.isEmpty(policy.getAllowExceptions()) &&
-                    CollectionUtils.isEmpty(policy.getDenyExceptions())) {
+                    CollectionUtils.isEmpty(policy.getDenyExceptions()) &&
+                    CollectionUtils.isEmpty(policy.getDataMaskPolicyItems())) {
 
                     if(policiesToPrune == null) {
                         policiesToPrune = new ArrayList<RangerPolicy>();
@@ -226,7 +229,7 @@ public class RangerPolicyRepository {
         return rangerPolicies;
     }
 
-    private List<RangerPolicy.RangerPolicyItem> 
normalizeAndPrunePolicyItems(List<RangerPolicy.RangerPolicyItem> policyItems, 
final String componentType) {
+    private List<? extends RangerPolicy.RangerPolicyItem> 
normalizeAndPrunePolicyItems(List<? extends RangerPolicy.RangerPolicyItem> 
policyItems, final String componentType) {
         if(CollectionUtils.isNotEmpty(policyItems)) {
             final String                        prefix       = componentType + 
AbstractServiceStore.COMPONENT_ACCESSTYPE_SEPARATOR;
             List<RangerPolicy.RangerPolicyItem> itemsToPrune = null;

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
index c48fb72..b87891f 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
@@ -97,7 +97,7 @@ public class RangerDefaultPolicyEvaluator extends 
RangerAbstractPolicyEvaluator
                resourceMatcher = new RangerDefaultPolicyResourceMatcher();
 
                resourceMatcher.setServiceDef(serviceDef);
-               resourceMatcher.setPolicyResources(policy == null ? null : 
policy.getResources());
+               resourceMatcher.setPolicy(policy);
                resourceMatcher.init();
 
                if(policy != null) {
@@ -118,7 +118,10 @@ public class RangerDefaultPolicyEvaluator extends 
RangerAbstractPolicyEvaluator
                Collections.sort(denyEvaluators);
                Collections.sort(allowExceptionEvaluators);
                Collections.sort(denyExceptionEvaluators);
+
+               /* dataMask policyItems must be evaulated in the order given in 
the policy; hence no sort
                Collections.sort(dataMaskEvaluators);
+               */
 
                RangerPerfTracer.log(perf);
 
@@ -536,9 +539,10 @@ public class RangerDefaultPolicyEvaluator extends 
RangerAbstractPolicyEvaluator
                preprocessPolicyItems(policy.getDenyPolicyItems(), 
impliedAccessGrants);
                preprocessPolicyItems(policy.getAllowExceptions(), 
impliedAccessGrants);
                preprocessPolicyItems(policy.getDenyExceptions(), 
impliedAccessGrants);
+               preprocessPolicyItems(policy.getDataMaskPolicyItems(), 
impliedAccessGrants);
        }
 
-       private void preprocessPolicyItems(List<RangerPolicyItem> policyItems, 
Map<String, Collection<String>> impliedAccessGrants) {
+       private void preprocessPolicyItems(List<? extends RangerPolicyItem> 
policyItems, Map<String, Collection<String>> impliedAccessGrants) {
                for(RangerPolicyItem policyItem : policyItems) {
                        if(CollectionUtils.isEmpty(policyItem.getAccesses())) {
                                continue;

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java
index 710d0c5..2e777ae 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java
@@ -74,6 +74,7 @@ public class RangerOptimizedPolicyEvaluator extends 
RangerDefaultPolicyEvaluator
         preprocessPolicyItems(policy.getDenyPolicyItems());
         preprocessPolicyItems(policy.getAllowExceptions());
         preprocessPolicyItems(policy.getDenyExceptions());
+        preprocessPolicyItems(policy.getDataMaskPolicyItems());
 
         hasAllPerms = checkIfHasAllPerms();
 
@@ -264,7 +265,7 @@ public class RangerOptimizedPolicyEvaluator extends 
RangerDefaultPolicyEvaluator
         return ret;
     }
 
-    private void preprocessPolicyItems(List<RangerPolicy.RangerPolicyItem> 
policyItems) {
+    private void preprocessPolicyItems(List<? extends 
RangerPolicy.RangerPolicyItem> policyItems) {
         if(CollectionUtils.isNotEmpty(policyItems)) {
                for (RangerPolicy.RangerPolicyItem item : policyItems) {
                    delegateAdmin = delegateAdmin || item.getDelegateAdmin();

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerDefaultPolicyResourceMatcher.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerDefaultPolicyResourceMatcher.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerDefaultPolicyResourceMatcher.java
index 4742850..6ea194d 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerDefaultPolicyResourceMatcher.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerDefaultPolicyResourceMatcher.java
@@ -29,6 +29,7 @@ import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.model.RangerPolicy;
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
 import org.apache.ranger.plugin.model.RangerServiceDef;
@@ -42,7 +43,8 @@ import com.google.common.collect.Sets;
 public class RangerDefaultPolicyResourceMatcher implements 
RangerPolicyResourceMatcher {
        private static final Log LOG = 
LogFactory.getLog(RangerDefaultPolicyResourceMatcher.class);
 
-       protected RangerServiceDef                  serviceDef     = null;
+       protected RangerServiceDef                  serviceDef      = null;
+       protected RangerPolicy                      policy          = null;
        protected Map<String, RangerPolicyResource> policyResources = null;
 
        private Map<String, RangerResourceMatcher> matchers = null;
@@ -54,6 +56,13 @@ public class RangerDefaultPolicyResourceMatcher implements 
RangerPolicyResourceM
        }
 
        @Override
+       public void setPolicy(RangerPolicy policy) {
+               this.policy = policy;
+
+               setPolicyResources(policy == null ? null : 
policy.getResources());
+       }
+
+       @Override
        public void setPolicyResources(Map<String, RangerPolicyResource> 
policyResources) {
                this.policyResources = policyResources;
        }
@@ -71,7 +80,8 @@ public class RangerDefaultPolicyResourceMatcher implements 
RangerPolicyResourceM
                        Set<String> policyResourceKeySet = 
policyResources.keySet();
 
                        RangerServiceDefHelper serviceDefHelper = new 
RangerServiceDefHelper(serviceDef, false);
-                       Set<List<RangerResourceDef>> validResourceHierarchies = 
serviceDefHelper.getResourceHierarchies();
+                       int policyType = policy != null && 
policy.getPolicyType() != null ? policy.getPolicyType() : 
RangerPolicy.POLICY_TYPE_ACCESS;
+                       Set<List<RangerResourceDef>> validResourceHierarchies = 
serviceDefHelper.getResourceHierarchies(policyType);
 
                        for (List<RangerResourceDef> validResourceHierarchy : 
validResourceHierarchies) {
 

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java
index f743d55..54b9586 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java
@@ -21,6 +21,7 @@ package org.apache.ranger.plugin.policyresourcematcher;
 
 import java.util.Map;
 
+import org.apache.ranger.plugin.model.RangerPolicy;
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
 import org.apache.ranger.plugin.model.RangerServiceDef;
 import org.apache.ranger.plugin.policyengine.RangerAccessResource;
@@ -28,6 +29,8 @@ import 
org.apache.ranger.plugin.policyengine.RangerAccessResource;
 public interface RangerPolicyResourceMatcher {
        void setServiceDef(RangerServiceDef serviceDef);
 
+       void setPolicy(RangerPolicy policy);
+
        void setPolicyResources(Map<String, RangerPolicyResource> 
policyResources);
 
        void init();

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerAbstractResourceMatcher.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerAbstractResourceMatcher.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerAbstractResourceMatcher.java
index 5063eea..cd725c9 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerAbstractResourceMatcher.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerAbstractResourceMatcher.java
@@ -75,16 +75,18 @@ public abstract class RangerAbstractResourceMatcher 
implements RangerResourceMat
                policyIsExcludes = policyResource == null ? false : 
policyResource.getIsExcludes();
 
                if(policyResource != null && policyResource.getValues() != 
null) {
-                       boolean isWildCardPresent = !optWildCard;
+                       boolean isWildCardPresent = false;
                        for(String policyValue : policyResource.getValues()) {
                                if(StringUtils.isEmpty(policyValue)) {
                                        continue;
                                }
 
-                               if(StringUtils.containsOnly(policyValue, 
WILDCARD_ASTERISK)) {
-                                       isMatchAny = true;
-                               } else if (!isWildCardPresent && 
StringUtils.containsAny(policyValue, WILDCARDS)) {
-                                       isWildCardPresent = true;
+                               if(optWildCard) {
+                                       if 
(StringUtils.containsOnly(policyValue, WILDCARD_ASTERISK)) {
+                                               isMatchAny = true;
+                                       } else if (!isWildCardPresent && 
StringUtils.containsAny(policyValue, WILDCARDS)) {
+                                               isWildCardPresent = true;
+                                       }
                                }
                                policyValues.add(policyValue);
                        }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java
index 1ec88d5..aef7bcb 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java
@@ -182,6 +182,18 @@ public class RangerBasePlugin {
                return null;
        }
 
+       public RangerDataMaskResult evalDataMaskPolicies(RangerAccessRequest 
request, RangerAccessResultProcessor resultProcessor) {
+               RangerPolicyEngine policyEngine = this.policyEngine;
+
+               if(policyEngine != null) {
+                       policyEngine.preProcess(request);
+
+                       return policyEngine.evalDataMaskPolicies(request, 
resultProcessor);
+               }
+
+               return null;
+       }
+
        public RangerResourceAccessInfo 
getResourceAccessInfo(RangerAccessRequest request) {
                RangerPolicyEngine policyEngine = this.policyEngine;
 

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java 
b/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java
index 90242da..fa04816 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java
@@ -19,11 +19,18 @@
 
 package org.apache.ranger.plugin.util;
 
+import org.apache.commons.collections.ArrayStack;
+import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
 import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.HashMap;
 import java.util.Map;
 
 public class ServiceDefUtil {
@@ -40,6 +47,124 @@ public class ServiceDefUtil {
         return ret;
     }
 
+    public static RangerServiceDef normalize(RangerServiceDef serviceDef) {
+        normalizeDataMaskDef(serviceDef);
+
+        return serviceDef;
+    }
+
+    private static void normalizeDataMaskDef(RangerServiceDef serviceDef) {
+        if(serviceDef != null && serviceDef.getDataMaskDef() != null) {
+            List<RangerResourceDef>   dataMaskResources   = 
serviceDef.getDataMaskDef().getResources();
+            List<RangerAccessTypeDef> dataMaskAccessTypes = 
serviceDef.getDataMaskDef().getAccessTypes();
+
+            if(CollectionUtils.isNotEmpty(dataMaskResources)) {
+                List<RangerResourceDef> resources     = 
serviceDef.getResources();
+                List<RangerResourceDef> processedDefs = new 
ArrayList<RangerResourceDef>(dataMaskResources.size());
+
+                for(RangerResourceDef dataMaskResource : dataMaskResources) {
+                    RangerResourceDef processedDef = dataMaskResource;
+
+                    for(RangerResourceDef resourceDef : resources) {
+                        if(StringUtils.equals(resourceDef.getName(), 
dataMaskResource.getName())) {
+                            processedDef = 
ServiceDefUtil.mergeResourceDef(resourceDef, dataMaskResource);
+                            break;
+                        }
+                    }
+
+                    processedDefs.add(processedDef);
+                }
+
+                serviceDef.getDataMaskDef().setResources(processedDefs);
+            }
+
+            if(CollectionUtils.isNotEmpty(dataMaskAccessTypes)) {
+                List<RangerAccessTypeDef> accessTypes   = 
serviceDef.getAccessTypes();
+                List<RangerAccessTypeDef> processedDefs = new 
ArrayList<RangerAccessTypeDef>(accessTypes.size());
+
+                for(RangerAccessTypeDef dataMaskAccessType : 
dataMaskAccessTypes) {
+                    RangerAccessTypeDef processedDef = dataMaskAccessType;
+
+                    for(RangerAccessTypeDef accessType : accessTypes) {
+                        if(StringUtils.equals(accessType.getName(), 
dataMaskAccessType.getName())) {
+                            processedDef = 
ServiceDefUtil.mergeAccessTypeDef(accessType, dataMaskAccessType);
+                            break;
+                        }
+                    }
+
+                    processedDefs.add(processedDef);
+                }
+
+                serviceDef.getDataMaskDef().setAccessTypes(processedDefs);
+            }
+        }
+    }
+
+    private static RangerResourceDef mergeResourceDef(RangerResourceDef base, 
RangerResourceDef delta) {
+        RangerResourceDef ret = new RangerResourceDef(base);
+
+        // retain base values for: itemId, name, type, level, parent, 
mandatory, lookupSupported
+
+        if(delta.getRecursiveSupported() != null)
+            ret.setRecursiveSupported(delta.getRecursiveSupported());
+
+        if(delta.getExcludesSupported() != null)
+            ret.setExcludesSupported(delta.getExcludesSupported());
+
+        if(StringUtils.isNotEmpty(delta.getMatcher()))
+            ret.setMatcher(delta.getMatcher());
+
+        if(MapUtils.isNotEmpty(delta.getMatcherOptions())) {
+            if(ret.getMatcherOptions() == null) {
+                ret.setMatcherOptions(new HashMap<String, String>());
+            }
+
+            for(Map.Entry<String, String> e : 
delta.getMatcherOptions().entrySet()) {
+                ret.getMatcherOptions().put(e.getKey(), e.getValue());
+            }
+        }
+
+        if(StringUtils.isNotEmpty(delta.getValidationRegEx()))
+            ret.setValidationRegEx(delta.getValidationRegEx());
+
+        if(StringUtils.isNotEmpty(delta.getValidationMessage()))
+            ret.setValidationMessage(delta.getValidationMessage());
+
+        if(StringUtils.isNotEmpty(delta.getUiHint()))
+            ret.setUiHint(delta.getUiHint());
+
+        if(StringUtils.isNotEmpty(delta.getLabel()))
+            ret.setLabel(delta.getLabel());
+
+        if(StringUtils.isNotEmpty(delta.getDescription()))
+            ret.setDescription(delta.getDescription());
+
+        if(StringUtils.isNotEmpty(delta.getRbKeyLabel()))
+            ret.setRbKeyLabel(delta.getRbKeyLabel());
+
+        if(StringUtils.isNotEmpty(delta.getRbKeyDescription()))
+            ret.setRbKeyDescription(delta.getRbKeyDescription());
+
+        if(StringUtils.isNotEmpty(delta.getRbKeyValidationMessage()))
+            ret.setRbKeyValidationMessage(delta.getRbKeyValidationMessage());
+
+        return ret;
+    }
+
+    private static RangerAccessTypeDef mergeAccessTypeDef(RangerAccessTypeDef 
base, RangerAccessTypeDef delta) {
+        RangerAccessTypeDef ret = new RangerAccessTypeDef(base);
+
+        // retain base values for: itemId, name, impliedGrants
+
+        if(StringUtils.isNotEmpty(delta.getLabel()))
+            ret.setLabel(delta.getLabel());
+
+        if(StringUtils.isNotEmpty(delta.getRbKeyLabel()))
+            ret.setRbKeyLabel(delta.getRbKeyLabel());
+
+        return ret;
+    }
+
     private static boolean getBooleanValue(Map<String, String> map, String 
elementName, boolean defaultValue) {
         boolean ret = defaultValue;
 

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/main/resources/service-defs/ranger-servicedef-hive.json
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/resources/service-defs/ranger-servicedef-hive.json 
b/agents-common/src/main/resources/service-defs/ranger-servicedef-hive.json
index b966be9..77167c4 100644
--- a/agents-common/src/main/resources/service-defs/ranger-servicedef-hive.json
+++ b/agents-common/src/main/resources/service-defs/ranger-servicedef-hive.json
@@ -222,5 +222,83 @@
                "label":"Hive Resources Accessed Together?",
                "description": "List of Hive resources"
          }
-       ]
+       ],
+
+       "dataMaskDef": {
+               "accessTypes": [
+                       {
+                               "name": "select"
+                       }
+               ],
+               "resources": [
+                       {
+                               "name": "database",
+                               "matcherOptions": {
+                                       "wildCard": "false"
+                               },
+                               "lookupSupported": true,
+                               "uiHint":"{ \"singleValue\":true }"
+                       },
+                       {
+                               "name": "table",
+                               "matcherOptions": {
+                                       "wildCard": "false"
+                               },
+                               "lookupSupported": true,
+                               "uiHint":"{ \"singleValue\":true }"
+                       },
+                       {
+                               "name": "column",
+                               "matcherOptions": {
+                                       "wildCard": "false"
+                               },
+                               "lookupSupported": true,
+                               "uiHint":"{ \"singleValue\":true }"
+                       }
+               ],
+               "maskTypes": [
+                       {
+                               "itemId": 1,
+                               "name": "MASK",
+                               "label": "Mask",
+                               "description": "Replace lowercase with 'x', 
uppercase with 'X', digits with '0'",
+                               "dataMaskOptions": { }
+                       },
+                       {
+                               "itemId": 2,
+                               "name": "SHUFFLE",
+                               "label": "Shuffle",
+                               "description": "Shuffle the value of the 
column",
+                               "dataMaskOptions": { }
+                       },
+                       {
+                               "itemId": 3,
+                               "name": "MASK_x_SHOW_LAST_4",
+                               "label": "Partial mask: show last 4",
+                               "description": "Show last 4 characters; replace 
rest with 'x'",
+                               "dataMaskOptions": { }
+                       },
+                       {
+                               "itemId": 4,
+                               "name": "MASK_x_SHOW_FIRST_4",
+                               "label": "Partial mask: show first 4",
+                               "description": "Show first 4 characters; 
replace rest with 'x'",
+                               "dataMaskOptions": { }
+                       },
+                       {
+                               "itemId": 10,
+                               "name": "NULL",
+                               "label": "NULL",
+                               "description": "Replace with NULL",
+                               "dataMaskOptions": { }
+                       },
+                       {
+                               "itemId": 11,
+                               "name": "NONE",
+                               "label": "No masking",
+                               "description": "No masking",
+                               "dataMaskOptions": { }
+                       }
+               ]
+       }
 }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPolicyResourceSignature.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPolicyResourceSignature.java
 
b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPolicyResourceSignature.java
index 7cc2831..8c8c4c0 100644
--- 
a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPolicyResourceSignature.java
+++ 
b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPolicyResourceSignature.java
@@ -86,19 +86,19 @@ public class TestRangerPolicyResourceSignature {
                rangerPolicy = mock(RangerPolicy.class);
                when(rangerPolicy.getResources()).thenReturn(null);
                policySerializer = new PolicySerializer(rangerPolicy);
-               assertFalse("policy.getSupportedResources()==null", 
policySerializer.isPolicyValidForResourceSignatureComputation());
+               assertFalse("policy.getResources()==null", 
policySerializer.isPolicyValidForResourceSignatureComputation());
                
                // empty resources map is ok!
                Map<String, RangerPolicyResource> policyResources = new 
HashMap<String, RangerPolicyResource>();
                when(rangerPolicy.getResources()).thenReturn(policyResources);
                policySerializer = new PolicySerializer(rangerPolicy);
-               assertTrue("policy.getSupportedResources().isEmpty()", 
policySerializer.isPolicyValidForResourceSignatureComputation());
+               assertTrue("policy.getResources().isEmpty()", 
policySerializer.isPolicyValidForResourceSignatureComputation());
                
                // but having a resource map with null key is not ok!
                RangerPolicyResource aPolicyResource = 
mock(RangerPolicyResource.class);
                policyResources.put(null, aPolicyResource);
                policySerializer = new PolicySerializer(rangerPolicy);
-               assertFalse("policy.getSupportedResources().contains(null)", 
policySerializer.isPolicyValidForResourceSignatureComputation());
+               assertFalse("policy.getResources().contains(null)", 
policySerializer.isPolicyValidForResourceSignatureComputation());
        }
        
        @Test

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefHelper.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefHelper.java
 
b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefHelper.java
index d9e50e4..af158b0 100644
--- 
a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefHelper.java
+++ 
b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefHelper.java
@@ -31,6 +31,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
+import org.apache.ranger.plugin.model.RangerPolicy;
 import org.apache.ranger.plugin.model.RangerServiceDef;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
 import 
org.apache.ranger.plugin.model.validation.RangerServiceDefHelper.Delegate;
@@ -79,7 +80,7 @@ public class TestRangerServiceDefHelper {
                // now assert the behavior
                _helper = new RangerServiceDefHelper(_serviceDef);
                assertTrue(_helper.isResourceGraphValid());
-               Set<List<RangerResourceDef>> hierarchies = 
_helper.getResourceHierarchies();
+               Set<List<RangerResourceDef>> hierarchies = 
_helper.getResourceHierarchies(RangerPolicy.POLICY_TYPE_ACCESS);
                // there should be 
                List<RangerResourceDef> hierarchy = 
Lists.newArrayList(Database, UDF);
                assertTrue(hierarchies.contains(hierarchy));
@@ -136,7 +137,7 @@ public class TestRangerServiceDefHelper {
                when(_serviceDef.getResources()).thenReturn(resourceDefs);
                _helper = new RangerServiceDefHelper(_serviceDef);
                assertTrue(_helper.isResourceGraphValid());
-               Set<List<RangerResourceDef>> hierarchies = 
_helper.getResourceHierarchies();
+               Set<List<RangerResourceDef>> hierarchies = 
_helper.getResourceHierarchies(RangerPolicy.POLICY_TYPE_ACCESS);
 
                Set<List<String>> expectedHierarchies = new 
HashSet<List<String>>(); 
                expectedHierarchies.add(Lists.newArrayList("database", 
"table-space"));
@@ -177,7 +178,7 @@ public class TestRangerServiceDefHelper {
                when(_serviceDef.getResources()).thenReturn(resourceDefs);
                _helper = new RangerServiceDefHelper(_serviceDef);
                assertTrue(_helper.isResourceGraphValid());
-               Set<List<RangerResourceDef>> hierarchies = 
_helper.getResourceHierarchies();
+               Set<List<RangerResourceDef>> hierarchies = 
_helper.getResourceHierarchies(RangerPolicy.POLICY_TYPE_ACCESS);
 
                Set<List<String>> expectedHierarchies = new 
HashSet<List<String>>(); 
                expectedHierarchies.add(Lists.newArrayList("database"));

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/agents-common/src/test/resources/policyengine/test_policyengine_hive_masking.json
----------------------------------------------------------------------
diff --git 
a/agents-common/src/test/resources/policyengine/test_policyengine_hive_masking.json
 
b/agents-common/src/test/resources/policyengine/test_policyengine_hive_masking.json
index 92b21aa..b0e4557 100644
--- 
a/agents-common/src/test/resources/policyengine/test_policyengine_hive_masking.json
+++ 
b/agents-common/src/test/resources/policyengine/test_policyengine_hive_masking.json
@@ -43,16 +43,22 @@
           "name": "SHUFFLE",
           "label": "Shuffle",
           "description": "Randomly shuffle the contents"
+        },
+        {
+          "itemId": 10,
+          "name": "NULL",
+          "label": "NULL",
+          "description": "Replace with NULL"
         }
 
       ],
-      "supportedAccessTypes": [
-        "select"
+      "accessTypes":[
+        {"name":"select","label":"Select"}
       ],
-      "supportedResources": [
-        "database",
-        "table",
-        "column"
+      "resources":[
+        {"name":"database","matcherOptions":{"wildCard":false}},
+        {"name":"table","matcherOptions":{"wildCard":false}},
+        {"name":"column","matcherOptions":{"wildCard":false}}
       ]
     }
   },
@@ -65,7 +71,7 @@
      ]
     },
     {"id":101,"name":"db=*, table=*, column=ssn: mask ssn column in all 
tables, databases","isEnabled":true,"isAuditEnabled":true,"policyType":1,
-      
"resources":{"database":{"values":["*"]},"table":{"values":["*"]},"column":{"values":["ssn"]}},
+      
"resources":{"database":{"values":["employee"]},"table":{"values":["personal"]},"column":{"values":["ssn"]}},
       "dataMaskPolicyItems":[
         
{"accesses":[{"type":"select","isAllowed":true}],"users":["user1"],"groups":[],"delegateAdmin":false,
          "dataMaskInfo": {"dataMaskType":"MASK"}
@@ -76,7 +82,7 @@
       ]
     },
     {"id":102,"name":"db=hr, table=*, column=date_of_birth: mask date_of_birth 
column in all tables in hr 
database","isEnabled":true,"isAuditEnabled":true,"policyType":1,
-      
"resources":{"database":{"values":["hr"]},"table":{"values":["*"]},"column":{"values":["date_of_birth"]}},
+      
"resources":{"database":{"values":["hr"]},"table":{"values":["employee"]},"column":{"values":["date_of_birth"]}},
       "dataMaskPolicyItems":[
         
{"accesses":[{"type":"select","isAllowed":true}],"users":["user1"],"groups":[],"delegateAdmin":false,
           "dataMaskInfo": {"dataMaskType":"MASK"}
@@ -124,9 +130,9 @@
       },
       
"dataMaskResult":{"maskType":"MASK","maskCondition":null,"maskValue":null,"policyId":102}
     },
-    {"name":"'select date_of_birth from hr.employee2;' for user2 - 
maskType=SHUFFLE",
+    {"name":"'select date_of_birth from hr.employee;' for user2 - 
maskType=SHUFFLE",
       "request":{
-        "resource":{"elements":{"database":"hr", "table":"employee2", 
"column":"date_of_birth"}},
+        "resource":{"elements":{"database":"hr", "table":"employee", 
"column":"date_of_birth"}},
         
"accessType":"select","user":"user2","userGroups":[],"requestData":"select 
date_of_birth from hr.employee2;' for user2"
       },
       
"dataMaskResult":{"maskType":"SHUFFLE","maskCondition":null,"maskValue":null,"policyId":102}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/security-admin/db/mysql/patches/020-datamask-policy.sql
----------------------------------------------------------------------
diff --git a/security-admin/db/mysql/patches/020-datamask-policy.sql 
b/security-admin/db/mysql/patches/020-datamask-policy.sql
index 43d9395..32e8a3e 100644
--- a/security-admin/db/mysql/patches/020-datamask-policy.sql
+++ b/security-admin/db/mysql/patches/020-datamask-policy.sql
@@ -13,37 +13,37 @@
 -- See the License for the specific language governing permissions and
 -- limitations under the License.
 
-/* add datamasking_supported column in x_access_type_def table if not exist */
-drop procedure if exists add_datamasking_supported_to_x_access_type_def_table;
+/* add datamask_options column in x_access_type_def table if not exist */
+drop procedure if exists add_datamask_options_to_x_access_type_def_table;
 delimiter ;;
- create procedure add_datamasking_supported_to_x_access_type_def_table() begin
+ create procedure add_datamask_options_to_x_access_type_def_table() begin
  
  if exists (select * from information_schema.columns where 
table_schema=database() and table_name = 'x_access_type_def') then
-       if not exists (select * from information_schema.columns where 
table_schema=database() and table_name = 'x_access_type_def' and column_name = 
'datamasking_supported') then
-               ALTER TABLE `x_access_type_def` ADD `datamasking_supported` 
tinyint NOT NULL DEFAULT 0;
+       if not exists (select * from information_schema.columns where 
table_schema=database() and table_name = 'x_access_type_def' and column_name = 
'datamask_options') then
+               ALTER TABLE `x_access_type_def` ADD `datamask_options` 
varchar(1024) DEFAULT NULL;
        end if;
  end if; 
 end;;
 
 delimiter ;
-call add_datamasking_supported_to_x_access_type_def_table();
-drop procedure if exists add_datamasking_supported_to_x_access_type_def_table;
+call add_datamask_options_to_x_access_type_def_table();
+drop procedure if exists add_datamask_options_to_x_access_type_def_table;
 
-/* add datamasking_supported column in x_resource_def table if not exist */
-drop procedure if exists add_datamasking_supported_to_x_resource_def_table;
+/* add datamask_options column in x_resource_def table if not exist */
+drop procedure if exists add_datamask_options_to_x_resource_def_table;
 delimiter ;;
- create procedure add_datamasking_supported_to_x_resource_def_table() begin
+ create procedure add_datamask_options_to_x_resource_def_table() begin
  
  if exists (select * from information_schema.columns where 
table_schema=database() and table_name = 'x_resource_def') then
-       if not exists (select * from information_schema.columns where 
table_schema=database() and table_name = 'x_resource_def' and column_name = 
'datamasking_supported') then
-               ALTER TABLE `x_resource_def` ADD `datamasking_supported` 
tinyint NOT NULL DEFAULT 0;
+       if not exists (select * from information_schema.columns where 
table_schema=database() and table_name = 'x_resource_def' and column_name = 
'datamask_options') then
+               ALTER TABLE `x_resource_def` ADD `datamask_options` 
varchar(1024) DEFAULT NULL;
        end if;
  end if; 
 end;;
 
 delimiter ;
-call add_datamasking_supported_to_x_resource_def_table();
-drop procedure if exists add_datamasking_supported_to_x_resource_def_table;
+call add_datamask_options_to_x_resource_def_table();
+drop procedure if exists add_datamask_options_to_x_resource_def_table;
 
 DROP TABLE IF EXISTS `x_datamask_type_def`;
 CREATE TABLE `x_datamask_type_def` (

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/security-admin/db/postgres/patches/020-datamask-policy.sql
----------------------------------------------------------------------
diff --git a/security-admin/db/postgres/patches/020-datamask-policy.sql 
b/security-admin/db/postgres/patches/020-datamask-policy.sql
new file mode 100644
index 0000000..4387e02
--- /dev/null
+++ b/security-admin/db/postgres/patches/020-datamask-policy.sql
@@ -0,0 +1,97 @@
+-- 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.
+
+select 'delimiter start';
+
+/* add x_access_type_def.datamask_options column if it does not exist */
+CREATE OR REPLACE FUNCTION add_datamask_options_to_x_access_type_def_table() 
+RETURNS void AS $$
+DECLARE
+ exists_access_type_def_datamask_options integer := 0;
+BEGIN
+ select count(*) into exists_access_type_def_datamask_options from 
pg_attribute where attrelid in(select oid from pg_class where 
relname='x_access_type_def') and attname='datamask_options';
+ IF exists_access_type_def_datamask_options = 0 THEN
+       ALTER TABLE x_access_type_def ADD COLUMN datamask_options VARCHAR(1024) 
DEFAULT NULL;
+ END IF;
+END;
+$$ LANGUAGE plpgsql;
+
+/* add x_resource_def.datamask_options column if it does not exist */
+CREATE OR REPLACE FUNCTION add_datamask_options_to_x_resource_def_table() 
+RETURNS void AS $$
+DECLARE
+ exists_resource_def_datamask_options integer := 0;
+BEGIN
+ select count(*) into exists_resource_def_datamask_options from pg_attribute 
where attrelid in(select oid from pg_class where relname='x_resource_def') and 
attname='datamask_options';
+ IF exists_resource_def_datamask_options = 0 THEN
+       ALTER TABLE x_resource_def ADD COLUMN datamask_options VARCHAR(1024) 
DEFAULT NULL;
+ END IF;
+END;
+$$ LANGUAGE plpgsql;
+
+select 'delimiter end';
+
+
+SELECT add_datamask_options_to_x_access_type_def_table();
+SELECT add_datamask_options_to_x_resource_def_table();
+
+DROP TABLE IF EXISTS x_datamask_type_def;
+DROP TABLE IF EXISTS x_policy_item_datamask;
+DROP SEQUENCE IF EXISTS x_datamask_type_def_seq;
+DROP SEQUENCE IF EXISTS x_policy_item_datamask_def_seq;
+
+CREATE SEQUENCE x_datamask_type_def_seq;
+CREATE TABLE x_datamask_type_def (
+  id BIGINT DEFAULT nextval('x_datamask_type_def_seq'::regclass),
+  guid VARCHAR(1024) DEFAULT NULL,
+  create_time TIMESTAMP DEFAULT NULL,
+  update_time TIMESTAMP DEFAULT NULL,
+  added_by_id BIGINT DEFAULT NULL,
+  upd_by_id BIGINT DEFAULT NULL,
+  def_id BIGINT NOT NULL,    
+  item_id BIGINT NOT NULL,    
+  name VARCHAR(1024) NOT NULL,
+  label VARCHAR(1024) NOT NULL,
+  description VARCHAR(1024) DEFAULT NULL,
+  datamask_options VARCHAR(1024) DEFAULT NULL,
+  rb_key_label VARCHAR(1024) DEFAULT NULL,
+  rb_key_description VARCHAR(1024) DEFAULT NULL,
+  sort_order SMALLINT DEFAULT '0',
+  primary key (id),      
+  CONSTRAINT x_datamask_type_def_FK_def_id FOREIGN KEY (def_id) REFERENCES 
x_service_def (id) ,
+  CONSTRAINT x_datamask_type_def_FK_added_by_id FOREIGN KEY (added_by_id) 
REFERENCES x_portal_user (id),
+  CONSTRAINT x_datamask_type_def_FK_upd_by_id FOREIGN KEY (upd_by_id) 
REFERENCES x_portal_user (id)
+);
+CREATE INDEX x_datamask_type_def_IDX_def_id ON x_datamask_type_def(def_id);
+
+CREATE SEQUENCE x_policy_item_datamask_seq;
+CREATE TABLE x_policy_item_datamask (
+  id BIGINT DEFAULT nextval('x_policy_item_datamask_seq'::regclass),
+  guid VARCHAR(1024) DEFAULT NULL,
+  create_time TIMESTAMP DEFAULT NULL,
+  update_time TIMESTAMP DEFAULT NULL,
+  added_by_id BIGINT DEFAULT NULL,
+  upd_by_id BIGINT DEFAULT NULL,
+  policy_item_id BIGINT NOT NULL, 
+  type BIGINT NOT NULL,
+  condition_expr VARCHAR(1024) DEFAULT NULL,
+  value_expr VARCHAR(1024) DEFAULT NULL,
+  primary key (id), 
+  CONSTRAINT x_policy_item_datamask_FK_policy_item_id FOREIGN KEY 
(policy_item_id) REFERENCES x_policy_item (id) ,
+  CONSTRAINT x_policy_item_datamask_FK_type FOREIGN KEY (type) REFERENCES 
x_datamask_type_def (id),
+  CONSTRAINT x_policy_item_datamask_FK_added_by_id FOREIGN KEY (added_by_id) 
REFERENCES x_portal_user (id),
+  CONSTRAINT x_policy_item_datamask_FK_upd_by_id FOREIGN KEY (upd_by_id) 
REFERENCES x_portal_user (id)
+);
+CREATE INDEX x_policy_item_datamask_IDX_policy_item_id ON 
x_policy_item_datamask(policy_item_id);

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
----------------------------------------------------------------------
diff --git 
a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java 
b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
index 77203dc..c4a823c 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
@@ -326,9 +326,9 @@ public class ServiceDBStore extends AbstractServiceStore {
                }
 
                if(dataMaskDef != null) {
-                       List<RangerDataMaskTypeDef> dataMaskTypes        = 
dataMaskDef.getMaskTypes();
-                       List<String>                supportedAccessTypes = 
dataMaskDef.getSupportedAccessTypes();
-                       List<String>                supportedResources   = 
dataMaskDef.getSupportedResources();
+                       List<RangerDataMaskTypeDef> dataMaskTypes       = 
dataMaskDef.getMaskTypes();
+                       List<RangerAccessTypeDef>   dataMaskAccessTypes = 
dataMaskDef.getAccessTypes();
+                       List<RangerResourceDef>     dataMaskResources   = 
dataMaskDef.getResources();
 
                        if(CollectionUtils.isNotEmpty(dataMaskTypes)) {
                                XXDataMaskTypeDefDao xxDataMaskDefDao = 
daoMgr.getXXDataMaskTypeDef();
@@ -343,14 +343,15 @@ public class ServiceDBStore extends AbstractServiceStore {
                                }
                        }
 
-                       if(CollectionUtils.isNotEmpty(supportedAccessTypes)) {
+                       if(CollectionUtils.isNotEmpty(dataMaskAccessTypes)) {
                                List<XXAccessTypeDef> xxAccessTypeDefs = 
xxATDDao.findByServiceDefId(xServiceDef.getId());
 
-                               for(String accessType : supportedAccessTypes) {
+                               for(RangerAccessTypeDef accessType : 
dataMaskAccessTypes) {
                                        boolean found = false;
                                        for(XXAccessTypeDef xxAccessTypeDef : 
xxAccessTypeDefs) {
-                                               
if(StringUtils.equals(xxAccessTypeDef.getName(), accessType)) {
+                                               
if(StringUtils.equals(xxAccessTypeDef.getName(), accessType.getName())) {
                                                        found = true;
+
                                                        break;
                                                }
                                        }
@@ -362,22 +363,29 @@ public class ServiceDBStore extends AbstractServiceStore {
                                }
 
                                for(XXAccessTypeDef xxAccessTypeDef : 
xxAccessTypeDefs) {
-                                       boolean isDatamaskingSupported = 
supportedAccessTypes.contains(xxAccessTypeDef.getName());
+                                       String dataMaskOptions = null;
+
+                                       for(RangerAccessTypeDef 
dataMaskAccessType : dataMaskAccessTypes) {
+                                               
if(StringUtils.equals(dataMaskAccessType.getName(), xxAccessTypeDef.getName())) 
{
+                                                       dataMaskOptions = 
svcDefServiceWithAssignedId.objectToJson(dataMaskAccessType);
+                                                       break;
+                                               }
+                                       }
 
-                                       
if(xxAccessTypeDef.isDatamaskingSupported() != isDatamaskingSupported) {
-                                               
xxAccessTypeDef.setDatamaskingSupported(isDatamaskingSupported);
+                                       if(! 
StringUtils.equals(dataMaskOptions, xxAccessTypeDef.getDataMaskOptions())) {
+                                               
xxAccessTypeDef.setDataMaskOptions(dataMaskOptions);
                                                
xxATDDao.update(xxAccessTypeDef);
                                        }
                                }
                        }
 
-                       if(CollectionUtils.isNotEmpty(supportedResources)) {
+                       if(CollectionUtils.isNotEmpty(dataMaskResources)) {
                                List<XXResourceDef> xxResourceDefs = 
xxResDefDao.findByServiceDefId(xServiceDef.getId());
 
-                               for(String resource : supportedResources) {
+                               for(RangerResourceDef resource : 
dataMaskResources) {
                                        boolean found = false;
                                        for(XXResourceDef xxResourceDef : 
xxResourceDefs) {
-                                               
if(StringUtils.equals(xxResourceDef.getName(), resource)) {
+                                               
if(StringUtils.equals(xxResourceDef.getName(), resource.getName())) {
                                                        found = true;
                                                        break;
                                                }
@@ -390,10 +398,17 @@ public class ServiceDBStore extends AbstractServiceStore {
                                }
 
                                for(XXResourceDef xxResourceDef : 
xxResourceDefs) {
-                                       boolean isDatamaskingSupported = 
supportedResources.contains(xxResourceDef.getName());
+                                       String dataMaskOptions = null;
+
+                                       for(RangerResourceDef dataMaskResource 
: dataMaskResources) {
+                                               
if(StringUtils.equals(dataMaskResource.getName(), xxResourceDef.getName())) {
+                                                       dataMaskOptions = 
svcDefServiceWithAssignedId.objectToJson(dataMaskResource);
+                                                       break;
+                                               }
+                                       }
 
-                                       
if(xxResourceDef.isDatamaskingSupported() != isDatamaskingSupported) {
-                                               
xxResourceDef.setDatamaskingSupported(isDatamaskingSupported);
+                                       if(! 
StringUtils.equals(dataMaskOptions, xxResourceDef.getDataMaskOptions())) {
+                                               
xxResourceDef.setDataMaskOptions(dataMaskOptions);
                                                
xxResDefDao.update(xxResourceDef);
                                        }
                                }
@@ -807,11 +822,11 @@ public class ServiceDBStore extends AbstractServiceStore {
                        }
                }
 
-               List<RangerDataMaskTypeDef> dataMasks            = dataMaskDef 
== null || dataMaskDef.getMaskTypes() == null ? new 
ArrayList<RangerDataMaskTypeDef>() : dataMaskDef.getMaskTypes();
-               List<String>                supportedAccessTypes = dataMaskDef 
== null || dataMaskDef.getSupportedAccessTypes() == null ? new 
ArrayList<String>() : dataMaskDef.getSupportedAccessTypes();
-               List<String>                supportedResources   = dataMaskDef 
== null || dataMaskDef.getSupportedResources() == null ? new 
ArrayList<String>() : dataMaskDef.getSupportedResources();
-               XXDataMaskTypeDefDao        dataMaskTypeDao      = 
daoMgr.getXXDataMaskTypeDef();
-               List<XXDataMaskTypeDef>     xxDataMaskTypes      = 
dataMaskTypeDao.findByServiceDefId(serviceDefId);
+               List<RangerDataMaskTypeDef> dataMasks           = dataMaskDef 
== null || dataMaskDef.getMaskTypes() == null ? new 
ArrayList<RangerDataMaskTypeDef>() : dataMaskDef.getMaskTypes();
+               List<RangerAccessTypeDef>   dataMaskAccessTypes = dataMaskDef 
== null || dataMaskDef.getAccessTypes() == null ? new 
ArrayList<RangerAccessTypeDef>() : dataMaskDef.getAccessTypes();
+               List<RangerResourceDef>     dataMaskResources   = dataMaskDef 
== null || dataMaskDef.getResources() == null ? new 
ArrayList<RangerResourceDef>() : dataMaskDef.getResources();
+               XXDataMaskTypeDefDao        dataMaskTypeDao     = 
daoMgr.getXXDataMaskTypeDef();
+               List<XXDataMaskTypeDef>     xxDataMaskTypes     = 
dataMaskTypeDao.findByServiceDefId(serviceDefId);
                // create or update dataMasks
                for (RangerServiceDef.RangerDataMaskTypeDef dataMask : 
dataMasks) {
                        boolean found = false;
@@ -861,10 +876,10 @@ public class ServiceDBStore extends AbstractServiceStore {
 
                List<XXAccessTypeDef> xxAccessTypeDefs = 
xxATDDao.findByServiceDefId(serviceDefId);
 
-               for(String accessType : supportedAccessTypes) {
+               for(RangerAccessTypeDef accessType : dataMaskAccessTypes) {
                        boolean found = false;
                        for(XXAccessTypeDef xxAccessTypeDef : xxAccessTypeDefs) 
{
-                               
if(StringUtils.equals(xxAccessTypeDef.getName(), accessType)) {
+                               
if(StringUtils.equals(xxAccessTypeDef.getName(), accessType.getName())) {
                                        found = true;
                                        break;
                                }
@@ -877,20 +892,27 @@ public class ServiceDBStore extends AbstractServiceStore {
                }
 
                for(XXAccessTypeDef xxAccessTypeDef : xxAccessTypeDefs) {
-                       boolean isDatamaskingSupported = 
supportedAccessTypes.contains(xxAccessTypeDef.getName());
+                       String dataMaskOptions = null;
 
-                       if(xxAccessTypeDef.isDatamaskingSupported() != 
isDatamaskingSupported) {
-                               
xxAccessTypeDef.setDatamaskingSupported(isDatamaskingSupported);
+                       for(RangerAccessTypeDef dataMaskAccessType : 
dataMaskAccessTypes) {
+                               
if(StringUtils.equals(dataMaskAccessType.getName(), xxAccessTypeDef.getName())) 
{
+                                       dataMaskOptions = 
svcDefServiceWithAssignedId.objectToJson(dataMaskAccessType);
+                                       break;
+                               }
+                       }
+
+                       if(! StringUtils.equals(dataMaskOptions, 
xxAccessTypeDef.getDataMaskOptions())) {
+                               
xxAccessTypeDef.setDataMaskOptions(dataMaskOptions);
                                xxATDDao.update(xxAccessTypeDef);
                        }
                }
 
                List<XXResourceDef> xxResourceDefs = 
xxResDefDao.findByServiceDefId(serviceDefId);
 
-               for(String resource : supportedResources) {
+               for(RangerResourceDef resource : dataMaskResources) {
                        boolean found = false;
                        for(XXResourceDef xxResourceDef : xxResourceDefs) {
-                               if(StringUtils.equals(xxResourceDef.getName(), 
resource)) {
+                               if(StringUtils.equals(xxResourceDef.getName(), 
resource.getName())) {
                                        found = true;
                                        break;
                                }
@@ -903,10 +925,17 @@ public class ServiceDBStore extends AbstractServiceStore {
                }
 
                for(XXResourceDef xxResourceDef : xxResourceDefs) {
-                       boolean isDatamaskingSupported = 
supportedResources.contains(xxResourceDef.getName());
+                       String dataMaskOptions = null;
+
+                       for(RangerResourceDef dataMaskResource : 
dataMaskResources) {
+                               
if(StringUtils.equals(dataMaskResource.getName(), xxResourceDef.getName())) {
+                                       dataMaskOptions = 
svcDefServiceWithAssignedId.objectToJson(dataMaskResource);
+                                       break;
+                               }
+                       }
 
-                       if(xxResourceDef.isDatamaskingSupported() != 
isDatamaskingSupported) {
-                               
xxResourceDef.setDatamaskingSupported(isDatamaskingSupported);
+                       if(! StringUtils.equals(dataMaskOptions, 
xxResourceDef.getDataMaskOptions())) {
+                               
xxResourceDef.setDataMaskOptions(dataMaskOptions);
                                xxResDefDao.update(xxResourceDef);
                        }
                }
@@ -2016,7 +2045,7 @@ public class ServiceDBStore extends AbstractServiceStore {
                        // we need to create one policy for each resource 
hierarchy
                        RangerServiceDefHelper serviceDefHelper = new 
RangerServiceDefHelper(serviceDef);
                        int i = 1;
-                       for (List<RangerResourceDef> aHierarchy : 
serviceDefHelper.getResourceHierarchies()) {
+                       for (List<RangerResourceDef> aHierarchy : 
serviceDefHelper.getResourceHierarchies(RangerPolicy.POLICY_TYPE_ACCESS)) {
                                createDefaultPolicy(createdService, vXUser, 
aHierarchy, i);
                                i++;
                        }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/security-admin/src/main/java/org/apache/ranger/common/JSONUtil.java
----------------------------------------------------------------------
diff --git 
a/security-admin/src/main/java/org/apache/ranger/common/JSONUtil.java 
b/security-admin/src/main/java/org/apache/ranger/common/JSONUtil.java
index 38a1659..db4c9c6 100644
--- a/security-admin/src/main/java/org/apache/ranger/common/JSONUtil.java
+++ b/security-admin/src/main/java/org/apache/ranger/common/JSONUtil.java
@@ -24,6 +24,7 @@ package org.apache.ranger.common;
 
 import java.io.File;
 import java.io.IOException;
+import java.io.Serializable;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -34,6 +35,7 @@ import org.codehaus.jackson.JsonGenerationException;
 import org.codehaus.jackson.JsonParseException;
 import org.codehaus.jackson.map.JsonMappingException;
 import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.ser.StdSerializers;
 import org.codehaus.jackson.type.TypeReference;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
@@ -130,12 +132,12 @@ public class JSONUtil {
                return jsonString;
        }
 
-       public String writeObjectAsString(ViewBaseBean vObj) {
+       public String writeObjectAsString(Serializable obj) {
                ObjectMapper mapper = new ObjectMapper();
 
                String jsonStr;
                try {
-                       jsonStr = mapper.writeValueAsString(vObj);
+                       jsonStr = mapper.writeValueAsString(obj);
                        return jsonStr;
                } catch (JsonParseException e) {
                        throw restErrorUtil.createRESTException(
@@ -151,5 +153,22 @@ public class JSONUtil {
                                        MessageEnums.INVALID_INPUT_DATA);
                }
        }
-       
+
+       public <T> T writeJsonToJavaObject(String json, Class<T> tClass) {
+               ObjectMapper mapper = new ObjectMapper();
+
+               try {
+                       return mapper.readValue(json, tClass);
+               } catch (JsonParseException e) {
+                       throw restErrorUtil.createRESTException("Invalid input 
data: " + e.getMessage(),
+                                       MessageEnums.INVALID_INPUT_DATA);
+               } catch (JsonMappingException e) {
+                       throw restErrorUtil.createRESTException("Invalid input 
data: " + e.getMessage(),
+                                       MessageEnums.INVALID_INPUT_DATA);
+               } catch (IOException e) {
+                       throw restErrorUtil.createRESTException("Invalid input 
data: " + e.getMessage(),
+                                       MessageEnums.INVALID_INPUT_DATA);
+               }
+       }
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/security-admin/src/main/java/org/apache/ranger/entity/XXAccessTypeDef.java
----------------------------------------------------------------------
diff --git 
a/security-admin/src/main/java/org/apache/ranger/entity/XXAccessTypeDef.java 
b/security-admin/src/main/java/org/apache/ranger/entity/XXAccessTypeDef.java
index 62b11ce..5bc22e0 100644
--- a/security-admin/src/main/java/org/apache/ranger/entity/XXAccessTypeDef.java
+++ b/security-admin/src/main/java/org/apache/ranger/entity/XXAccessTypeDef.java
@@ -94,13 +94,13 @@ public class XXAccessTypeDef extends XXDBBase implements 
java.io.Serializable {
        protected Integer order;
 
        /**
-        * datamaskingSupported of the XXAccessTypeDef
+        * dataMaskOptions of the XXAccessTypeDef
         * <ul>
         * </ul>
         *
         */
-       @Column(name = "datamasking_supported")
-       protected boolean datamaskingSupported;
+       @Column(name = "datamask_options")
+       protected String dataMaskOptions;
 
        /**
         * This method sets the value to the member attribute <b> id</b> . You
@@ -242,12 +242,12 @@ public class XXAccessTypeDef extends XXDBBase implements 
java.io.Serializable {
                return this.order;
        }
 
-       public boolean isDatamaskingSupported() {
-               return datamaskingSupported;
+       public String getDataMaskOptions() {
+               return dataMaskOptions;
        }
 
-       public void setDatamaskingSupported(boolean datamaskingSupported) {
-               this.datamaskingSupported = datamaskingSupported;
+       public void setDataMaskOptions(String dataMaskOptions) {
+               this.dataMaskOptions = dataMaskOptions;
        }
 
        /*
@@ -319,7 +319,11 @@ public class XXAccessTypeDef extends XXDBBase implements 
java.io.Serializable {
                } else if (!rbKeyLabel.equals(other.rbKeyLabel)) {
                        return false;
                }
-               if (datamaskingSupported != other.datamaskingSupported) {
+               if (dataMaskOptions == null) {
+                       if (other.dataMaskOptions != null) {
+                               return false;
+                       }
+               } else if (!dataMaskOptions.equals(other.dataMaskOptions)) {
                        return false;
                }
                return true;
@@ -334,7 +338,7 @@ public class XXAccessTypeDef extends XXDBBase implements 
java.io.Serializable {
        public String toString() {
                return "XXAccessTypeDef [" + super.toString() + " id=" + id
                                + ", defId=" + defId + ", itemId=" + itemId + 
", name=" + name + ", label=" + label
-                               + ", rbKeyLabel=" + rbKeyLabel + ", 
datamaskingSupported=" + datamaskingSupported + ", order=" + order + "]";
+                               + ", rbKeyLabel=" + rbKeyLabel + ", 
dataMaskOptions=" + dataMaskOptions + ", order=" + order + "]";
        }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/security-admin/src/main/java/org/apache/ranger/entity/XXResourceDef.java
----------------------------------------------------------------------
diff --git 
a/security-admin/src/main/java/org/apache/ranger/entity/XXResourceDef.java 
b/security-admin/src/main/java/org/apache/ranger/entity/XXResourceDef.java
index 8a2b6e0..6679c35 100644
--- a/security-admin/src/main/java/org/apache/ranger/entity/XXResourceDef.java
+++ b/security-admin/src/main/java/org/apache/ranger/entity/XXResourceDef.java
@@ -229,13 +229,13 @@ public class XXResourceDef extends XXDBBase implements 
java.io.Serializable {
        protected Integer order;
 
        /**
-        * datamaskingSupported of the XXResourceDef
+        * dataMaskOptions of the XXResourceDef
         * <ul>
         * </ul>
         *
         */
-       @Column(name = "datamasking_supported")
-       protected boolean datamaskingSupported;
+       @Column(name = "datamask_options")
+       protected String dataMaskOptions;
 
        /**
         * This method sets the value to the member attribute <b> id</b> . You
@@ -653,12 +653,12 @@ public class XXResourceDef extends XXDBBase implements 
java.io.Serializable {
                return this.order;
        }
 
-       public boolean isDatamaskingSupported() {
-               return datamaskingSupported;
+       public String getDataMaskOptions() {
+               return dataMaskOptions;
        }
 
-       public void setDatamaskingSupported(boolean datamaskingSupported) {
-               this.datamaskingSupported = datamaskingSupported;
+       public void setDataMaskOptions(String dataMaskOptions) {
+               this.dataMaskOptions = dataMaskOptions;
        }
 
        /*
@@ -796,7 +796,11 @@ public class XXResourceDef extends XXDBBase implements 
java.io.Serializable {
                } else if (!type.equals(other.type)) {
                        return false;
                }
-               if (datamaskingSupported != other.datamaskingSupported) {
+               if (dataMaskOptions == null) {
+                       if (other.dataMaskOptions != null) {
+                               return false;
+                       }
+               } else if (!dataMaskOptions.equals(other.dataMaskOptions)) {
                        return false;
                }
                return true;
@@ -824,7 +828,7 @@ public class XXResourceDef extends XXDBBase implements 
java.io.Serializable {
                                + ", rbKeyDescription=" + rbKeyDescription
                                + ", rbKeyValidationMessage=" + 
rbKeyValidationMessage
                                + ", order=" + order
-                               + ", datamaskingSupported=" + 
datamaskingSupported
+                               + ", dataMaskOptions=" + dataMaskOptions
                                + "]";
        }
 

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/164d46fd/security-admin/src/main/java/org/apache/ranger/service/RangerServiceDefServiceBase.java
----------------------------------------------------------------------
diff --git 
a/security-admin/src/main/java/org/apache/ranger/service/RangerServiceDefServiceBase.java
 
b/security-admin/src/main/java/org/apache/ranger/service/RangerServiceDefServiceBase.java
index 7a172d4..9e2e9f5 100644
--- 
a/security-admin/src/main/java/org/apache/ranger/service/RangerServiceDefServiceBase.java
+++ 
b/security-admin/src/main/java/org/apache/ranger/service/RangerServiceDefServiceBase.java
@@ -17,6 +17,7 @@
 
 package org.apache.ranger.service;
 
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -45,6 +46,7 @@ import 
org.apache.ranger.plugin.model.RangerServiceDef.RangerPolicyConditionDef;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef;
 import org.apache.ranger.plugin.util.SearchFilter;
+import org.apache.ranger.plugin.util.ServiceDefUtil;
 import org.apache.ranger.view.RangerServiceDefList;
 import org.springframework.beans.factory.annotation.Autowired;
 
@@ -156,24 +158,30 @@ public abstract class RangerServiceDefServiceBase<T 
extends XXServiceDefBase, V
 
                if (!stringUtil.isEmpty(xResources)) {
                        for (XXResourceDef xResource : xResources) {
-                               if (xResource.isDatamaskingSupported()) {
-                                       
dataMaskDef.getSupportedResources().add(xResource.getName());
+                               if 
(StringUtils.isNotEmpty(xResource.getDataMaskOptions())) {
+                                       RangerResourceDef dataMaskResource = 
jsonToObject(xResource.getDataMaskOptions(), RangerResourceDef.class);
+
+                                       
dataMaskDef.getResources().add(dataMaskResource);
                                }
                        }
                }
 
                if (!stringUtil.isEmpty(xAccessTypes)) {
                        for (XXAccessTypeDef xAtd : xAccessTypes) {
-                               if(xAtd.isDatamaskingSupported()) {
-                                       
dataMaskDef.getSupportedAccessTypes().add(xAtd.getName());
+                               
if(StringUtils.isNotEmpty(xAtd.getDataMaskOptions())) {
+                                       RangerAccessTypeDef dataMaskAccessType 
= jsonToObject(xAtd.getDataMaskOptions(), RangerAccessTypeDef.class);
+
+                                       
dataMaskDef.getAccessTypes().add(dataMaskAccessType);
                                }
                        }
                }
                serviceDef.setDataMaskDef(dataMaskDef);
 
+               ServiceDefUtil.normalize(serviceDef);
+
                return serviceDef;
        }
-       
+
        @SuppressWarnings("unchecked")
        @Override
        protected XXServiceDefBase mapViewToEntityBean(RangerServiceDef vObj, 
XXServiceDefBase xObj, int operationContext) {
@@ -537,7 +545,7 @@ public abstract class RangerServiceDefServiceBase<T extends 
XXServiceDefBase, V
                retList.setResultSize(onePageList.size());
                retList.setTotalCount(xxObjList.size());
        }
-       
+
        private String mapToJsonString(Map<String, String> map) {
                String ret = null;
 
@@ -585,4 +593,32 @@ public abstract class RangerServiceDefServiceBase<T 
extends XXServiceDefBase, V
 
                return ret;
        }
+
+       public String objectToJson(Serializable obj) {
+               String ret = null;
+
+               if(obj != null) {
+                       try {
+                               ret = jsonUtil.writeObjectAsString(obj);
+                       } catch(Exception excp) {
+                               LOG.warn("objectToJson() failed to convert 
object to json: " + obj, excp);
+                       }
+               }
+
+               return ret;
+       }
+
+       public <T> T jsonToObject(String jsonStr, Class<T> clz) {
+               T ret = null;
+
+               if(StringUtils.isNotEmpty(jsonStr)) {
+                       try {
+                               ret = jsonUtil.writeJsonToJavaObject(jsonStr, 
clz);
+                       } catch(Exception excp) {
+                               LOG.warn("jsonToObject() failed to convert json 
to object: " + jsonStr, excp);
+                       }
+               }
+
+               return ret;
+       }
 }

Reply via email to