This is an automated email from the ASF dual-hosted git repository.

madhan pushed a commit to branch ranger-2.4
in repository https://gitbox.apache.org/repos/asf/ranger.git


The following commit(s) were added to refs/heads/ranger-2.4 by this push:
     new 7ec75608e RANGER-4100: Efficient computation of the smallest set of 
evaluators returned by search of multiple Trie trees
7ec75608e is described below

commit 7ec75608e7bcdfe286885fecaf00ea3a8d7a318f
Author: Abhay Kulkarni <[email protected]>
AuthorDate: Mon Feb 20 14:11:05 2023 -0800

    RANGER-4100: Efficient computation of the smallest set of evaluators 
returned by search of multiple Trie trees
    
    (cherry picked from commit 85f5483ed444bf40caa588ec5b788a51532c3095)
---
 .../plugin/contextenricher/RangerTagEnricher.java  |  75 +---------
 .../validation/RangerSecurityZoneValidator.java    |  65 +--------
 .../ranger/plugin/policyengine/PolicyEngine.java   | 111 ++++-----------
 .../util/RangerResourceEvaluatorsRetriever.java    | 158 +++++++++++++++++++++
 .../plugin/policyengine/TestPolicyEngine.java      |   3 +-
 5 files changed, 195 insertions(+), 217 deletions(-)

diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java
index da06e4161..93d1e9d08 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java
@@ -44,6 +44,7 @@ import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
 import org.apache.ranger.plugin.util.RangerCommonConstants;
 import org.apache.ranger.plugin.util.RangerPerfTracer;
 import org.apache.ranger.plugin.util.RangerReadWriteLock;
+import org.apache.ranger.plugin.util.RangerResourceEvaluatorsRetriever;
 import org.apache.ranger.plugin.util.RangerServiceNotFoundException;
 import org.apache.ranger.plugin.util.RangerServiceTagsDeltaUtil;
 import org.apache.ranger.plugin.util.ServiceTags;
@@ -548,7 +549,7 @@ public class RangerTagEnricher extends 
RangerAbstractContextEnricher {
                        RangerAccessRequestImpl  request = new 
RangerAccessRequestImpl();
                        request.setResource(accessResource);
 
-                       List<RangerServiceResourceMatcher> oldMatchers = 
getEvaluators(request, enrichedServiceTags);
+                       Collection<RangerServiceResourceMatcher> oldMatchers = 
getEvaluators(request, enrichedServiceTags);
 
                        if (LOG.isDebugEnabled()) {
                                LOG.debug("Found [" + oldMatchers.size() + "] 
matchers for service-resource[" + serviceResource + "]");
@@ -669,7 +670,7 @@ public class RangerTagEnricher extends 
RangerAbstractContextEnricher {
                        ret = 
enrichedServiceTags.getTagsForEmptyResourceAndAnyAccess();
                } else {
 
-                       final List<RangerServiceResourceMatcher> 
serviceResourceMatchers = getEvaluators(request, enrichedServiceTags);
+                       final Collection<RangerServiceResourceMatcher> 
serviceResourceMatchers = getEvaluators(request, enrichedServiceTags);
 
                        if 
(CollectionUtils.isNotEmpty(serviceResourceMatchers)) {
 
@@ -715,11 +716,11 @@ public class RangerTagEnricher extends 
RangerAbstractContextEnricher {
                return ret;
        }
 
-       private List<RangerServiceResourceMatcher> 
getEvaluators(RangerAccessRequest request, EnrichedServiceTags 
enrichedServiceTags) {
+       private Collection<RangerServiceResourceMatcher> 
getEvaluators(RangerAccessRequest request, EnrichedServiceTags 
enrichedServiceTags) {
                if(LOG.isDebugEnabled()) {
                        LOG.debug("==> 
RangerTagEnricher.getEvaluators(request=" + request + ")");
                }
-               List<RangerServiceResourceMatcher>  ret        = 
Collections.EMPTY_LIST;
+               Collection<RangerServiceResourceMatcher>  ret;
 
                RangerAccessResource                resource   = 
request.getResource();
 
@@ -734,71 +735,7 @@ public class RangerTagEnricher extends 
RangerAbstractContextEnricher {
                                perf = 
RangerPerfTracer.getPerfTracer(PERF_TRIE_OP_LOG, 
"RangerTagEnricher.getEvaluators(resource=" + resource.getAsString() + ")");
                        }
 
-                       List<String>                            resourceKeys = 
serviceDefHelper.getOrderedResourceNames(resource.getKeys());
-                       Set<RangerServiceResourceMatcher>       smallestList = 
null;
-
-                       if (CollectionUtils.isNotEmpty(resourceKeys)) {
-
-                               for (String resourceName : resourceKeys) {
-                                       
RangerResourceTrie<RangerServiceResourceMatcher> trie = 
serviceResourceTrie.get(resourceName);
-
-                                       if (trie == null) { // if no trie 
exists for this resource level, ignore and continue to next level
-                                               continue;
-                                       }
-
-                                       Set<RangerServiceResourceMatcher> 
serviceResourceMatchersForResource = 
trie.getEvaluatorsForResource(resource.getValue(resourceName), 
request.getResourceMatchingScope());
-                                       Set<RangerServiceResourceMatcher> 
inheritedResourceMatchers = trie.getInheritedEvaluators();
-
-                                       if (smallestList != null) {
-                                               if 
(CollectionUtils.isEmpty(inheritedResourceMatchers) && 
CollectionUtils.isEmpty(serviceResourceMatchersForResource)) {
-                                                       smallestList = null;
-                                               } else if 
(CollectionUtils.isEmpty(inheritedResourceMatchers)) {
-                                                       
smallestList.retainAll(serviceResourceMatchersForResource);
-                                               } else if 
(CollectionUtils.isEmpty(serviceResourceMatchersForResource)) {
-                                                       
smallestList.retainAll(inheritedResourceMatchers);
-                                               } else {
-                                                       
Set<RangerServiceResourceMatcher> smaller, bigger;
-                                                       if 
(serviceResourceMatchersForResource.size() < inheritedResourceMatchers.size()) {
-                                                               smaller = 
serviceResourceMatchersForResource;
-                                                               bigger = 
inheritedResourceMatchers;
-                                                       } else {
-                                                               smaller = 
inheritedResourceMatchers;
-                                                               bigger = 
serviceResourceMatchersForResource;
-                                                       }
-                                                       
Set<RangerServiceResourceMatcher> tmp = new HashSet<>();
-                                                       if (smallestList.size() 
< smaller.size()) {
-                                                               
smallestList.stream().filter(smaller::contains).forEach(tmp::add);
-                                                               
smallestList.stream().filter(bigger::contains).forEach(tmp::add);
-                                                       } else {
-                                                               
smaller.stream().filter(smallestList::contains).forEach(tmp::add);
-                                                               if 
(smallestList.size() < bigger.size()) {
-                                                                       
smallestList.stream().filter(bigger::contains).forEach(tmp::add);
-                                                               } else {
-                                                                       
bigger.stream().filter(smallestList::contains).forEach(tmp::add);
-                                                               }
-                                                       }
-                                                       smallestList = tmp;
-                                               }
-                                       } else {
-                                               if 
(CollectionUtils.isEmpty(inheritedResourceMatchers) || 
CollectionUtils.isEmpty(serviceResourceMatchersForResource)) {
-                                                       
Set<RangerServiceResourceMatcher> tmp = 
CollectionUtils.isEmpty(inheritedResourceMatchers) ? 
serviceResourceMatchersForResource : inheritedResourceMatchers;
-                                                       smallestList = 
resourceKeys.size() == 1 || CollectionUtils.isEmpty(tmp) ? tmp : new 
HashSet<>(tmp);
-                                               } else {
-                                                       smallestList = new 
HashSet<>(serviceResourceMatchersForResource);
-                                                       
smallestList.addAll(inheritedResourceMatchers);
-                                               }
-                                       }
-
-                                       if 
(CollectionUtils.isEmpty(smallestList)) {// no tags for this resource, bail out
-                                               smallestList = null;
-                                               break;
-                                       }
-                               }
-                       }
-
-                       if (smallestList != null) {
-                               ret = new ArrayList<>(smallestList);
-                       }
+                       ret = 
RangerResourceEvaluatorsRetriever.getEvaluators(serviceResourceTrie, 
resource.getAsMap(), request.getResourceMatchingScope());
 
                        RangerPerfTracer.logAlways(perf);
                }
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerSecurityZoneValidator.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerSecurityZoneValidator.java
index f1045ad60..ca899979a 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerSecurityZoneValidator.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerSecurityZoneValidator.java
@@ -35,11 +35,13 @@ import 
org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatche
 import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
 import org.apache.ranger.plugin.store.SecurityZoneStore;
 import org.apache.ranger.plugin.store.ServiceStore;
+import org.apache.ranger.plugin.util.RangerResourceEvaluatorsRetriever;
 import org.apache.ranger.plugin.util.SearchFilter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -407,69 +409,12 @@ public class RangerSecurityZoneValidator extends 
RangerValidator {
         //       flag error if there are more than one matching evaluators 
with different zone-ids.
         //
 
-        RangerServiceDefHelper serviceDefHelper = new 
RangerServiceDefHelper(serviceDef, true);
-
         for (RangerSecurityZone zone : zones) {
             List<HashMap<String, List<String>>> resources = 
zone.getServices().get(serviceName).getResources();
 
             for (Map<String, List<String>> resource : resources) {
 
-                Set<RangerZoneResourceMatcher>       smallestList     = null;
-
-                List<String> resourceKeys = 
serviceDefHelper.getOrderedResourceNames(resource.keySet());
-
-                for (String resourceDefName : resourceKeys) {
-                    List<String> resourceValues = 
resource.get(resourceDefName);
-
-                    RangerResourceTrie<RangerZoneResourceMatcher> trie = 
trieMap.get(resourceDefName);
-
-                    Set<RangerZoneResourceMatcher> zoneMatchersForResource = 
trie.getEvaluatorsForResource(resourceValues);
-                    Set<RangerZoneResourceMatcher> inheritedZoneMatchers = 
trie.getInheritedEvaluators();
-
-                    if (LOG.isDebugEnabled()) {
-                        LOG.debug("ResourceDefName:[" + resourceDefName + "], 
values:[" + resourceValues + "], matched-zones:[" + zoneMatchersForResource + 
"], inherited-zones:[" + inheritedZoneMatchers + "]");
-                    }
-
-                    if (smallestList != null) {
-                        if (CollectionUtils.isEmpty(inheritedZoneMatchers) && 
CollectionUtils.isEmpty(zoneMatchersForResource)) {
-                            smallestList = null;
-                        } else if 
(CollectionUtils.isEmpty(inheritedZoneMatchers)) {
-                            smallestList.retainAll(zoneMatchersForResource);
-                        } else if 
(CollectionUtils.isEmpty(zoneMatchersForResource)) {
-                            smallestList.retainAll(inheritedZoneMatchers);
-                        } else {
-                            Set<RangerZoneResourceMatcher> smaller, bigger;
-                            if (zoneMatchersForResource.size() < 
inheritedZoneMatchers.size()) {
-                                smaller = zoneMatchersForResource;
-                                bigger = inheritedZoneMatchers;
-                            } else {
-                                smaller = inheritedZoneMatchers;
-                                bigger = zoneMatchersForResource;
-                            }
-                            Set<RangerZoneResourceMatcher> tmp = new 
HashSet<>();
-                            if (smallestList.size() < smaller.size()) {
-                                
smallestList.stream().filter(smaller::contains).forEach(tmp::add);
-                                
smallestList.stream().filter(bigger::contains).forEach(tmp::add);
-                            } else {
-                                
smaller.stream().filter(smallestList::contains).forEach(tmp::add);
-                                if (smallestList.size() < bigger.size()) {
-                                    
smallestList.stream().filter(bigger::contains).forEach(tmp::add);
-                                } else {
-                                    
bigger.stream().filter(smallestList::contains).forEach(tmp::add);
-                                }
-                            }
-                            smallestList = tmp;
-                        }
-                    } else {
-                        if (CollectionUtils.isEmpty(inheritedZoneMatchers) || 
CollectionUtils.isEmpty(zoneMatchersForResource)) {
-                            Set<RangerZoneResourceMatcher> tmp = 
CollectionUtils.isEmpty(inheritedZoneMatchers) ? zoneMatchersForResource : 
inheritedZoneMatchers;
-                            smallestList = resourceKeys.size() == 1 || 
CollectionUtils.isEmpty(tmp) ? tmp : new HashSet<>(tmp);
-                        } else {
-                            smallestList = new 
HashSet<>(zoneMatchersForResource);
-                            smallestList.addAll(inheritedZoneMatchers);
-                        }
-                    }
-                }
+                Collection<RangerZoneResourceMatcher> smallestList = 
RangerResourceEvaluatorsRetriever.getEvaluators(trieMap, resource);
 
                 if (LOG.isDebugEnabled()) {
                     LOG.debug("Resource:[" + resource +"], matched-zones:[" + 
smallestList +"]");
@@ -479,8 +424,6 @@ public class RangerSecurityZoneValidator extends 
RangerValidator {
                     continue;
                 }
 
-                final Set<RangerZoneResourceMatcher> intersection = 
smallestList;
-
                 RangerAccessResourceImpl accessResource = new 
RangerAccessResourceImpl();
 
                 accessResource.setServiceDef(serviceDef);
@@ -491,7 +434,7 @@ public class RangerSecurityZoneValidator extends 
RangerValidator {
 
                 Set<String> matchedZoneNames = new HashSet<>();
 
-                for (RangerZoneResourceMatcher zoneMatcher : intersection) {
+                for (RangerZoneResourceMatcher zoneMatcher : smallestList) {
                     if (LOG.isDebugEnabled()) {
                         LOG.debug("Trying to match resource:[" + 
accessResource +"] using zoneMatcher:[" + zoneMatcher + "]");
                     }
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEngine.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEngine.java
index f44570623..3864f30d2 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEngine.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEngine.java
@@ -21,6 +21,8 @@ package org.apache.ranger.plugin.policyengine;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -28,14 +30,12 @@ import java.util.Map;
 import java.util.Set;
 
 import org.apache.commons.collections.CollectionUtils;
-import org.apache.commons.collections.ListUtils;
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.ranger.plugin.contextenricher.RangerContextEnricher;
 import org.apache.ranger.plugin.model.RangerPolicy;
 import org.apache.ranger.plugin.model.RangerPolicyDelta;
 import org.apache.ranger.plugin.model.RangerServiceDef;
-import org.apache.ranger.plugin.model.validation.RangerServiceDefHelper;
 import org.apache.ranger.plugin.model.validation.RangerZoneResourceMatcher;
 import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator;
 import 
org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatcher;
@@ -44,6 +44,7 @@ import org.apache.ranger.plugin.service.RangerAuthContext;
 import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
 import org.apache.ranger.plugin.util.RangerPerfTracer;
 import org.apache.ranger.plugin.util.RangerPolicyDeltaUtil;
+import org.apache.ranger.plugin.util.RangerResourceEvaluatorsRetriever;
 import org.apache.ranger.plugin.util.RangerReadWriteLock;
 import org.apache.ranger.plugin.util.RangerRoles;
 import org.apache.ranger.plugin.util.ServicePolicies;
@@ -62,7 +63,7 @@ public class PolicyEngine {
     private final List<RangerContextEnricher>         allContextEnrichers;
     private final RangerPluginContext                 pluginContext;
     private final Map<String, RangerPolicyRepository> zonePolicyRepositories = 
new HashMap<>();
-    private final Map<String, RangerResourceTrie>     resourceZoneTrie = new 
HashMap<>();
+    private final Map<String, RangerResourceTrie<RangerZoneResourceMatcher>>   
  resourceZoneTrie = new HashMap<>();
     private final Map<String, String>                 zoneTagServiceMap = new 
HashMap<>();
     private       boolean                             useForwardedIPAddress;
     private       String[]                            trustedProxyAddresses;
@@ -173,10 +174,10 @@ public class PolicyEngine {
     public List<RangerPolicy> getResourcePolicies(String zoneName) {
         RangerPolicyRepository zoneResourceRepository = 
zonePolicyRepositories.get(zoneName);
 
-        return zoneResourceRepository == null ? ListUtils.EMPTY_LIST : 
zoneResourceRepository.getPolicies();
+        return zoneResourceRepository == null ? Collections.emptyList() : 
zoneResourceRepository.getPolicies();
     }
 
-    Map<String, RangerResourceTrie> getResourceZoneTrie() {
+    Map<String, RangerResourceTrie<RangerZoneResourceMatcher>> 
getResourceZoneTrie() {
         return resourceZoneTrie;
     }
 
@@ -466,101 +467,39 @@ public class PolicyEngine {
         Set<String> ret = null;
 
         if (MapUtils.isNotEmpty(this.resourceZoneTrie)) {
-            Set<RangerZoneResourceMatcher>       smallestList     = null;
-            RangerServiceDefHelper               serviceDefHelper = 
policyRepository.getOptions().getServiceDefHelper();
 
-            List<String> resourceKeys = resource == null ? new ArrayList<>() : 
serviceDefHelper.getOrderedResourceNames(resource.keySet());
-
-            for (String resourceDefName : resourceKeys) {
-                RangerResourceTrie<RangerZoneResourceMatcher> trie = 
resourceZoneTrie.get(resourceDefName);
-
-                if (trie == null) {
-                    continue;
-                }
-
-                Object resourceValues = resource.get(resourceDefName);
-
-                Set<RangerZoneResourceMatcher> zoneMatchersForResource = 
trie.getEvaluatorsForResource(resourceValues);
-                Set<RangerZoneResourceMatcher> inheritedZoneMatchers = 
trie.getInheritedEvaluators();
-
-                if (LOG.isDebugEnabled()) {
-                    LOG.debug("ResourceDefName:[" + resourceDefName + "], 
values:[" + resourceValues + "], matched-zones:[" + zoneMatchersForResource + 
"], inherited-zones:[" + inheritedZoneMatchers + "]");
-                }
-
-                if (smallestList != null) {
-                    if (CollectionUtils.isEmpty(inheritedZoneMatchers) && 
CollectionUtils.isEmpty(zoneMatchersForResource)) {
-                        smallestList = null;
-                    } else if (CollectionUtils.isEmpty(inheritedZoneMatchers)) 
{
-                        smallestList.retainAll(zoneMatchersForResource);
-                    } else if 
(CollectionUtils.isEmpty(zoneMatchersForResource)) {
-                        smallestList.retainAll(inheritedZoneMatchers);
-                    } else {
-                        Set<RangerZoneResourceMatcher> smaller, bigger;
-                        if (zoneMatchersForResource.size() < 
inheritedZoneMatchers.size()) {
-                            smaller = zoneMatchersForResource;
-                            bigger = inheritedZoneMatchers;
-                        } else {
-                            smaller = inheritedZoneMatchers;
-                            bigger = zoneMatchersForResource;
-                        }
-                        Set<RangerZoneResourceMatcher> tmp = new HashSet<>();
-                        if (smallestList.size() < smaller.size()) {
-                            
smallestList.stream().filter(smaller::contains).forEach(tmp::add);
-                            
smallestList.stream().filter(bigger::contains).forEach(tmp::add);
-                        } else {
-                            
smaller.stream().filter(smallestList::contains).forEach(tmp::add);
-                            if (smallestList.size() < bigger.size()) {
-                                
smallestList.stream().filter(bigger::contains).forEach(tmp::add);
-                            } else {
-                                
bigger.stream().filter(smallestList::contains).forEach(tmp::add);
-                            }
-                        }
-                        smallestList = tmp;
-                    }
-                } else {
-                    if (CollectionUtils.isEmpty(inheritedZoneMatchers) || 
CollectionUtils.isEmpty(zoneMatchersForResource)) {
-                        Set<RangerZoneResourceMatcher> tmp = 
CollectionUtils.isEmpty(inheritedZoneMatchers) ? zoneMatchersForResource : 
inheritedZoneMatchers;
-                        smallestList = resourceKeys.size() == 1 || 
CollectionUtils.isEmpty(tmp) ? tmp : new HashSet<>(tmp);
-                    } else {
-                        smallestList = new HashSet<>(zoneMatchersForResource);
-                        smallestList.addAll(inheritedZoneMatchers);
-                    }
-                }
-            }
+            Collection<RangerZoneResourceMatcher> smallestList = 
RangerResourceEvaluatorsRetriever.getEvaluators(resourceZoneTrie, resource);
 
             if (CollectionUtils.isNotEmpty(smallestList)) {
-                final Set<RangerZoneResourceMatcher> intersection = 
smallestList;
 
                 if (LOG.isDebugEnabled()) {
-                    LOG.debug("Resource:[" + resource + "], matched-zones:[" + 
intersection + "]");
+                    LOG.debug("Resource:[" + resource + "], matched-zones:[" + 
smallestList + "]");
                 }
 
-                if (intersection.size() > 0) {
-                    ret = new HashSet<>();
+                ret = new HashSet<>();
 
-                    for (RangerZoneResourceMatcher zoneMatcher : intersection) 
{
+                for (RangerZoneResourceMatcher zoneMatcher : smallestList) {
+                    if (LOG.isDebugEnabled()) {
+                        LOG.debug("Trying to match resource:[" + 
accessResource + "] using zoneMatcher:[" + zoneMatcher + "]");
+                    }
+
+                    // These are potential matches. Try to really match them
+                    if 
(zoneMatcher.getPolicyResourceMatcher().isMatch(accessResource, 
RangerPolicyResourceMatcher.MatchScope.ANY, null)) {
                         if (LOG.isDebugEnabled()) {
-                            LOG.debug("Trying to match resource:[" + 
accessResource + "] using zoneMatcher:[" + zoneMatcher + "]");
+                            LOG.debug("Matched resource:[" + accessResource + 
"] using zoneMatcher:[" + zoneMatcher + "]");
                         }
 
-                        // These are potential matches. Try to really match 
them
-                        if 
(zoneMatcher.getPolicyResourceMatcher().isMatch(accessResource, 
RangerPolicyResourceMatcher.MatchScope.ANY, null)) {
-                            if (LOG.isDebugEnabled()) {
-                                LOG.debug("Matched resource:[" + 
accessResource + "] using zoneMatcher:[" + zoneMatcher + "]");
-                            }
-
-                            // Actual match happened
-                            ret.add(zoneMatcher.getSecurityZoneName());
-                        } else {
-                            if (LOG.isDebugEnabled()) {
-                                LOG.debug("Did not match resource:[" + 
accessResource + "] using zoneMatcher:[" + zoneMatcher + "]");
-                            }
+                        // Actual match happened
+                        ret.add(zoneMatcher.getSecurityZoneName());
+                    } else {
+                        if (LOG.isDebugEnabled()) {
+                            LOG.debug("Did not match resource:[" + 
accessResource + "] using zoneMatcher:[" + zoneMatcher + "]");
                         }
                     }
+                }
 
-                    if (LOG.isDebugEnabled()) {
-                        LOG.debug("The following zone-names matched 
resource:[" + accessResource + "]: " + ret);
-                    }
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("The following zone-names matched resource:[" + 
accessResource + "]: " + ret);
                 }
             }
         }
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerResourceEvaluatorsRetriever.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerResourceEvaluatorsRetriever.java
new file mode 100644
index 000000000..dfe591c59
--- /dev/null
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerResourceEvaluatorsRetriever.java
@@ -0,0 +1,158 @@
+/*
+ * 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.util;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
+import org.apache.ranger.plugin.policyengine.RangerResourceTrie;
+import org.apache.ranger.plugin.policyresourcematcher.RangerResourceEvaluator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class RangerResourceEvaluatorsRetriever {
+    private static final Logger LOG = 
LoggerFactory.getLogger(RangerResourceEvaluatorsRetriever.class);
+
+    public static <T  extends RangerResourceEvaluator> Collection<T> 
getEvaluators(Map<String, RangerResourceTrie<T>> resourceTrie, Map<String, ?> 
resource) {
+        return getEvaluators(resourceTrie, resource, 
RangerAccessRequest.ResourceMatchingScope.SELF);
+    }
+
+    public static <T  extends RangerResourceEvaluator> Collection<T> 
getEvaluators(Map<String, RangerResourceTrie<T>> resourceTrie, Map<String, ?> 
resource, RangerAccessRequest.ResourceMatchingScope scope) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> 
RangerPolicyResourceEvaluatorsRetriever.getEvaluators(" + resource + ")");
+        }
+        Set<T> ret = null;
+
+        if (MapUtils.isNotEmpty(resourceTrie) && 
MapUtils.isNotEmpty(resource)) {
+            Set<String> resourceKeys = resource.keySet();
+
+            List<Evaluators<T>> sortedEvaluators = new 
ArrayList<>(resourceKeys.size());
+
+            for (String resourceDefName : resourceKeys) {
+                RangerResourceTrie<T> trie = resourceTrie.get(resourceDefName);
+
+                if (trie == null) {
+                    continue;
+                }
+
+                Object resourceValues = resource.get(resourceDefName);
+
+                Set<T> inheritedMatchers   = trie.getInheritedEvaluators();
+                Set<T> matchersForResource = 
trie.getEvaluatorsForResource(resourceValues, scope);
+
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("ResourceDefName:[" + resourceDefName + "], 
values:[" + resourceValues + "], resource-matchers:[" + matchersForResource + 
"], inherited-matchers:[" + inheritedMatchers + "]");
+                }
+                if (CollectionUtils.isEmpty(inheritedMatchers) && 
CollectionUtils.isEmpty(matchersForResource)) {
+                    sortedEvaluators.clear();
+                    break;
+                }
+                sortedEvaluators.add(new Evaluators<>(inheritedMatchers, 
matchersForResource));
+            }
+
+            if (CollectionUtils.isNotEmpty(sortedEvaluators)) {
+                Collections.sort(sortedEvaluators);
+
+                ret = sortedEvaluators.remove(0).getMatchers();
+
+                for (Evaluators<T> evaluators : sortedEvaluators) {
+                    if (CollectionUtils.isEmpty(evaluators.inheritedMatchers)) 
{
+                        ret.retainAll(evaluators.resourceMatchers);
+                    } else if 
(CollectionUtils.isEmpty(evaluators.resourceMatchers)) {
+                        ret.retainAll(evaluators.inheritedMatchers);
+                    } else {
+                        Set<T> smaller = evaluators.getSmaller();
+                        Set<T> bigger  = evaluators.getBigger();
+
+                        Set<T> tmp = new HashSet<>(ret.size());
+
+                        if (ret.size() < smaller.size()) {
+                            
ret.stream().filter(smaller::contains).forEach(tmp::add);
+                            
ret.stream().filter(bigger::contains).forEach(tmp::add);
+                        } else {
+                            
smaller.stream().filter(ret::contains).forEach(tmp::add);
+                            if (ret.size() < bigger.size()) {
+                                
ret.stream().filter(bigger::contains).forEach(tmp::add);
+                            } else {
+                                
bigger.stream().filter(ret::contains).forEach(tmp::add);
+                            }
+                        }
+                        ret = tmp;
+                    }
+                    if (ret.isEmpty()) {
+                        break;
+                    }
+                }
+            }
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> RangerResourceEvaluatorsRetriever.getEvaluators(" + 
resource + ") : evaluator:[" + ret + "]");
+        }
+        return ret;
+    }
+
+    static class Evaluators<T> implements Comparable<Evaluators<T>> {
+        private final Set<T> inheritedMatchers;
+        private final Set<T> resourceMatchers;
+        private final Set<T> smaller;
+        private final Set<T> bigger;
+        private final int    size;
+
+        Evaluators(Set<T> inherited, Set<T> matched) {
+            inheritedMatchers = inherited == null ? Collections.emptySet() : 
inherited;
+            resourceMatchers  = matched   == null ? Collections.emptySet() : 
matched;
+            size              = inheritedMatchers.size() + 
resourceMatchers.size();
+            smaller           = inheritedMatchers.size() < 
resourceMatchers.size() ? inheritedMatchers : resourceMatchers;
+            bigger            = smaller == inheritedMatchers ? 
resourceMatchers : inheritedMatchers;
+        }
+
+        // Should be called at most once
+        Set<T> getMatchers() {
+            Set<T> ret = new HashSet<>(size);
+
+            ret.addAll(inheritedMatchers);
+            ret.addAll(resourceMatchers);
+
+            return ret;
+        }
+
+        Set<T> getSmaller() {
+            return smaller;
+        }
+
+        Set<T> getBigger() {
+            return bigger;
+        }
+
+        @Override
+        public int compareTo(Evaluators<T> other) {
+            return Integer.compare(size, other.size);
+        }
+    }
+}
diff --git 
a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java
 
b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java
index eb3d0ff46..632d7cf7e 100644
--- 
a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java
+++ 
b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java
@@ -44,6 +44,7 @@ import org.apache.ranger.plugin.model.RangerServiceDef;
 import org.apache.ranger.plugin.model.RangerServiceResource;
 import org.apache.ranger.plugin.model.RangerValiditySchedule;
 import 
org.apache.ranger.plugin.model.validation.RangerValidityScheduleValidator;
+import org.apache.ranger.plugin.model.validation.RangerZoneResourceMatcher;
 import org.apache.ranger.plugin.model.validation.ValidationFailureDetails;
 import 
org.apache.ranger.plugin.policyengine.TestPolicyEngine.PolicyEngineTestCase.TestData;
 import 
org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator.RangerPolicyResourceEvaluator;
@@ -958,7 +959,7 @@ public class TestPolicyEngine {
                        ret = Objects.equals(me.getResourceZoneTrie().keySet(), 
other.getResourceZoneTrie().keySet());
 
                        if (ret) {
-                               for (Map.Entry<String, RangerResourceTrie> 
entry : me.getResourceZoneTrie().entrySet()) {
+                               for (Map.Entry<String, 
RangerResourceTrie<RangerZoneResourceMatcher>> entry : 
me.getResourceZoneTrie().entrySet()) {
                                        ret = compareSubtree(entry.getValue(), 
other.getResourceZoneTrie().get(entry.getKey()));
 
                                        if (!ret) {

Reply via email to