RANGER-1781: Policy model update to support restricted access-types based on 
selected resource

Signed-off-by: Madhan Neethiraj <[email protected]>


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

Branch: refs/heads/master
Commit: 7985dd473acb024e8f3c56c12af6608b0cecc3b6
Parents: e0c1e35
Author: Abhay Kulkarni <[email protected]>
Authored: Fri Oct 6 08:46:43 2017 -0700
Committer: Madhan Neethiraj <[email protected]>
Committed: Tue Oct 10 22:20:24 2017 -0700

----------------------------------------------------------------------
 .../ranger/plugin/model/RangerServiceDef.java   |   46 +-
 .../model/validation/RangerPolicyValidator.java |   16 +-
 .../validation/RangerServiceDefHelper.java      |  126 +-
 .../RangerDefaultPolicyResourceMatcher.java     | 1296 +++++++++---------
 .../plugin/service/RangerBaseService.java       |   47 +-
 .../plugin/service/RangerDefaultService.java    |   49 +
 .../ranger/plugin/util/RangerResourceTrie.java  |    2 -
 .../ranger/plugin/util/ServiceDefUtil.java      |   52 +-
 .../validation/TestRangerPolicyValidator.java   |    8 +-
 .../validation/TestRangerServiceDefHelper.java  |  114 +-
 .../model/validation/ValidationTestUtils.java   |    1 +
 .../plugin/policyengine/TestPolicyEngine.java   |    6 +-
 ...stDefaultPolicyResourceMatcherForPolicy.java |    5 +-
 .../test_defaultpolicyresourcematcher.json      |    4 +-
 ...rcematcher_for_resource_specific_policy.json |  335 +++++
 .../ranger/services/hdfs/RangerServiceHdfs.java |  134 +-
 .../org/apache/ranger/biz/ServiceDBStore.java   |   96 +-
 .../java/org/apache/ranger/biz/ServiceMgr.java  |   25 +-
 .../service/RangerServiceDefServiceBase.java    |   58 +-
 19 files changed, 1578 insertions(+), 842 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ranger/blob/7985dd47/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 ec3ce69..adafb99 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
@@ -22,8 +22,10 @@ package org.apache.ranger.plugin.model;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
@@ -1242,9 +1244,11 @@ public class RangerServiceDef extends 
RangerBaseModelObject implements java.io.S
                private String              rbKeyLabel;
                private String              rbKeyDescription;
                private String              rbKeyValidationMessage;
+               private Set<String>         accessTypeRestrictions;
+               private Boolean             isValidLeaf;
 
                public RangerResourceDef() {
-                       this(null, null, null, null, null, null, null, null, 
null, null, null, null, null, null, null, null, null, null, null);
+                       this(null, null, null, null, null, null, null, null, 
null, null, null, null, null, null, null, null, null, null, null, null, null);
                }
 
                public RangerResourceDef(RangerResourceDef other) {
@@ -1267,9 +1271,11 @@ public class RangerServiceDef extends 
RangerBaseModelObject implements java.io.S
                        setRbKeyLabel(other.getRbKeyLabel());
                        setRbKeyDescription(other.getRbKeyDescription());
                        
setRbKeyValidationMessage(other.getRbKeyValidationMessage());
+                       
setAccessTypeRestrictions(other.getAccessTypeRestrictions());
+                       setIsValidLeaf(other.getIsValidLeaf());
                }
 
-               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) {
+               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, Set<String> 
accessTypeRestrictions, Boolean isValidLeaf) {
                        setItemId(itemId);
                        setName(name);
                        setType(type);
@@ -1289,6 +1295,8 @@ public class RangerServiceDef extends 
RangerBaseModelObject implements java.io.S
                        setRbKeyLabel(rbKeyLabel);
                        setRbKeyDescription(rbKeyDescription);
                        setRbKeyValidationMessage(rbKeyValidationMessage);
+                       setAccessTypeRestrictions(accessTypeRestrictions);
+                       setIsValidLeaf(isValidLeaf);
                }
 
                /**
@@ -1557,6 +1565,20 @@ public class RangerServiceDef extends 
RangerBaseModelObject implements java.io.S
                        this.rbKeyValidationMessage = rbKeyValidationMessage;
                }
 
+               public Set<String> getAccessTypeRestrictions() {
+                       return accessTypeRestrictions;
+               }
+
+               public void setAccessTypeRestrictions(Set<String> 
accessTypeRestrictions) {
+                       this.accessTypeRestrictions = accessTypeRestrictions == 
null ? new HashSet<String>() : new HashSet<String>(accessTypeRestrictions);
+               }
+
+               public Boolean getIsValidLeaf() { return isValidLeaf; }
+
+               public void setIsValidLeaf(Boolean isValidLeaf) {
+                   this.isValidLeaf = isValidLeaf;
+        }
+
                @Override
                public String toString( ) {
                        StringBuilder sb = new StringBuilder();
@@ -1587,6 +1609,8 @@ public class RangerServiceDef extends 
RangerBaseModelObject implements java.io.S
                        sb.append("rbKeyLabel={").append(rbKeyLabel).append("} 
");
                        
sb.append("rbKeyDescription={").append(rbKeyDescription).append("} ");
                        
sb.append("rbKeyValidationMessage={").append(rbKeyValidationMessage).append("} 
");
+                       
sb.append("accessTypeRestrictions={").append(accessTypeRestrictions == null ? 
"null" : accessTypeRestrictions.toString()).append("} ");
+                       sb.append("isValidLeaf={").append(isValidLeaf == null ? 
"null" : isValidLeaf.toString()).append("} ");
                        sb.append("}");
 
                        return sb;
@@ -1643,6 +1667,12 @@ public class RangerServiceDef extends 
RangerBaseModelObject implements java.io.S
                                        * result
                                        + ((validationRegEx == null) ? 0 : 
validationRegEx
                                                        .hashCode());
+                       result = prime
+                                       * result
+                                       + ((accessTypeRestrictions == null) ? 0 
: accessTypeRestrictions.hashCode());
+                       result = prime
+                                       * result
+                                       + ((isValidLeaf == null) ? 0 : 
isValidLeaf.hashCode());
                        return result;
                }
 
@@ -1746,7 +1776,17 @@ public class RangerServiceDef extends 
RangerBaseModelObject implements java.io.S
                                        return false;
                        } else if 
(!validationRegEx.equals(other.validationRegEx))
                                return false;
-                       return true;
+                       if (accessTypeRestrictions == null) {
+                               if (other.accessTypeRestrictions != null)
+                                       return false;
+                       } else if 
(!accessTypeRestrictions.equals(other.accessTypeRestrictions))
+                               return false;
+            if (isValidLeaf == null) {
+                if (other.isValidLeaf != null)
+                    return false;
+            } else if (!isValidLeaf.equals(other.isValidLeaf))
+                return false;
+            return true;
                }
                
        }

http://git-wip-us.apache.org/repos/asf/ranger/blob/7985dd47/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 0b5fc0e..95eeca7 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
@@ -461,7 +461,18 @@ public class RangerPolicyValidator extends RangerValidator 
{
                RangerServiceDefHelper defHelper = new 
RangerServiceDefHelper(serviceDef);
                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!");
+                       if (LOG.isDebugEnabled()) {
+                               
LOG.debug("RangerPolicyValidator.isValidResourceNames: serviceDef does not have 
any resource hierarchies, possibly due to invalid service def!!");
+                       }
+                       ValidationErrorCode error = 
ValidationErrorCode.POLICY_VALIDATION_ERR_INVALID_RESOURCE_NO_COMPATIBLE_HIERARCHY;
+                       failures.add(new ValidationFailureDetailsBuilder()
+                                       .field("service def resource 
hierarchies")
+                                       .subField("incompatible")
+                                       .isSemanticallyIncorrect()
+                                       
.becauseOf(error.getMessage(serviceDef.getName(), " does not have any resource 
hierarchies"))
+                                       .errorCode(error.getErrorCode())
+                                       .build());
+                       valid = false;
                } else {
                        /*
                         * A policy is for a single hierarchy however, it 
doesn't specify which one.  So we have to guess which hierarchy(s) it possibly 
be for.  First, see if the policy could be for
@@ -572,8 +583,7 @@ public class RangerPolicyValidator extends RangerValidator {
                // helper function skipping sanity checks of getting null 
arguments passed
                Set<List<RangerResourceDef>> result = new 
HashSet<List<RangerResourceDef>>(hierarchies.size());
                for (List<RangerResourceDef> aHierarchy : hierarchies) {
-                       Set<String> hierarchyResources = 
defHelper.getAllResourceNames(aHierarchy);
-                       if (hierarchyResources.containsAll(policyResources)) {
+                       if (defHelper.hierarchyHasAllResources(aHierarchy, 
policyResources)) {
                                result.add(aHierarchy);
                        }
                }

http://git-wip-us.apache.org/repos/asf/ranger/blob/7985dd47/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 9fb724d..7a719ab 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
@@ -179,7 +179,7 @@ public class RangerServiceDefHelper {
                Set<List<RangerResourceDef>> ret = new 
HashSet<List<RangerResourceDef>>();
 
                for (List<RangerResourceDef> hierarchy : 
getResourceHierarchies(policyType)) {
-                       if (getAllResourceNames(hierarchy).containsAll(keys)) {
+                       if (hierarchyHasAllResources(hierarchy, keys)) {
                                ret.add(hierarchy);
                        }
                }
@@ -187,6 +187,28 @@ public class RangerServiceDefHelper {
                return ret;
        }
 
+       public boolean hierarchyHasAllResources(List<RangerResourceDef> 
hierarchy, Collection<String> resourceNames) {
+               boolean foundAllResourceKeys = true;
+
+               for (String resourceKey : resourceNames) {
+                       boolean found = false;
+
+                       for (RangerResourceDef resourceDef : hierarchy) {
+                               if (resourceDef.getName().equals(resourceKey)) {
+                                       found = true;
+                                       break;
+                               }
+                       }
+
+                       if (!found) {
+                               foundAllResourceKeys = false;
+                               break;
+                       }
+               }
+
+               return foundAllResourceKeys;
+       }
+
        public Set<String> getMandatoryResourceNames(List<RangerResourceDef> 
hierarchy) {
                Set<String> result = new HashSet<String>(hierarchy.size());
                for (RangerResourceDef resourceDef : hierarchy) {
@@ -249,9 +271,10 @@ public class RangerServiceDefHelper {
                                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))));
+                                       Map<String, RangerResourceDef> 
resourceDefMap = getResourcesAsMap(resources);
+                                       if (isValid(graph, resourceDefMap)) {
+                                               Set<List<RangerResourceDef>> 
hierarchies = getHierarchies(graph, resourceDefMap);
+                                               _hierarchies.put(policyType, 
Collections.unmodifiableSet(hierarchies));
                                        } else {
                                                isValid = false;
                                                _hierarchies.put(policyType, 
EMPTY_RESOURCE_HIERARCHY);
@@ -266,6 +289,9 @@ public class RangerServiceDefHelper {
                                                _serviceDefFreshnessDate == 
null ? null : _serviceDefFreshnessDate.toString(), _hierarchies);
                                LOG.debug(message);
                        }
+                       if (!_valid) {
+                               LOG.error("ERROR: Service resource-definitions 
do not form valid DAG!!");
+                       }
                }
                
                public Set<List<RangerResourceDef>> 
getResourceHierarchies(Integer policyType) {
@@ -357,40 +383,76 @@ public class RangerServiceDefHelper {
                 *
                 * @return
                 */
-               boolean isValid(DirectedGraph graph) {
-                       return !graph.getSources().isEmpty() && 
!graph.getSinks().isEmpty();
-               }
+        boolean isValid(DirectedGraph graph, Map<String, RangerResourceDef> 
resourceDefMap) {
+            boolean     ret     = true;
+            Set<String> sources = graph.getSources();
+            Set<String> sinks   = graph.getSinks();
+
+            if (CollectionUtils.isEmpty(sources) || 
CollectionUtils.isEmpty(sinks)) {
+                ret = false;
+            } else {
+                for (String sink : sinks) {
+                    RangerResourceDef sinkResourceDef = 
resourceDefMap.get(sink);
+                    if 
(Boolean.FALSE.equals(sinkResourceDef.getIsValidLeaf())) {
+                        LOG.error("Error in path: sink node:[" + sink + "] is 
not leaf node");
+
+                        ret = false;
+                        break;
+                    } else if (sinkResourceDef.getIsValidLeaf() == null) {
+                        LOG.info("Setting sink ResourceDef's isValidLeaf from 
null to 'true'");
+                        sinkResourceDef.setIsValidLeaf(true);
+                    }
+                }
+            }
+
+            return ret;
+        }
 
                /**
                 * 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 graph
+                * @param resourceMap
                 * @return
                 */
-               Set<List<String>> getHierarchies(DirectedGraph graph) {
-                       Set<List<String>> hierarchies = new HashSet<>();
-                       Set<String> sources = graph.getSources();
-                       Set<String> sinks = graph.getSinks();
-                       for (String source : sources) {
-                               /*
-                                * A disconnected node, i.e. one that does not 
have any arc coming into or out of it is a hierarchy in itself!
-                                * A source by definition does not have any 
arcs coming into it.  So if it also doesn't have any neighbors then we know
-                                * it is a disconnected node.
-                                */
-                               if (!graph.hasNeighbors(source)) {
-                                       List<String> path = 
Lists.newArrayList(source);
-                                       hierarchies.add(path);
-                               } else {
-                                       for (String sink : sinks) {
-                                               List<String> path = 
graph.getAPath(source, sink, new HashSet<String>());
-                                               if (!path.isEmpty()) {
-                                                       hierarchies.add(path);
-                                               }
-                                       }
-                               }
-                       }
-                       return hierarchies;
-               }
+        Set<List<RangerResourceDef>> getHierarchies(DirectedGraph graph, 
Map<String, RangerResourceDef> resourceMap) {
+            Set<List<String>> hierarchies = new HashSet<>();
+            Set<String>       sources     = graph.getSources();
+            Set<String>       sinks       = graph.getSinks();
+
+            for (String source : sources) {
+                /*
+                 * A disconnected node, i.e. one that does not have any arc 
coming into or out of it is a hierarchy in itself!
+                 * A source by definition does not have any arcs coming into 
it.  So if it also doesn't have any neighbors then we know
+                 * it is a disconnected node.
+                 */
+                if (!graph.hasNeighbors(source)) {
+                    hierarchies.add(Lists.newArrayList(source));
+                } else {
+                    for (String sink : sinks) {
+                        List<String> path = graph.getAPath(source, sink, new 
HashSet<String>());
+
+                        if (!path.isEmpty()) {
+                            hierarchies.add(path);
+
+                            List<String> workingPath = new ArrayList<String>();
+
+                            for (int index = 0, pathSize = path.size(); index 
< pathSize -1; index++) {
+                                String node = path.get(index);
+
+                                workingPath.add(node);
+
+                                if 
(Boolean.TRUE.equals(resourceMap.get(node).getIsValidLeaf())) {
+                                    hierarchies.add(new 
ArrayList<String>(workingPath));
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            return convertHierarchies(hierarchies, resourceMap);
+        }
                
                Set<List<RangerResourceDef>> 
convertHierarchies(Set<List<String>> hierarchies, Map<String, 
RangerResourceDef> resourceMap) {
                        Set<List<RangerResourceDef>> result = new 
HashSet<List<RangerResourceDef>>(hierarchies.size());
@@ -408,7 +470,7 @@ public class RangerServiceDefHelper {
                /**
                 * Converts resource list to resource map for efficient querying
                 *
-                * @param resourceList
+                * @param resourceList - is guaranteed to be non-null and 
non-empty
                 * @return
                 */
                Map<String, RangerResourceDef> 
getResourcesAsMap(List<RangerResourceDef> resourceList) {

http://git-wip-us.apache.org/repos/asf/ranger/blob/7985dd47/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 5bb7c75..2566a4b 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
@@ -20,6 +20,7 @@
 package org.apache.ranger.plugin.policyresourcematcher;
 
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
@@ -30,6 +31,7 @@ import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.authorization.hadoop.config.RangerConfiguration;
 import org.apache.ranger.plugin.model.RangerPolicy;
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
@@ -40,649 +42,657 @@ import 
org.apache.ranger.plugin.policyengine.RangerAccessResourceImpl;
 import org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher;
 import org.apache.ranger.plugin.resourcematcher.RangerResourceMatcher;
 
-import com.google.common.collect.Sets;
-
 public class RangerDefaultPolicyResourceMatcher implements 
RangerPolicyResourceMatcher {
-       private static final Log LOG = 
LogFactory.getLog(RangerDefaultPolicyResourceMatcher.class);
-
-       protected RangerServiceDef                  serviceDef;
-       protected RangerPolicy                      policy;
-       protected Map<String, RangerPolicyResource> policyResources;
-
-       private Map<String, RangerResourceMatcher> matchers;
-       private boolean                            needsDynamicEval;
-       private List<RangerResourceDef> firstValidResourceDefHierarchy;
-       /*
-        * For hive resource policy:
-        *      lastNonAnyMatcherIndex will be set to
-        *              0 : if all matchers in policy are '*'; such as 
database=*, table=*, column=*
-        *              1 : database=hr, table=*, column=*
-        *              2 : database=<any>, table=employee, column=*
-        *              3 : database=<any>, table=<any>, column=ssn
-        */
-       private int lastNonAnyMatcherIndex;
-
-       @Override
-       public void setServiceDef(RangerServiceDef serviceDef) {
-               this.serviceDef = serviceDef;
-       }
-
-       @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;
-       }
-
-       @Override
-       public boolean getNeedsDynamicEval() {
-               return needsDynamicEval;
-       }
-
-       @Override
-       public void init() {
-               if(LOG.isDebugEnabled()) {
-                       LOG.debug("==> 
RangerDefaultPolicyResourceMatcher.init()");
-               }
-
-               String errorText = "";
-
-               if(policyResources != null && !policyResources.isEmpty() && 
serviceDef != null) {
-                       Set<String> policyResourceKeySet = 
policyResources.keySet();
-
-                       RangerServiceDefHelper serviceDefHelper = new 
RangerServiceDefHelper(serviceDef, false);
-                       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) {
-
-                               Set<String> resourceDefNameSet = 
serviceDefHelper.getAllResourceNames(validResourceHierarchy);
-
-                               if ((Sets.difference(policyResourceKeySet, 
resourceDefNameSet)).isEmpty()) {
-
-                                       firstValidResourceDefHierarchy = 
validResourceHierarchy;
-                                       break;
-
-                               }
-
-                       }
-
-                       if (firstValidResourceDefHierarchy != null) {
-                               List<String> resourceDefNameOrderedList = 
serviceDefHelper.getAllResourceNamesOrdered(firstValidResourceDefHierarchy);
-
-                               boolean foundGapsInResourceSpecs = false;
-                               boolean skipped = false;
-
-                               for (String resourceDefName : 
resourceDefNameOrderedList) {
-                                       RangerPolicyResource policyResource = 
policyResources.get(resourceDefName);
-                                       if (policyResource == null) {
-                                               skipped = true;
-                                       } else if (skipped) {
-                                               foundGapsInResourceSpecs = true;
-                                               break;
-                                       }
-                               }
-
-                               if (foundGapsInResourceSpecs) {
-
-                                       errorText = "policyResources does not 
specify contiguous sequence in any valid resourcedef hiearchy.";
-                                       if (LOG.isDebugEnabled()) {
-                                               
LOG.debug("RangerDefaultPolicyResourceMatcher.init() failed: Gaps found in 
policyResources, internal error, skipping..");
-                                       }
-                                       firstValidResourceDefHierarchy = null;
-
-                               } else {
-                                       matchers = new HashMap<>();
-
-                                       for (RangerResourceDef resourceDef : 
firstValidResourceDefHierarchy) {
-
-                                               String resourceName = 
resourceDef.getName();
-                                               RangerPolicyResource 
policyResource = policyResources.get(resourceName);
-
-                                               if (policyResource != null) {
-                                                       RangerResourceMatcher 
matcher = createResourceMatcher(resourceDef, policyResource);
-
-                                                       if (matcher != null) {
-                                                               if 
(!needsDynamicEval && matcher.getNeedsDynamicEval()) {
-                                                                       
needsDynamicEval = true;
-                                                               }
-                                                               
matchers.put(resourceName, matcher);
-                                                               if 
(!matcher.isMatchAny()) {
-                                                                       
lastNonAnyMatcherIndex = matchers.size();
-                                                               }
-                                                       } else {
-                                                               
LOG.error("failed to find matcher for resource " + resourceName);
-                                                       }
-                                               } else {
-                                                       if 
(LOG.isDebugEnabled()) {
-                                                               
LOG.debug("RangerDefaultPolicyResourceMatcher.init() - no matcher created for " 
+ resourceName + ". Continuing ...");
-                                                       }
-                                               }
-                                       }
-                               }
-                       } else {
-                               errorText = "policyResources elements are not 
part of any valid resourcedef hierarchy.";
-                       }
-               } else {
-                       errorText = " policyResources is null or empty, or 
serviceDef is null.";
-               }
-
-               if(matchers == null) {
-                       Set<String> policyResourceKeys = policyResources == 
null ? null : policyResources.keySet();
-                       StringBuilder sb = new StringBuilder();
-                       if (CollectionUtils.isNotEmpty(policyResourceKeys)) {
-                               for (String policyResourceKeyName : 
policyResourceKeys) {
-                                       sb.append(" 
").append(policyResourceKeyName).append(" ");
-                               }
-                       }
-                       String keysString = sb.toString();
-                       String serviceDefName = serviceDef == null ? "" : 
serviceDef.getName();
-                       String validHierarchy = "";
-                       if (serviceDef != null && 
CollectionUtils.isNotEmpty(firstValidResourceDefHierarchy)) {
-                               RangerServiceDefHelper serviceDefHelper = new 
RangerServiceDefHelper(serviceDef, false);
-                               List<String> resourceDefNameOrderedList = 
serviceDefHelper.getAllResourceNamesOrdered(firstValidResourceDefHierarchy);
-
-                               for (String resourceDefName : 
resourceDefNameOrderedList) {
-                                       validHierarchy += " " + resourceDefName 
+ " ";
-                               }
-                       }
-                       LOG.warn("RangerDefaultPolicyResourceMatcher.init() 
failed: " + errorText + " (serviceDef=" + serviceDefName + ", 
policyResourceKeys=" + keysString
-                       + ", validHierarchy=" + validHierarchy + ")");
-               }
-
-               if(LOG.isDebugEnabled()) {
-                       LOG.debug("<== 
RangerDefaultPolicyResourceMatcher.init()");
-               }
-       }
-
-       @Override
-       public RangerServiceDef getServiceDef() {
-               return serviceDef;
-       }
-
-       @Override
-       public RangerResourceMatcher getResourceMatcher(String resourceName) {
-               return matchers != null ? matchers.get(resourceName) : null;
-       }
-
-       @Override
-       public boolean isMatch(Map<String, RangerPolicyResource> resources, 
Map<String, Object> evalContext) {
-               if(LOG.isDebugEnabled()) {
-                       LOG.debug("==> 
RangerDefaultPolicyResourceMatcher.isMatch(" + resources  + ", " + evalContext 
+ ")");
-               }
-
-               boolean ret = false;
-
-               if(serviceDef != null && serviceDef.getResources() != null) {
-                       Collection<String> resourceKeys = resources == null ? 
null : resources.keySet();
-                       Collection<String> policyKeys   = matchers == null ? 
null : matchers.keySet();
-
-                       boolean keysMatch = 
CollectionUtils.isEmpty(resourceKeys) || (policyKeys != null && 
policyKeys.containsAll(resourceKeys));
-
-                       if(keysMatch) {
-                               for(RangerResourceDef resourceDef : 
serviceDef.getResources()) {
-                                       String                resourceName   = 
resourceDef.getName();
-                                       RangerPolicyResource  resourceValues = 
resources == null ? null : resources.get(resourceName);
-                                       RangerResourceMatcher matcher        = 
matchers == null ? null : matchers.get(resourceName);
-
-                                       // when no value exists for a 
resourceName, consider it a match only if: policy doesn't have a matcher OR 
matcher allows no-value resource
-                                       if(resourceValues == null || 
CollectionUtils.isEmpty(resourceValues.getValues())) {
-                                               ret = matcher == null || 
matcher.isMatch(null, null);
-                                       } else if(matcher != null) {
-                                               for(String resourceValue : 
resourceValues.getValues()) {
-                                                       ret = 
matcher.isMatch(resourceValue, evalContext);
-
-                                                       if(! ret) {
-                                                               break;
-                                                       }
-                                               }
-                                       }
-
-                                       if(! ret) {
-                                               break;
-                                       }
-                               }
-                       } else {
-                               if(LOG.isDebugEnabled()) {
-                                       LOG.debug("isMatch(): keysMatch=false. 
resourceKeys=" + resourceKeys + "; policyKeys=" + policyKeys);
-                               }
-                       }
-               }
-
-               if(LOG.isDebugEnabled()) {
-                       LOG.debug("<== 
RangerDefaultPolicyResourceMatcher.isMatch(" + resources  + ", " + evalContext 
+ "): " + ret);
-               }
-
-               return ret;
-       }
-
-       @Override
-       public boolean isCompleteMatch(RangerAccessResource resource, 
Map<String, Object> evalContext) {
-               if(LOG.isDebugEnabled()) {
-                       LOG.debug("==> 
RangerDefaultPolicyResourceMatcher.isCompleteMatch(" + resource  + ", " + 
evalContext + ")");
-               }
-
-               boolean ret = false;
-
-               if(serviceDef != null && serviceDef.getResources() != null) {
-                       Collection<String> resourceKeys = resource == null ? 
null : resource.getKeys();
-                       Collection<String> policyKeys   = matchers == null ? 
null : matchers.keySet();
-
-                       boolean keysMatch = resourceKeys != null && policyKeys 
!= null && CollectionUtils.isEqualCollection(resourceKeys, policyKeys);
-
-                       if(keysMatch) {
-                               for(RangerResourceDef resourceDef : 
serviceDef.getResources()) {
-                                       String                resourceName  = 
resourceDef.getName();
-                                       String                resourceValue = 
resource == null ? null : resource.getValue(resourceName);
-                                       RangerResourceMatcher matcher       = 
matchers == null ? null : matchers.get(resourceName);
-
-                                       if(StringUtils.isEmpty(resourceValue)) {
-                                               ret = matcher == null || 
matcher.isCompleteMatch(resourceValue, evalContext);
-                                       } else {
-                                               ret = matcher != null && 
matcher.isCompleteMatch(resourceValue, evalContext);
-                                       }
-
-                                       if(! ret) {
-                                               break;
-                                       }
-                               }
-                       } else {
-                               if(LOG.isDebugEnabled()) {
-                                       LOG.debug("isCompleteMatch(): 
keysMatch=false. resourceKeys=" + resourceKeys + "; policyKeys=" + policyKeys);
-                               }
-                       }
-               }
-
-               if(LOG.isDebugEnabled()) {
-                       LOG.debug("<== 
RangerDefaultPolicyResourceMatcher.isCompleteMatch(" + resource  + ", " + 
evalContext + "): " + ret);
-               }
-
-               return ret;
-       }
-
-       @Override
-       public boolean isCompleteMatch(Map<String, RangerPolicyResource> 
resources, Map<String, Object> evalContext) {
-               if(LOG.isDebugEnabled()) {
-                       LOG.debug("==> 
RangerDefaultPolicyResourceMatcher.isCompleteMatch(" + resources + ", " + 
evalContext + ")");
-               }
-
-               boolean ret = false;
-
-               if(serviceDef != null && serviceDef.getResources() != null) {
-                       Collection<String> resourceKeys = resources == null ? 
null : resources.keySet();
-                       Collection<String> policyKeys   = matchers == null ? 
null : matchers.keySet();
-
-                       boolean keysMatch = resourceKeys != null && policyKeys 
!= null && CollectionUtils.isEqualCollection(resourceKeys, policyKeys);
-
-                       if(keysMatch) {
-                               for(RangerResourceDef resourceDef : 
serviceDef.getResources()) {
-                                       String                resourceName   = 
resourceDef.getName();
-                                       RangerPolicyResource  resourceValues = 
resources == null ? null : resources.get(resourceName);
-                                       RangerPolicyResource  policyValues   = 
policyResources == null ? null : policyResources.get(resourceName);
-
-                                       if(resourceValues == null || 
CollectionUtils.isEmpty(resourceValues.getValues())) {
-                                               ret = (policyValues == null || 
CollectionUtils.isEmpty(policyValues.getValues()));
-                                       } else if(policyValues != null && 
CollectionUtils.isNotEmpty(policyValues.getValues())) {
-                                               ret = 
CollectionUtils.isEqualCollection(resourceValues.getValues(), 
policyValues.getValues());
-                                       }
-
-                                       if(! ret) {
-                                               break;
-                                       }
-                               }
-                       } else {
-                               if(LOG.isDebugEnabled()) {
-                                       LOG.debug("isCompleteMatch(): 
keysMatch=false. resourceKeys=" + resourceKeys + "; policyKeys=" + policyKeys);
-                               }
-                       }
-               }
-
-               if(LOG.isDebugEnabled()) {
-                       LOG.debug("<== 
RangerDefaultPolicyResourceMatcher.isCompleteMatch(" + resources + ", " + 
evalContext + "): " + ret);
-               }
-
-               return ret;
-       }
-
-       @Override
-       public boolean isMatch(RangerAccessResource resource, Map<String, 
Object> evalContext) {
-               return isMatch(resource, MatchScope.SELF_OR_ANCESTOR, 
evalContext);
-       }
-
-       @Override
-       public boolean isMatch(RangerPolicy policy, MatchScope scope, 
Map<String, Object> evalContext) {
-
-               boolean ret = false;
-               MatchType matchType = MatchType.NONE;
-
-               Map<String, RangerPolicyResource> resources = 
policy.getResources();
-
-               if (MapUtils.isNotEmpty(resources)) {
-
-                       RangerAccessResourceImpl accessResource = new 
RangerAccessResourceImpl();
-                       accessResource.setServiceDef(serviceDef);
-
-                       // Build up accessResource resourceDef by resourceDef.
-                       // For each resourceDef,
-                       //              examine policy-values one by one.
-                       //              The first value that is acceptable, 
that is,
-                       //                      value matches in any way, is 
used for that resourceDef, and
-                       //                      next resourceDef is processed.
-                       //              If none of the values matches, the 
policy as a whole definitely will not match,
-                       //              therefore, the match is failed
-                       // After all resourceDefs are processed, and some match 
is achieved at every
-                       // level, the final matchType (which is for the entire 
policy) is checked against
-                       // requested scope to determine the match-result.
-
-                       // Unit tests in 
TestDefaultPolicyResourceForPolicy.java, 
test_defaultpolicyresourcematcher_for_policy.json,
-                       // and 
test_defaultpolicyresourcematcher_for_hdfs_policy.json
-
-                       for (RangerResourceDef resourceDef : 
firstValidResourceDefHierarchy) {
-
-                               ret = false;
-                               matchType = MatchType.NONE;
-
-                               String name = resourceDef.getName();
-                               RangerPolicyResource policyResource = 
resources.get(name);
-
-                               if (policyResource != null) {
-                                       for (String value : 
policyResource.getValues()) {
-
-                                               accessResource.setValue(name, 
value);
-
-                                               matchType = 
getMatchType(accessResource, evalContext);
-
-                                               if (matchType != 
MatchType.NONE) { // One value for this resourceDef matched
-                                                       ret = true;
-                                                       break;
-                                               }
-                                       }
-                               }
-
-                               if (!ret) { // None of the values specified for 
this resourceDef matched, no point in continuing with next resourceDef
-                                       break;
-                               }
-                       }
-                       ret = ret && isMatch(scope, matchType);
-               }
-               return ret;
-       }
-
-       @Override
-       public boolean isMatch(RangerAccessResource resource, MatchScope scope, 
Map<String, Object> evalContext) {
-
-               final boolean ret;
-
-               MatchType matchType = getMatchType(resource, evalContext);
-               ret = isMatch(scope, matchType);
-
-               return ret;
-       }
-
-       @Override
-       public MatchType getMatchType(RangerAccessResource resource, 
Map<String, Object> evalContext) {
-               if (LOG.isDebugEnabled()) {
-                       LOG.debug("==> 
RangerDefaultPolicyResourceMatcher.getMatchType(" + resource + evalContext + 
")");
-               }
-
-               int matchersSize = matchers == null ? 0 : matchers.size();
-               int resourceKeysSize = resource == null || resource.getKeys() 
== null ? 0 : resource.getKeys().size();
-
-               MatchType ret = MatchType.NONE;
-
-               if (!isValid(resource)) {
-                       ret = MatchType.NONE;
-               } else if (matchersSize == 0 || lastNonAnyMatcherIndex == 0) {
-                       ret = resourceKeysSize == 0 ? MatchType.SELF : 
MatchType.ANCESTOR;
-               } else if (resourceKeysSize == 0) {
-                       ret = MatchType.DESCENDANT;
-               } else {
-                       int index = 0;
-                       for (RangerResourceDef resourceDef : 
firstValidResourceDefHierarchy) {
-
-                               String resourceName = resourceDef.getName();
-                               RangerResourceMatcher matcher = 
matchers.get(resourceName);
-                               String resourceValue = 
resource.getValue(resourceName);
-
-                               if (resourceValue != null) {
-                                       if (matcher != null) {
-                                               index++;
-                                               if 
(matcher.isMatch(resourceValue, evalContext)) {
-                                                       ret = index == 
resourceKeysSize && matcher.isMatchAny() ? MatchType.ANCESTOR : MatchType.SELF;
-                                               } else {
-                                                       ret = MatchType.NONE;
-                                                       break;
-                                               }
-                                       } else {
-                                               // More resource-levels than 
matchers
-                                               ret = MatchType.ANCESTOR;
-                                               break;
-                                       }
-                               } else {
-                                       if (matcher != null) {
-                                               // More matchers than 
resource-levels
-                                               if (index >= 
lastNonAnyMatcherIndex) {
-                                                       // All AnyMatch 
matchers after this
-                                                       ret = 
MatchType.ANCESTOR;
-                                               } else {
-                                                       ret = 
MatchType.DESCENDANT;
-                                               }
-                                       } else {
-                                               // Common part of several 
possible hierarchies matched
-                                               if (resourceKeysSize > index) {
-                                                       ret = 
MatchType.ANCESTOR;
-                                               }
-                                       }
-                                       break;
-                               }
-                       }
-
-               }
-
-               if (LOG.isDebugEnabled()) {
-                       LOG.debug("<== 
RangerDefaultPolicyResourceMatcher.getMatchType(" + resource + evalContext + 
"): " + ret);
-               }
-
-               return ret;
-       }
-
-       private boolean 
isValidResourceDefHierachyForResource(List<RangerResourceDef> 
resourceHierarchy, RangerAccessResource resource) {
-               boolean foundAllResourceKeys = true;
-
-               for (String resourceKey : resource.getKeys()) {
-                       boolean found = false;
-                       for (RangerResourceDef resourceDef : resourceHierarchy) 
{
-                               if (resourceDef.getName().equals(resourceKey)) {
-                                       found = true;
-                                       break;
-                               }
-                       }
-                       if (!found) {
-                               foundAllResourceKeys = false;
-                               break;
-                       }
-               }
-
-               return foundAllResourceKeys;
-       }
-
-       private boolean isValid(RangerAccessResource resource) {
-               if (LOG.isDebugEnabled()) {
-                       LOG.debug("==> 
RangerDefaultPolicyResourceMatcher.isValid(" + resource + ")");
-               }
-
-               boolean ret = true;
-
-               if (matchers != null && resource != null && resource.getKeys() 
!= null) {
-                       if (matchers.keySet().containsAll(resource.getKeys()) 
|| resource.getKeys().containsAll(matchers.keySet())) {
-
-                               List<RangerResourceDef> aValidHierarchy = null;
-
-                               if 
(resource.getKeys().containsAll(matchers.keySet()) && resource.getKeys().size() 
> matchers.keySet().size()) {
-                                       if 
(isValidResourceDefHierachyForResource(firstValidResourceDefHierarchy, 
resource)) {
-                                               aValidHierarchy = 
firstValidResourceDefHierarchy;
-                                       } else {
-                                               RangerServiceDefHelper 
serviceDefHelper = new RangerServiceDefHelper(serviceDef, false);
-                                               int policyType = policy != null 
&& policy.getPolicyType() != null ? policy.getPolicyType() : 
RangerPolicy.POLICY_TYPE_ACCESS;
-                                               Set<List<RangerResourceDef>> 
validResourceHierarchies = serviceDefHelper.getResourceHierarchies(policyType);
-
-                                               for (List<RangerResourceDef> 
resourceHierarchy : validResourceHierarchies) {
-                                                       if (resourceHierarchy 
== firstValidResourceDefHierarchy) { // Pointer comparison
-                                                               // 
firstValidResourceDefHierarchy is already checked before and it does not match
-                                                               continue;
-                                                       }
-
-                                                       if 
(isValidResourceDefHierachyForResource(resourceHierarchy, resource)) {
-                                                               aValidHierarchy 
= resourceHierarchy;
-                                                               break;
-                                                       }
-                                               }
-                                       }
-                               } else {
-                                       aValidHierarchy = 
firstValidResourceDefHierarchy;
-                               }
-
-                               if (aValidHierarchy != null) {
-                                       boolean skipped = false;
-
-                                       for (RangerResourceDef resourceDef : 
aValidHierarchy) {
-
-                                               String resourceName = 
resourceDef.getName();
-                                               String resourceValue = 
resource.getValue(resourceName);
-
-                                               if (resourceValue == null) {
-                                                       if (!skipped) {
-                                                               skipped = true;
-                                                       }
-                                               } else {
-                                                       if (skipped) {
-                                                               ret = false;
-                                                               break;
-                                                       }
-                                               }
-
-                                       }
-                               } else {
-                                       ret = false;
-                               }
-                       } else {
-                               ret = false;
-                       }
-               }
-
-               if (LOG.isDebugEnabled()) {
-                       LOG.debug("<== 
RangerDefaultPolicyResourceMatcher.isValid(" + resource + "): " + ret);
-               }
-
-               return ret;
-       }
-
-       private boolean isMatch(final MatchScope scope, final MatchType 
matchType) {
-               final boolean ret;
-               switch (scope) {
-                       case SELF_OR_ANCESTOR_OR_DESCENDANT: {
-                               ret = matchType != MatchType.NONE;
-                               break;
-                       }
-                       case SELF: {
-                               ret = matchType == MatchType.SELF;
-                               break;
-                       }
-                       case SELF_OR_DESCENDANT: {
-                               ret = matchType == MatchType.SELF || matchType 
== MatchType.DESCENDANT;
-                               break;
-                       }
-                       case SELF_OR_ANCESTOR: {
-                               ret = matchType == MatchType.SELF || matchType 
== MatchType.ANCESTOR;
-                               break;
-                       }
-                       case DESCENDANT: {
-                               ret = matchType == MatchType.DESCENDANT;
-                               break;
-                       }
-                       case ANCESTOR: {
-                               ret = matchType == MatchType.ANCESTOR;
-                               break;
-                       }
-                       default:
-                               ret = matchType != MatchType.NONE;
-                               break;
-               }
-               return ret;
-       }
-
-       @Override
-       public String toString() {
-               StringBuilder sb = new StringBuilder();
-
-               toString(sb);
-
-               return sb.toString();
-       }
-
-       @Override
-       public StringBuilder toString(StringBuilder sb) {
-               sb.append("RangerDefaultPolicyResourceMatcher={");
-
-               sb.append("matchers={");
-               if(matchers != null) {
-                       for(RangerResourceMatcher matcher : matchers.values()) {
-                               sb.append("{").append(matcher).append("} ");
-                       }
-               }
-               sb.append("} ");
-
-               sb.append("}");
-
-               return sb;
-       }
-
-       protected static RangerResourceMatcher 
createResourceMatcher(RangerResourceDef resourceDef, RangerPolicyResource 
resource) {
-               if(LOG.isDebugEnabled()) {
-                       LOG.debug("==> 
RangerDefaultPolicyResourceMatcher.createResourceMatcher(" + resourceDef + ", " 
+ resource + ")");
-               }
-
-               RangerResourceMatcher ret = null;
-
-               if (resourceDef != null) {
-                       String resName = resourceDef.getName();
-                       String clsName = resourceDef.getMatcher();
-
-                       if (!StringUtils.isEmpty(clsName)) {
-                               try {
-                                       @SuppressWarnings("unchecked")
-                                       Class<RangerResourceMatcher> 
matcherClass = (Class<RangerResourceMatcher>) Class.forName(clsName);
-
-                                       ret = matcherClass.newInstance();
-                               } catch (Exception excp) {
-                                       LOG.error("failed to instantiate 
resource matcher '" + clsName + "' for '" + resName + "'. Default resource 
matcher will be used", excp);
-                               }
-                       }
-
-
-                       if (ret == null) {
-                               ret = new RangerDefaultResourceMatcher();
-                       }
-
-                       if (ret != null) {
-                               ret.setResourceDef(resourceDef);
-                               ret.setPolicyResource(resource);
-                               ret.init();
-                       }
-               } else {
-                       LOG.error("RangerDefaultPolicyResourceMatcher: 
RangerResourceDef is null");
-               }
-
-               if(LOG.isDebugEnabled()) {
-                       LOG.debug("<== 
RangerDefaultPolicyResourceMatcher.createResourceMatcher(" + resourceDef + ", " 
+ resource + "): " + ret);
-               }
-
-               return ret;
-       }
+    private static final Log LOG = 
LogFactory.getLog(RangerDefaultPolicyResourceMatcher.class);
+
+    protected RangerServiceDef                  serviceDef;
+    protected RangerPolicy                      policy;
+    protected Map<String, RangerPolicyResource> policyResources;
+
+    private Map<String, RangerResourceMatcher>  allMatchers;
+    private boolean                             needsDynamicEval = false;
+    private List<RangerResourceDef>             validResourceHierarchy;
+    private boolean                             isInitialized = false;
+    private RangerServiceDefHelper              serviceDefHelper;
+
+    @Override
+    public void setServiceDef(RangerServiceDef serviceDef) {
+        if (isInitialized) {
+            LOG.warn("RangerDefaultPolicyResourceMatcher(policyId=" + 
getPolicyId() + "): already initialized. init() must be done again after 
updating serviceDef");
+        }
+
+        this.serviceDef = serviceDef;
+    }
+
+    @Override
+    public void setPolicy(RangerPolicy policy) {
+        if (isInitialized) {
+            LOG.warn("RangerDefaultPolicyResourceMatcher(policyId=" + 
getPolicyId() + "): already initialized. init() must be done again after 
updating policy");
+        }
+
+        this.policy          = policy;
+        this.policyResources = (policy == null ? null : policy.getResources());
+    }
+
+    @Override
+    public void setPolicyResources(Map<String, RangerPolicyResource> 
policyResources) {
+        if (isInitialized) {
+            LOG.warn("RangerDefaultPolicyResourceMatcher(policyId=" + 
getPolicyId() + "): already initialized. init() must be done again after 
updating policy-resources");
+        }
+
+        this.policyResources = policyResources;
+    }
+
+    @Override
+    public boolean getNeedsDynamicEval() { return needsDynamicEval; }
+
+    @Override
+    public void init() {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> RangerDefaultPolicyResourceMatcher(policyId=" + 
getPolicyId() + ").init()");
+        }
+
+        allMatchers            = null;
+        needsDynamicEval       = false;
+        validResourceHierarchy = null;
+        isInitialized          = false;
+        serviceDefHelper       = null;
+
+        String errorText = "";
+
+        boolean useCache = 
RangerConfiguration.getInstance().getBoolean("ranger.plugin.use-cache-for-service-def-helper",
 false);
+
+        if (policyResources != null && !policyResources.isEmpty() && 
serviceDef != null) {
+            serviceDefHelper                                    = new 
RangerServiceDefHelper(serviceDef, useCache);
+
+            Set<List<RangerResourceDef>> resourceHierarchies   = 
serviceDefHelper.getResourceHierarchies(getPolicyType(), 
policyResources.keySet());
+            int                          validHierarchiesCount = 0;
+
+            for (List<RangerResourceDef> resourceHierarchy : 
resourceHierarchies) {
+                boolean foundGapsInResourceSpecs = false;
+                boolean skipped                  = false;
+
+                for (RangerResourceDef resourceDef : resourceHierarchy) {
+                    RangerPolicyResource policyResource = 
policyResources.get(resourceDef.getName());
+
+                    if (policyResource == null) {
+                        skipped = true;
+                    } else if (skipped) {
+                        foundGapsInResourceSpecs = true;
+                        break;
+                    }
+                }
+
+                if (foundGapsInResourceSpecs) {
+                    LOG.warn("RangerDefaultPolicyResourceMatcher(policyId=" + 
getPolicyId() + ").init(): gaps found in policyResources, skipping hierarchy:[" 
+ resourceHierarchies + "]");
+                } else {
+                    validHierarchiesCount++;
+
+                    if (validHierarchiesCount == 1) {
+                        validResourceHierarchy = resourceHierarchy;
+                    } else {
+                        validResourceHierarchy = null;
+                    }
+                }
+            }
+
+            if (validHierarchiesCount > 0) {
+                allMatchers = new HashMap<>();
+
+                for (List<RangerResourceDef> resourceHierarchy : 
resourceHierarchies) {
+                    for (RangerResourceDef resourceDef : resourceHierarchy) {
+                        String resourceName = resourceDef.getName();
+
+                        if (allMatchers.get(resourceName) != null) {
+                            continue;
+                        }
+
+                        RangerPolicyResource policyResource = 
policyResources.get(resourceName);
+
+                        if (policyResource == null) {
+                            if (LOG.isDebugEnabled()) {
+                                
LOG.debug("RangerDefaultPolicyResourceMatcher(policyId=" + getPolicyId() + 
").init(): no matcher created for " + resourceName + ". Continuing ...");
+                            }
+
+                            continue;
+                        }
+
+                        RangerResourceMatcher matcher = 
createResourceMatcher(resourceDef, policyResource);
+
+                        if (matcher != null) {
+                            if (!needsDynamicEval && 
matcher.getNeedsDynamicEval()) {
+                                needsDynamicEval = true;
+                            }
+
+                            allMatchers.put(resourceName, matcher);
+                        } else {
+                            
LOG.error("RangerDefaultPolicyResourceMatcher(policyId=" + getPolicyId() + 
").init(): failed to find matcher for resource " + resourceName);
+
+                            allMatchers = null;
+                            errorText   = "no matcher found for resource " + 
resourceName;
+
+                            break;
+                        }
+                    }
+
+                    if (allMatchers == null) {
+                        break;
+                    }
+                }
+            } else {
+                errorText = "policyResources elements are not part of any 
valid resourcedef hierarchy.";
+            }
+        } else {
+            errorText = "policyResources is null or empty, or serviceDef is 
null.";
+        }
+
+        if (allMatchers == null) {
+            serviceDefHelper       = null;
+            validResourceHierarchy = null;
+
+            Set<String>   policyResourceKeys = policyResources == null ? null 
: policyResources.keySet();
+            String        serviceDefName     = serviceDef == null ? "" : 
serviceDef.getName();
+            StringBuilder keysString         = new StringBuilder();
+
+            if (CollectionUtils.isNotEmpty(policyResourceKeys)) {
+                for (String policyResourceKeyName : policyResourceKeys) {
+                    keysString.append(policyResourceKeyName).append(" ");
+                }
+            }
+
+            LOG.error("RangerDefaultPolicyResourceMatcher(policyId=" + 
getPolicyId() + ").init() failed: " + errorText + " (serviceDef=" + 
serviceDefName + ", policyResourceKeys=" + keysString.toString());
+        } else {
+            isInitialized = true;
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== RangerDefaultPolicyResourceMatcher(policyId=" + 
getPolicyId() + ").init(): ret=" + isInitialized);
+        }
+    }
+
+    @Override
+    public RangerServiceDef getServiceDef() {
+        return serviceDef;
+    }
+
+    @Override
+    public RangerResourceMatcher getResourceMatcher(String resourceName) {
+        return allMatchers != null ? allMatchers.get(resourceName) : null;
+    }
+
+    @Override
+    public boolean isMatch(Map<String, RangerPolicyResource> resources, 
Map<String, Object> evalContext) {
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("==> RangerDefaultPolicyResourceMatcher.isMatch(" + 
resources  + ", " + evalContext + ")");
+        }
+
+        boolean ret = isMatch(resources, MatchScope.SELF_OR_ANCESTOR, true, 
evalContext);
+
+
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("<== RangerDefaultPolicyResourceMatcher.isMatch(" + 
resources  + ", " + evalContext + "): " + ret);
+        }
+
+        return ret;
+    }
+
+    @Override
+    public boolean isCompleteMatch(RangerAccessResource resource, Map<String, 
Object> evalContext) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> 
RangerDefaultPolicyResourceMatcher.isCompleteMatch(" + resource + ", " + 
evalContext + ")");
+        }
+
+        boolean            ret          = false;
+        Collection<String> resourceKeys = resource == null ? null : 
resource.getKeys();
+        Collection<String> policyKeys   = policyResources == null ? null : 
policyResources.keySet();
+        boolean            keysMatch    = resourceKeys != null && policyKeys 
!= null && CollectionUtils.isEqualCollection(resourceKeys, policyKeys);
+
+        if (keysMatch) {
+            for (RangerResourceDef resourceDef : serviceDef.getResources()) {
+                String                resourceName  = resourceDef.getName();
+                String                resourceValue = resource == null ? null 
: resource.getValue(resourceName);
+                RangerResourceMatcher matcher       = allMatchers == null ? 
null : allMatchers.get(resourceName);
+
+                if (StringUtils.isEmpty(resourceValue)) {
+                    ret = matcher == null || 
matcher.isCompleteMatch(resourceValue, evalContext);
+                } else {
+                    ret = matcher != null && 
matcher.isCompleteMatch(resourceValue, evalContext);
+                }
+
+                if (!ret) {
+                    break;
+                }
+            }
+        } else {
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("isCompleteMatch(): keysMatch=false. resourceKeys=" 
+ resourceKeys + "; policyKeys=" + policyKeys);
+            }
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== 
RangerDefaultPolicyResourceMatcher.isCompleteMatch(" + resource + ", " + 
evalContext + "): " + ret);
+        }
+
+        return ret;
+    }
+
+    @Override
+    public boolean isCompleteMatch(Map<String, RangerPolicyResource> 
resources, Map<String, Object> evalContext) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> 
RangerDefaultPolicyResourceMatcher.isCompleteMatch(" + resources + ", " + 
evalContext + ")");
+        }
+
+        boolean            ret          = false;
+        Collection<String> resourceKeys = resources == null ? null : 
resources.keySet();
+        Collection<String> policyKeys   = policyResources == null ? null : 
policyResources.keySet();
+        boolean            keysMatch    = resourceKeys != null && policyKeys 
!= null && CollectionUtils.isEqualCollection(resourceKeys, policyKeys);
+
+        if (keysMatch) {
+            for (RangerResourceDef resourceDef : serviceDef.getResources()) {
+                String               resourceName   = resourceDef.getName();
+                RangerPolicyResource resourceValues = resources == null ? null 
: resources.get(resourceName);
+                RangerPolicyResource policyValues   = policyResources == null 
? null : policyResources.get(resourceName);
+
+                if (resourceValues == null || 
CollectionUtils.isEmpty(resourceValues.getValues())) {
+                    ret = (policyValues == null || 
CollectionUtils.isEmpty(policyValues.getValues()));
+                } else if (policyValues != null && 
CollectionUtils.isNotEmpty(policyValues.getValues())) {
+                    ret = 
CollectionUtils.isEqualCollection(resourceValues.getValues(), 
policyValues.getValues());
+                }
+
+                if (!ret) {
+                    break;
+                }
+            }
+        } else {
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("isCompleteMatch(): keysMatch=false. resourceKeys=" 
+ resourceKeys + "; policyKeys=" + policyKeys);
+            }
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== 
RangerDefaultPolicyResourceMatcher.isCompleteMatch(" + resources + ", " + 
evalContext + "): " + ret);
+        }
+
+        return ret;
+    }
+
+    @Override
+    public boolean isMatch(RangerAccessResource resource, Map<String, Object> 
evalContext) {
+        return isMatch(resource, MatchScope.SELF_OR_ANCESTOR, evalContext);
+    }
+
+    @Override
+    public boolean isMatch(RangerPolicy policy, MatchScope scope, Map<String, 
Object> evalContext) {
+        return isMatch(policy.getResources(), scope, false, evalContext);
+    }
+
+    private int getPolicyType() {
+        return policy != null && policy.getPolicyType() != null ? 
policy.getPolicyType() : RangerPolicy.POLICY_TYPE_ACCESS;
+    }
+
+    private Long getPolicyId() {
+        return policy != null ? policy.getId() : null;
+    }
+
+    boolean isMatch(Map<String, RangerPolicyResource> resources, MatchScope 
scope, boolean mustMatchAllPolicyValues, Map<String, Object> evalContext) {
+        boolean ret = false;
+
+        if (MapUtils.isNotEmpty(resources)) {
+            List<RangerResourceDef> hierarchy = 
getMatchingHierarchy(resources.keySet());
+
+            if (CollectionUtils.isNotEmpty(hierarchy)) {
+                MatchType                matchType      = MatchType.NONE;
+                RangerAccessResourceImpl accessResource = new 
RangerAccessResourceImpl();
+
+                accessResource.setServiceDef(serviceDef);
+
+                // Build up accessResource resourceDef by resourceDef.
+                // For each resourceDef,
+                //         examine policy-values one by one.
+                //         The first value that is acceptable, that is,
+                //             value matches in any way, is used for that 
resourceDef, and
+                //            next resourceDef is processed.
+                //         If none of the values matches, the policy as a 
whole definitely will not match,
+                //        therefore, the match is failed
+                // After all resourceDefs are processed, and some match is 
achieved at every
+                // level, the final matchType (which is for the entire policy) 
is checked against
+                // requested scope to determine the match-result.
+
+                // Unit tests in TestDefaultPolicyResourceForPolicy.java, 
test_defaultpolicyresourcematcher_for_policy.json,
+                // test_defaultpolicyresourcematcher_for_hdfs_policy.json, and
+                // 
test_defaultpolicyresourcematcher_for_resource_specific_policy.json
+
+                boolean skipped = false;
+
+                for (RangerResourceDef resourceDef : hierarchy) {
+                    String               name           = 
resourceDef.getName();
+                    RangerPolicyResource policyResource = resources.get(name);
+
+                    if (policyResource != null && 
CollectionUtils.isNotEmpty(policyResource.getValues())) {
+                        ret       = false;
+                        matchType = MatchType.NONE;
+
+                        if (!skipped) {
+                            for (String value : policyResource.getValues()) {
+                                accessResource.setValue(name, value);
+
+                                matchType = getMatchType(accessResource, 
evalContext);
+
+                                if (matchType != MatchType.NONE) { // One 
value for this resourceDef matched
+                                    ret = true;
+
+                                    if (!mustMatchAllPolicyValues) {
+                                        break;
+                                    }
+                                }
+                            }
+                        } else {
+                            break;
+                        }
+                    } else {
+                        skipped = true;
+                    }
+
+                    if (!ret) { // None of the values specified for this 
resourceDef matched, no point in continuing with next resourceDef
+                        break;
+                    }
+                }
+                ret = ret && isMatch(scope, matchType);
+            }
+        }
+
+        return ret;
+    }
+
+    @Override
+    public boolean isMatch(RangerAccessResource resource, MatchScope scope, 
Map<String, Object> evalContext) {
+        MatchType matchType = getMatchType(resource, evalContext);
+        boolean   ret       = isMatch(scope, matchType);
+
+        return ret;
+    }
+
+    @Override
+    public MatchType getMatchType(RangerAccessResource resource, Map<String, 
Object> evalContext) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> RangerDefaultPolicyResourceMatcher.getMatchType(" + 
resource + evalContext + ")");
+        }
+
+        MatchType ret              = MatchType.NONE;
+        int       policyKeysSize   = policyResources == null ? 0 : 
policyResources.size();
+        int       resourceKeysSize = resource == null || resource.getKeys() == 
null ? 0 : resource.getKeys().size();
+
+        if (policyKeysSize == 0 && resourceKeysSize == 0) {
+            ret = MatchType.SELF;
+        } else {
+            List<RangerResourceDef> hierarchy = getMatchingHierarchy(resource);
+            if (CollectionUtils.isNotEmpty(hierarchy)) {
+                int lastNonAnyMatcherIndex = 0;
+                /*
+                 * For hive resource policy:
+                 *     lastNonAnyMatcherIndex will be set to
+                 *         0 : if all matchers in policy are '*'; such as 
database=*, table=*, column=*
+                 *         1 : database=hr, table=*, column=*
+                 *         2 : database=<any>, table=employee, column=*
+                 *         3 : database=<any>, table=<any>, column=ssn
+                */
+                int matchersSize = 0;
+
+                for (RangerResourceDef resourceDef : hierarchy) {
+                    RangerResourceMatcher matcher = 
allMatchers.get(resourceDef.getName());
+                    if (matcher != null) {
+                        matchersSize++;
+                        if (!matcher.isMatchAny()) {
+                            lastNonAnyMatcherIndex = matchersSize;
+                        }
+                    }
+                }
+
+                if (resourceKeysSize == 0 && lastNonAnyMatcherIndex == 0) {
+                    ret = MatchType.SELF;
+                } else if (lastNonAnyMatcherIndex == 0) {
+                    ret = MatchType.ANCESTOR;
+                } else {
+                    int index = 0;
+                    for (RangerResourceDef resourceDef : hierarchy) {
+
+                        String resourceName = resourceDef.getName();
+                        RangerResourceMatcher matcher = 
allMatchers.get(resourceName);
+                        String resourceValue = resource.getValue(resourceName);
+
+                        if (resourceValue != null) {
+                            if (matcher != null) {
+                                index++;
+                                if (matcher.isMatch(resourceValue, 
evalContext)) {
+                                    ret = index == resourceKeysSize && 
matcher.isMatchAny() ? MatchType.ANCESTOR : MatchType.SELF;
+                                } else {
+                                    ret = MatchType.NONE;
+                                    break;
+                                }
+                            } else {
+                                // More resource-levels than matchers
+                                ret = MatchType.ANCESTOR;
+                                break;
+                            }
+                        } else {
+                            if (matcher != null) {
+                                // More matchers than resource-levels
+                                if (index >= lastNonAnyMatcherIndex) {
+                                    // All AnyMatch matchers after this
+                                    ret = MatchType.ANCESTOR;
+                                } else {
+                                    ret = MatchType.DESCENDANT;
+                                }
+                            } else {
+                                // Common part of several possible hierarchies 
matched
+                                if (resourceKeysSize > index) {
+                                    ret = MatchType.ANCESTOR;
+                                }
+                            }
+                            break;
+                        }
+                    }
+                    if (ret == MatchType.SELF && resourceKeysSize > 
matchersSize) {
+                        ret = MatchType.ANCESTOR;
+                    }
+                }
+            }
+
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== RangerDefaultPolicyResourceMatcher.getMatchType(" + 
resource + evalContext + "): " + ret);
+        }
+
+        return ret;
+    }
+
+    private List<RangerResourceDef> getMatchingHierarchy(Set<String> 
resourceKeys) {
+        List<RangerResourceDef> ret = null;
+
+        if (CollectionUtils.isNotEmpty(resourceKeys)) {
+            Set<List<RangerResourceDef>> resourceHierarchies = 
serviceDefHelper == null ? Collections.EMPTY_SET : 
serviceDefHelper.getResourceHierarchies(getPolicyType(), resourceKeys);
+
+            // pick the shortest hierarchy
+            for (List<RangerResourceDef> resourceHierarchy : 
resourceHierarchies) {
+                if (ret == null) {
+                    ret = resourceHierarchy;
+                } else {
+                    if (resourceHierarchy.size() < ret.size()) {
+                        ret = resourceHierarchy;
+                        if (ret.size() == resourceKeys.size()) {
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+
+        return ret;
+    }
+
+    private List<RangerResourceDef> getMatchingHierarchy(RangerAccessResource 
resource) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> 
RangerDefaultPolicyResourceMatcher.getMatchingHierarchy(" + resource + ")");
+        }
+
+        final List<RangerResourceDef> ret;
+
+        Set<String> policyResourcesKeySet = policyResources == null ? 
Collections.EMPTY_SET : policyResources.keySet();
+
+        if (resource != null && resource.getKeys() != null) {
+            List<RangerResourceDef> aValidHierarchy = null;
+
+            if (validResourceHierarchy != null && serviceDefHelper != null) {
+                if 
(serviceDefHelper.hierarchyHasAllResources(validResourceHierarchy, 
resource.getKeys())) {
+                    aValidHierarchy = validResourceHierarchy;
+                }
+            } else {
+                if (policyResourcesKeySet.containsAll(resource.getKeys())) {
+                    aValidHierarchy = 
getMatchingHierarchy(policyResourcesKeySet);
+                } else if 
(resource.getKeys().containsAll(policyResourcesKeySet)) {
+                    aValidHierarchy = getMatchingHierarchy(resource.getKeys());
+                }
+            }
+
+            if (aValidHierarchy != null) {
+                boolean isValid = true;
+                boolean skipped = false;
+
+                for (RangerResourceDef resourceDef : aValidHierarchy) {
+                    String resourceName = resourceDef.getName();
+                    String resourceValue = resource.getValue(resourceName);
+
+                    if (resourceValue == null) {
+                        if (!skipped) {
+                            skipped = true;
+                        }
+                    } else {
+                        if (skipped) {
+                            isValid = false;
+                            break;
+                        }
+                    }
+                }
+
+                if (!isValid) {
+                    aValidHierarchy = null;
+                }
+            }
+
+            ret = aValidHierarchy;
+        } else {
+            ret = getMatchingHierarchy(policyResourcesKeySet);
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== 
RangerDefaultPolicyResourceMatcher.getMatchingHierarchy(" + resource + "): " + 
ret);
+        }
+
+        return ret;
+    }
+
+    private boolean isMatch(final MatchScope scope, final MatchType matchType) 
{
+        final boolean ret;
+        switch (scope) {
+            case SELF_OR_ANCESTOR_OR_DESCENDANT: {
+                ret = matchType != MatchType.NONE;
+                break;
+            }
+            case SELF: {
+                ret = matchType == MatchType.SELF;
+                break;
+            }
+            case SELF_OR_DESCENDANT: {
+                ret = matchType == MatchType.SELF || matchType == 
MatchType.DESCENDANT;
+                break;
+            }
+            case SELF_OR_ANCESTOR: {
+                ret = matchType == MatchType.SELF || matchType == 
MatchType.ANCESTOR;
+                break;
+            }
+            case DESCENDANT: {
+                ret = matchType == MatchType.DESCENDANT;
+                break;
+            }
+            case ANCESTOR: {
+                ret = matchType == MatchType.ANCESTOR;
+                break;
+            }
+            default:
+                ret = matchType != MatchType.NONE;
+                break;
+        }
+        return ret;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+
+        toString(sb);
+
+        return sb.toString();
+    }
+
+    @Override
+    public StringBuilder toString(StringBuilder sb) {
+        sb.append("RangerDefaultPolicyResourceMatcher={");
+
+        sb.append("isInitialized=").append(isInitialized).append(", ");
+
+        sb.append("matchers={");
+        if(allMatchers != null) {
+            for(RangerResourceMatcher matcher : allMatchers.values()) {
+                sb.append("{").append(matcher).append("} ");
+            }
+        }
+        sb.append("} ");
+
+        sb.append("}");
+
+        return sb;
+    }
+
+    protected static RangerResourceMatcher 
createResourceMatcher(RangerResourceDef resourceDef, RangerPolicyResource 
resource) {
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("==> 
RangerDefaultPolicyResourceMatcher.createResourceMatcher(" + resourceDef + ", " 
+ resource + ")");
+        }
+
+        RangerResourceMatcher ret = null;
+
+        if (resourceDef != null) {
+            String resName = resourceDef.getName();
+            String clsName = resourceDef.getMatcher();
+
+            if (!StringUtils.isEmpty(clsName)) {
+                try {
+                    @SuppressWarnings("unchecked")
+                    Class<RangerResourceMatcher> matcherClass = 
(Class<RangerResourceMatcher>) Class.forName(clsName);
+
+                    ret = matcherClass.newInstance();
+                } catch (Exception excp) {
+                    LOG.error("failed to instantiate resource matcher '" + 
clsName + "' for '" + resName + "'. Default resource matcher will be used", 
excp);
+                }
+            }
+
+
+            if (ret == null) {
+                ret = new RangerDefaultResourceMatcher();
+            }
+
+            ret.setResourceDef(resourceDef);
+            ret.setPolicyResource(resource);
+            ret.init();
+        } else {
+            LOG.error("RangerDefaultPolicyResourceMatcher: RangerResourceDef 
is null");
+        }
+
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("<== 
RangerDefaultPolicyResourceMatcher.createResourceMatcher(" + resourceDef + ", " 
+ resource + "): " + ret);
+        }
+
+        return ret;
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/ranger/blob/7985dd47/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBaseService.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBaseService.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBaseService.java
index f1c6b9f..25f9985 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBaseService.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBaseService.java
@@ -25,6 +25,7 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang.StringUtils;
@@ -38,6 +39,7 @@ import org.apache.ranger.plugin.model.RangerService;
 import org.apache.ranger.plugin.model.RangerServiceDef;
 import org.apache.ranger.plugin.model.validation.RangerServiceDefHelper;
 import org.apache.ranger.plugin.resourcematcher.RangerAbstractResourceMatcher;
+import org.apache.ranger.plugin.util.ServiceDefUtil;
 
 
 public abstract class RangerBaseService {
@@ -133,18 +135,6 @@ public abstract class RangerBaseService {
                return ret;
        }
 
-       public List<RangerPolicy.RangerPolicyItemAccess> 
getAndAllowAllAccesses() {
-               List<RangerPolicy.RangerPolicyItemAccess> ret = new 
ArrayList<RangerPolicy.RangerPolicyItemAccess>();
-
-               for (RangerServiceDef.RangerAccessTypeDef accessTypeDef : 
serviceDef.getAccessTypes()) {
-                       RangerPolicy.RangerPolicyItemAccess access = new 
RangerPolicy.RangerPolicyItemAccess();
-                       access.setType(accessTypeDef.getName());
-                       access.setIsAllowed(true);
-                       ret.add(access);
-               }
-               return ret;
-       }
-
        private RangerPolicy 
getDefaultPolicy(List<RangerServiceDef.RangerResourceDef> resourceHierarchy) 
throws Exception {
 
                if (LOG.isDebugEnabled()) {
@@ -165,7 +155,7 @@ public abstract class RangerBaseService {
 
                List<RangerPolicy.RangerPolicyItem> policyItems = new 
ArrayList<RangerPolicy.RangerPolicyItem>();
                //Create Default policy item for the service user
-               RangerPolicy.RangerPolicyItem policyItem = 
createDefaultPolicyItem();
+               RangerPolicy.RangerPolicyItem policyItem = 
createDefaultPolicyItem(policy.getResources());
                policyItems.add(policyItem);
                policy.setPolicyItems(policyItems);
 
@@ -176,7 +166,7 @@ public abstract class RangerBaseService {
                return policy;
        }
 
-       private RangerPolicy.RangerPolicyItem createDefaultPolicyItem() throws 
Exception {
+       private RangerPolicy.RangerPolicyItem 
createDefaultPolicyItem(Map<String, RangerPolicy.RangerPolicyResource> 
policyResources) throws Exception {
 
                if (LOG.isDebugEnabled()) {
                        LOG.debug("==> 
RangerBaseService.createDefaultPolicyItem()");
@@ -185,7 +175,10 @@ public abstract class RangerBaseService {
                RangerPolicy.RangerPolicyItem policyItem = new 
RangerPolicy.RangerPolicyItem();
 
                policyItem.setUsers(getUserList());
-               policyItem.setAccesses(getAndAllowAllAccesses());
+
+               List<RangerPolicy.RangerPolicyItemAccess> accesses = 
getAllowedAccesses(policyResources);
+               policyItem.setAccesses(accesses);
+
                policyItem.setDelegateAdmin(true);
 
                if (LOG.isDebugEnabled()) {
@@ -194,7 +187,29 @@ public abstract class RangerBaseService {
                return policyItem;
        }
 
-       private Map<String, RangerPolicy.RangerPolicyResource> 
createDefaultPolicyResource(List<RangerServiceDef.RangerResourceDef> 
resourceHierarchy) throws Exception {
+       protected List<RangerPolicy.RangerPolicyItemAccess> 
getAllowedAccesses(Map<String, RangerPolicy.RangerPolicyResource> 
policyResources) {
+               List<RangerPolicy.RangerPolicyItemAccess> ret = new 
ArrayList<RangerPolicy.RangerPolicyItemAccess>();
+
+               RangerServiceDef.RangerResourceDef leafResourceDef = 
ServiceDefUtil.getLeafResourceDef(serviceDef, policyResources);
+
+               if (leafResourceDef != null) {
+                       Set<String> accessTypeRestrictions = 
leafResourceDef.getAccessTypeRestrictions();
+
+                       for (RangerServiceDef.RangerAccessTypeDef accessTypeDef 
: serviceDef.getAccessTypes()) {
+                               boolean isAccessTypeAllowed = 
CollectionUtils.isEmpty(accessTypeRestrictions) || 
accessTypeRestrictions.contains(accessTypeDef.getName());;
+
+                               if (isAccessTypeAllowed) {
+                                       RangerPolicy.RangerPolicyItemAccess 
access = new RangerPolicy.RangerPolicyItemAccess();
+                                       access.setType(accessTypeDef.getName());
+                                       access.setIsAllowed(true);
+                                       ret.add(access);
+                               }
+                       }
+               }
+               return ret;
+       }
+
+       protected Map<String, RangerPolicy.RangerPolicyResource> 
createDefaultPolicyResource(List<RangerServiceDef.RangerResourceDef> 
resourceHierarchy) throws Exception {
                if (LOG.isDebugEnabled()) {
                        LOG.debug("==> 
RangerBaseService.createDefaultPolicyResource()");
                }

http://git-wip-us.apache.org/repos/asf/ranger/blob/7985dd47/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerDefaultService.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerDefaultService.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerDefaultService.java
new file mode 100644
index 0000000..c61ebd6
--- /dev/null
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerDefaultService.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.plugin.service;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.collections.ListUtils;
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public class RangerDefaultService extends RangerBaseService {
+       private static final Log LOG = 
LogFactory.getLog(RangerDefaultService.class);
+               
+       @Override
+       public  Map<String, Object> validateConfig() throws Exception {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("RangerDefaultService.validateConfig Service: 
(" + serviceName + " ), returning empty map");
+               }
+               return MapUtils.EMPTY_MAP;
+       }
+       
+       @Override
+       public List<String> lookupResource(ResourceLookupContext context) 
throws Exception {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("RangerDefaultService.lookupResource Context: 
(" + context + "), returning empty list");
+               }
+               return ListUtils.EMPTY_LIST;
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/ranger/blob/7985dd47/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerResourceTrie.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerResourceTrie.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerResourceTrie.java
index 77808b8..f6c1e4d 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerResourceTrie.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerResourceTrie.java
@@ -46,7 +46,6 @@ public class RangerResourceTrie<T extends 
RangerPolicyResourceEvaluator> {
     private final boolean  optWildcard;
     private final String   wildcardChars;
     private final TrieNode root;
-    private final Comparator<T> comparator;
 
     public RangerResourceTrie(RangerServiceDef.RangerResourceDef resourceDef, 
List<T> evaluators) {
         this(resourceDef, evaluators, null);
@@ -78,7 +77,6 @@ public class RangerResourceTrie<T extends 
RangerPolicyResourceEvaluator> {
         this.optWildcard   = 
RangerAbstractResourceMatcher.getOptionWildCard(matcherOptions);
         this.wildcardChars = optWildcard ? DEFAULT_WILDCARD_CHARS + 
tokenReplaceSpecialChars : "" + tokenReplaceSpecialChars;
         this.root          = new TrieNode(Character.valueOf((char)0));
-        this.comparator    = comparator;
 
         for(T evaluator : evaluators) {
             Map<String, RangerPolicyResource> policyResources = 
evaluator.getPolicyResource();

http://git-wip-us.apache.org/repos/asf/ranger/blob/7985dd47/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 b0090d4..f8994a7 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
@@ -94,16 +94,30 @@ public class ServiceDefUtil {
     public static Integer getLeafResourceLevel(RangerServiceDef serviceDef, 
Map<String, RangerPolicy.RangerPolicyResource> policyResource) {
         Integer ret = null;
 
+        RangerResourceDef resourceDef = getLeafResourceDef(serviceDef, 
policyResource);
+
+        if (resourceDef != null) {
+            ret = resourceDef.getLevel();
+        }
+
+        return ret;
+    }
+
+    public static RangerResourceDef getLeafResourceDef(RangerServiceDef 
serviceDef, Map<String, RangerPolicy.RangerPolicyResource> policyResource) {
+        RangerResourceDef ret = null;
+
         if(serviceDef != null && policyResource != null) {
             for(Map.Entry<String, RangerPolicy.RangerPolicyResource> entry : 
policyResource.entrySet()) {
-                String            resource    = entry.getKey();
-                RangerResourceDef resourceDef = 
ServiceDefUtil.getResourceDef(serviceDef, resource);
-
-                if(resourceDef != null && resourceDef.getLevel() != null) {
-                    if(ret == null) {
-                        ret = resourceDef.getLevel();
-                    } else if(ret < resourceDef.getLevel()) {
-                        ret = resourceDef.getLevel();
+                if (!isEmpty(entry.getValue())) {
+                    String            resource    = entry.getKey();
+                    RangerResourceDef resourceDef = 
ServiceDefUtil.getResourceDef(serviceDef, resource);
+
+                    if (resourceDef != null && resourceDef.getLevel() != null) 
{
+                        if (ret == null) {
+                            ret = resourceDef;
+                        } else if(ret.getLevel() < resourceDef.getLevel()) {
+                            ret = resourceDef;
+                        }
                     }
                 }
             }
@@ -112,6 +126,22 @@ public class ServiceDefUtil {
         return ret;
     }
 
+    public static boolean isEmpty(RangerPolicy.RangerPolicyResource 
policyResource) {
+        boolean ret = true;
+        if (policyResource != null) {
+            List<String> resourceValues = policyResource.getValues();
+            if (CollectionUtils.isNotEmpty(resourceValues)) {
+                for (String resourceValue : resourceValues) {
+                    if (StringUtils.isNotBlank(resourceValue)) {
+                        ret = false;
+                        break;
+                    }
+                }
+            }
+        }
+        return ret;
+    }
+
     public static String getOption(Map<String, String> options, String name, 
String defaultValue) {
         String ret = options != null && name != null ? options.get(name) : 
null;
 
@@ -276,6 +306,12 @@ public class ServiceDefUtil {
         if(StringUtils.isNotEmpty(delta.getRbKeyValidationMessage()))
             ret.setRbKeyValidationMessage(delta.getRbKeyValidationMessage());
 
+        if(CollectionUtils.isNotEmpty(delta.getAccessTypeRestrictions()))
+            ret.setAccessTypeRestrictions(delta.getAccessTypeRestrictions());
+
+        if (delta.getIsValidLeaf() != null)
+            ret.setIsValidLeaf(delta.getIsValidLeaf());
+
         return ret;
     }
 

http://git-wip-us.apache.org/repos/asf/ranger/blob/7985dd47/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyValidator.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyValidator.java
 
b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyValidator.java
index 9bfa859..d8a1354 100644
--- 
a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyValidator.java
+++ 
b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyValidator.java
@@ -120,7 +120,7 @@ public class TestRangerPolicyValidator {
                        { "col", false,             true,               false,  
   "col\\d{1,2}", "tbl" },      // valid: col1, col47, etc.; invalid: col, 
col238, col1, etc., excludes == false, recursive == true
                        { "udf", true,              true,               true,   
   null,          "db" }        // same parent as tbl (simulating hive's 
multiple resource hierarchies)
        };
-               
+
        private final Object[][] policyResourceMap_good = new Object[][] {
                        // resource-name, values, excludes, recursive
                        { "db", new String[] { "db1", "db2" }, null, null },
@@ -804,17 +804,17 @@ public class TestRangerPolicyValidator {
                List<RangerResourceDef> resourceDefs = 
_utils.createResourceDefs(resourceDefData_multipleHierarchies);
                when(_serviceDef.getResources()).thenReturn(resourceDefs);
                // setup policy
-               Map<String, RangerPolicyResource> policyResources = 
_utils.createPolicyResourceMap(policyResourceMap_bad);                          
    
+               Map<String, RangerPolicyResource> policyResources = 
_utils.createPolicyResourceMap(policyResourceMap_bad);
                when(_policy.getResources()).thenReturn(policyResources);
                Assert.assertFalse("Missing required resource and unknown 
resource", _validator.isValidResourceNames(_policy, _failures, _serviceDef));
                _utils.checkFailureForSemanticError(_failures, "policy 
resources");
-               
+
                // another bad resource map that straddles multiple hierarchies
                policyResources = 
_utils.createPolicyResourceMap(policyResourceMap_bad_multiple_hierarchies);
                when(_policy.getResources()).thenReturn(policyResources);
                _failures.clear(); Assert.assertFalse("Policy with resources 
for multiple hierarchies", _validator.isValidResourceNames(_policy, _failures, 
_serviceDef));
                _utils.checkFailureForSemanticError(_failures, "policy 
resources", "incompatible");
-               
+
                // another bad policy resource map that could match multiple 
hierarchies but is short on mandatory resources for all of those matches
                policyResources = 
_utils.createPolicyResourceMap(policyResourceMap_bad_multiple_hierarchies_missing_mandatory);
                when(_policy.getResources()).thenReturn(policyResources);

Reply via email to