Repository: incubator-ranger
Updated Branches:
  refs/heads/master d4f2eb20f -> 2e0be82df


RANGER-307: Policy evaluation optimization: reorder policies and short-circuit 
evaluation


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

Branch: refs/heads/master
Commit: 2e0be82df973a6f37e766b7e9fff2b41431d0db1
Parents: d4f2eb2
Author: Abhay Kulkarni <[email protected]>
Authored: Fri Mar 13 19:50:19 2015 -0700
Committer: Madhan Neethiraj <[email protected]>
Committed: Fri Mar 13 19:50:19 2015 -0700

----------------------------------------------------------------------
 .../ranger/plugin/policyengine/CacheMap.java    |  40 +++
 .../plugin/policyengine/RangerAccessData.java   |  39 +++
 .../plugin/policyengine/RangerAccessResult.java |  32 ++-
 .../policyengine/RangerPolicyEngineImpl.java    | 149 ++---------
 .../RangerPolicyEvaluatorFacade.java            | 128 ++++++++++
 .../policyengine/RangerPolicyRepository.java    | 231 +++++++++++++++++
 .../RangerDefaultPolicyEvaluator.java           | 223 ++++++++++-------
 .../RangerOptimizedPolicyEvaluator.java         | 247 +++++++++++++++++++
 .../RangerDefaultPolicyEvaluatorTest.java       |   8 +-
 .../policyengine/test_policyengine_hdfs.json    |   2 +-
 pom.xml                                         |   2 +-
 src/main/assembly/ranger-src.xml                |  83 ++++---
 12 files changed, 913 insertions(+), 271 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2e0be82d/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/CacheMap.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/CacheMap.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/CacheMap.java
new file mode 100644
index 0000000..0a1566c
--- /dev/null
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/CacheMap.java
@@ -0,0 +1,40 @@
+/*
+ * 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.policyengine;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+
+public class CacheMap<K, V> extends LinkedHashMap<K, V> {
+    private static final float RANGER_CACHE_DEFAULT_LOAD_FACTOR = 0.75f;
+
+    protected int maxCapacity;
+
+    public CacheMap(int maxCapacity) {
+        super(maxCapacity, CacheMap.RANGER_CACHE_DEFAULT_LOAD_FACTOR, true); 
// true for access-order
+
+        this.maxCapacity = maxCapacity;
+    }
+
+    @Override
+    protected boolean removeEldestEntry(Map.Entry eldest) {
+        return size() > maxCapacity;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2e0be82d/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessData.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessData.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessData.java
new file mode 100644
index 0000000..34f7428
--- /dev/null
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessData.java
@@ -0,0 +1,39 @@
+/*
+ * 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.policyengine;
+
+
+public class RangerAccessData<T> {
+    private String accessFDN    = null;
+    private T accessDetails    = null;
+
+    public RangerAccessData(String accessFDN) {
+        this.accessFDN = accessFDN;
+    }
+    public String getAccessFDN() {
+        return accessFDN;
+    }
+    public T getAccessDetails() {
+        return accessDetails;
+    }
+    public void setAccessDetails(T accessDetails) {
+        this.accessDetails = accessDetails;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2e0be82d/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessResult.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessResult.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessResult.java
index 2eaec16..3a1fa1d 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessResult.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessResult.java
@@ -27,23 +27,23 @@ public class RangerAccessResult {
        private RangerServiceDef    serviceDef  = null;
        private RangerAccessRequest request     = null;
 
+       private boolean isAccessDetermined = false;
        private boolean  isAllowed = false;
+       private boolean isAuditedDetermined = false;
        private boolean  isAudited = false;
        private long     policyId  = -1;
        private String   reason    = null;
 
        public RangerAccessResult(String serviceName, RangerServiceDef 
serviceDef, RangerAccessRequest request) {
-               this(serviceName, serviceDef, request, false, false, -1, null);
-       }
-
-       public RangerAccessResult(String serviceName, RangerServiceDef 
serviceDef, RangerAccessRequest request, boolean isAllowed, boolean isAudited, 
long policyId, String reason) {
                this.serviceName = serviceName;
                this.serviceDef  = serviceDef;
                this.request     = request;
-               this.isAllowed   = isAllowed;
-               this.isAudited   = isAudited;
-               this.policyId    = policyId;
-               this.reason      = reason;
+               this.isAccessDetermined = false;
+               this.isAllowed   = false;
+               this.isAuditedDetermined = false;
+               this.isAudited   = false;
+               this.policyId    = -1;
+               this.reason      = null;
        }
 
        /**
@@ -67,6 +67,10 @@ public class RangerAccessResult {
                return request;
        }
 
+       public boolean getIsAccessDetermined() { return isAccessDetermined; }
+
+       private void setIsAccessDetermined(boolean value) { isAccessDetermined 
= value; }
+
        /**
         * @return the isAllowed
         */
@@ -78,6 +82,7 @@ public class RangerAccessResult {
         * @param isAllowed the isAllowed to set
         */
        public void setIsAllowed(boolean isAllowed) {
+               setIsAccessDetermined(true);
                this.isAllowed = isAllowed;
        }
 
@@ -87,6 +92,10 @@ public class RangerAccessResult {
        public void setReason(String reason) {
                this.reason = reason;
        }
+
+       public boolean getIsAuditedDetermined() { return isAuditedDetermined; }
+
+       private void setIsAuditedDetermined(boolean value) { 
isAuditedDetermined = value; }
        
        /**
         * @return the isAudited
@@ -95,10 +104,13 @@ public class RangerAccessResult {
                return isAudited;
        }
 
+
+
        /**
         * @param isAudited the isAudited to set
         */
        public void setIsAudited(boolean isAudited) {
+               setIsAuditedDetermined(true);
                this.isAudited = isAudited;
        }
 
@@ -145,8 +157,10 @@ public class RangerAccessResult {
        public StringBuilder toString(StringBuilder sb) {
                sb.append("RangerAccessResult={");
 
+        sb.append("isAccessDetermined={").append(isAccessDetermined).append("} 
");
                sb.append("isAllowed={").append(isAllowed).append("} ");
-               sb.append("isAudited={").append(isAudited).append("} ");
+        
sb.append("isAuditedDetermined={").append(isAuditedDetermined).append("} ");
+        sb.append("isAudited={").append(isAudited).append("} ");
                sb.append("policyId={").append(policyId).append("} ");
                sb.append("reason={").append(reason).append("} ");
 

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2e0be82d/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
index 51787ac..abae1fe 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
@@ -19,31 +19,25 @@
 
 package org.apache.ranger.plugin.policyengine;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import org.apache.commons.collections.CollectionUtils;
-import org.apache.commons.lang.StringUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.ranger.plugin.audit.RangerAuditHandler;
 import org.apache.ranger.plugin.contextenricher.RangerContextEnricher;
 import org.apache.ranger.plugin.model.RangerPolicy;
 import org.apache.ranger.plugin.model.RangerServiceDef;
-import 
org.apache.ranger.plugin.model.RangerServiceDef.RangerContextEnricherDef;
-import org.apache.ranger.plugin.policyevaluator.RangerDefaultPolicyEvaluator;
 import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
 
 public class RangerPolicyEngineImpl implements RangerPolicyEngine {
        private static final Log LOG = 
LogFactory.getLog(RangerPolicyEngineImpl.class);
 
-       private String                      serviceName         = null;
-       private RangerServiceDef            serviceDef          = null;
-       private List<RangerContextEnricher> contextEnrichers    = null;
-       private List<RangerPolicyEvaluator> policyEvaluators    = null;
-       private RangerAuditHandler          defaultAuditHandler = null;
+       private String                 serviceName         = null;
+       private RangerPolicyRepository policyRepository    = null;
+       private RangerAuditHandler     defaultAuditHandler = null;
 
 
        public RangerPolicyEngineImpl() {
@@ -63,12 +57,13 @@ public class RangerPolicyEngineImpl implements 
RangerPolicyEngine {
 
        @Override
        public RangerServiceDef getServiceDef() {
-               return serviceDef;
+               return policyRepository == null ? null : 
policyRepository.getServiceDef();
        }
 
        @Override
        public List<RangerContextEnricher> getContextEnrichers() {
-               return contextEnrichers;
+
+               return policyRepository == null ? null : getContextEnrichers();
        }
 
        @Override
@@ -77,51 +72,12 @@ public class RangerPolicyEngineImpl implements 
RangerPolicyEngine {
                        LOG.debug("==> RangerPolicyEngineImpl.setPolicies(" + 
serviceName + ", " + serviceDef + ", policies.count=" + (policies == null ? 0 : 
policies.size()) + ")");
                }
 
-               if(serviceName != null && serviceDef != null && policies != 
null) {
-                       List<RangerContextEnricher> contextEnrichers = new 
ArrayList<RangerContextEnricher>();
-
-                       
if(!CollectionUtils.isEmpty(serviceDef.getContextEnrichers())) {
-                               for(RangerContextEnricherDef enricherDef : 
serviceDef.getContextEnrichers()) {
-                                       if(enricherDef == null) {
-                                               continue;
-                                       }
-                                       
-                                       RangerContextEnricher contextEnricher = 
getContextEnricher(enricherDef);
-                                       
-                                       contextEnrichers.add(contextEnricher);
-                               }
-                       }
-
-                       List<RangerPolicyEvaluator> evaluators = new 
ArrayList<RangerPolicyEvaluator>();
-
-                       for(RangerPolicy policy : policies) {
-                               if(! policy.getIsEnabled()) {
-                                       continue;
-                               }
-
-                               RangerPolicyEvaluator evaluator = 
getPolicyEvaluator(policy, serviceDef);
-
-                               if(evaluator != null) {
-                                       evaluators.add(evaluator);
-                               }
-                       }
-
-                       /* TODO:
-                        *  sort evaluators list for faster completion of 
isAccessAllowed() method
-                        *   1. Global policies: the policies that cover for 
any resource (for example: database=*; table=*; column=*)
-                        *   2. Policies that cover all resources under level-1 
(for example: every thing in one or more databases)
-                        *   3. Policies that cover all resources under level-2 
(for example: every thing in one or more tables)
-                        *   ...
-                        *   4. Policies that cover all resources under level-n 
(for example: one or more columns)
-                        * 
-                        */
-
-                       this.serviceName      = serviceName;
-                       this.serviceDef       = serviceDef;
-                       this.contextEnrichers = contextEnrichers;
-                       this.policyEvaluators = evaluators;
+               if (serviceName != null && serviceDef != null && policies != 
null) {
+                       policyRepository = new 
RangerPolicyRepository(serviceName);
+                       policyRepository.init(serviceDef, policies);
+                       this.serviceName = serviceName;
                } else {
-                       LOG.error("RangerPolicyEngineImpl.setPolicies(): 
invalid arguments - null serviceDef/policies");
+                       LOG.error("RangerPolicyEngineImpl.setPolicies ->Invalid 
arguments: serviceName, serviceDef, or policies is null");
                }
 
                if(LOG.isDebugEnabled()) {
@@ -141,7 +97,7 @@ public class RangerPolicyEngineImpl implements 
RangerPolicyEngine {
 
        @Override
        public RangerAccessResult createAccessResult(RangerAccessRequest 
request) {
-               return new RangerAccessResult(serviceName, serviceDef, 
request);        
+               return policyRepository == null ? null : new 
RangerAccessResult(serviceName, policyRepository.getServiceDef(), request);
        }
 
        @Override
@@ -207,73 +163,26 @@ public class RangerPolicyEngineImpl implements 
RangerPolicyEngine {
 
                RangerAccessResult ret = createAccessResult(request);
 
-               if(request != null) {
-                       List<RangerPolicyEvaluator> evaluators = 
policyEvaluators;
+               if(policyRepository != null && ret != null && request != null) {
+                       List<RangerPolicyEvaluatorFacade> evaluators = 
policyRepository.getPolicyEvaluators();
 
                        if(evaluators != null) {
+                               policyRepository.retrieveAuditEnabled(request, 
ret);
                                for(RangerPolicyEvaluator evaluator : 
evaluators) {
                                        evaluator.evaluate(request, ret);
 
-                                       // stop once allowed=true && 
audited==true
-                                       if(ret.getIsAllowed() && 
ret.getIsAudited()) {
+                                       // stop once allowed==true && 
auditedDetermined==true
+                                       if(ret.getIsAccessDetermined() && 
ret.getIsAuditedDetermined()) {
                                                break;
                                        }
                                }
-                       }
-               }
+                               policyRepository.storeAuditEnabled(request, 
ret);
 
-               if(LOG.isDebugEnabled()) {
-                       LOG.debug("<== 
RangerPolicyEngineImpl.isAccessAllowedNoAudit(" + request + "): " + ret);
-               }
-
-               return ret;
-       }
-
-       private RangerContextEnricher 
getContextEnricher(RangerContextEnricherDef enricherDef) {
-               if(LOG.isDebugEnabled()) {
-                       LOG.debug("==> 
RangerPolicyEngineImpl.getContextEnricher(" + enricherDef + ")");
-               }
-
-               RangerContextEnricher ret = null;
-
-               String name    = enricherDef != null ? enricherDef.getName()    
 : null;
-               String clsName = enricherDef != null ? 
enricherDef.getEnricher() : null;
-
-               if(! StringUtils.isEmpty(clsName)) {
-                       try {
-                               @SuppressWarnings("unchecked")
-                               Class<RangerContextEnricher> enricherClass = 
(Class<RangerContextEnricher>)Class.forName(clsName);
-
-                               ret = enricherClass.newInstance();
-                       } catch(Exception excp) {
-                               LOG.error("failed to instantiate context 
enricher '" + clsName + "' for '" + name + "'", excp);
                        }
                }
 
-               if(ret != null) {
-                       ret.init(enricherDef);
-               }
-
                if(LOG.isDebugEnabled()) {
-                       LOG.debug("<== 
RangerPolicyEngineImpl.getContextEnricher(" + enricherDef + "): " + ret);
-               }
-
-               return ret;
-       }
-
-       private RangerPolicyEvaluator getPolicyEvaluator(RangerPolicy policy, 
RangerServiceDef serviceDef) {
-               if(LOG.isDebugEnabled()) {
-                       LOG.debug("==> 
RangerPolicyEngineImpl.getPolicyEvaluator(" + policy + "," + serviceDef + ")");
-               }
-
-               RangerPolicyEvaluator ret = null;
-
-               ret = new RangerDefaultPolicyEvaluator(); // TODO: configurable 
evaluator class?
-
-               ret.init(policy, serviceDef);
-
-               if(LOG.isDebugEnabled()) {
-                       LOG.debug("<== 
RangerPolicyEngineImpl.getPolicyEvaluator(" + policy + "," + serviceDef + "): " 
+ ret);
+                       LOG.debug("<== 
RangerPolicyEngineImpl.isAccessAllowedNoAudit(" + request + "): " + ret);
                }
 
                return ret;
@@ -292,17 +201,7 @@ public class RangerPolicyEngineImpl implements 
RangerPolicyEngine {
                sb.append("RangerPolicyEngineImpl={");
 
                sb.append("serviceName={").append(serviceName).append("} ");
-               sb.append("serviceDef={").append(serviceDef).append("} ");
-
-               sb.append("policyEvaluators={");
-               if(policyEvaluators != null) {
-                       for(RangerPolicyEvaluator policyEvaluator : 
policyEvaluators) {
-                               if(policyEvaluator != null) {
-                                       sb.append(policyEvaluator).append(" ");
-                               }
-                       }
-               }
-               sb.append("} ");
+               sb.append(policyRepository);
 
                sb.append("}");
 

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2e0be82d/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEvaluatorFacade.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEvaluatorFacade.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEvaluatorFacade.java
new file mode 100644
index 0000000..5c30df3
--- /dev/null
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEvaluatorFacade.java
@@ -0,0 +1,128 @@
+/*
+ * 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.policyengine;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.conditionevaluator.RangerConditionEvaluator;
+import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.policyevaluator.RangerDefaultPolicyEvaluator;
+import org.apache.ranger.plugin.policyevaluator.RangerOptimizedPolicyEvaluator;
+import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator;
+
+import java.util.Map;
+
+public class RangerPolicyEvaluatorFacade implements RangerPolicyEvaluator, 
Comparable<RangerPolicyEvaluatorFacade> {
+    private static final Log LOG = 
LogFactory.getLog(RangerPolicyEvaluatorFacade.class);
+
+    RangerDefaultPolicyEvaluator delegate  =   null;
+    int computedPriority            =   0;
+    boolean useCachePolicyEngine         = false;
+
+    RangerPolicyEvaluatorFacade(boolean useCachePolicyEngine) {
+        super();
+        this.useCachePolicyEngine = useCachePolicyEngine;
+        delegate = new RangerOptimizedPolicyEvaluator();
+    }
+
+    RangerPolicyEvaluator getPolicyEvaluator() {
+        return delegate;
+    }
+
+    @Override
+    public void init(RangerPolicy policy, RangerServiceDef serviceDef) {
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("==> RangerPolicyEvaluatorFacade.init(), 
useCachePolicyEngine:" + useCachePolicyEngine);
+        }
+        delegate.init(policy, serviceDef);
+        computedPriority = computePriority();
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("<== RangerPolicyEvaluatorFacade.init(), 
useCachePolicyEngine:" + useCachePolicyEngine);
+        }
+    }
+
+    @Override
+    public RangerPolicy getPolicy() {
+        return delegate.getPolicy();
+    }
+
+    @Override
+    public RangerServiceDef getServiceDef() {
+        return delegate.getServiceDef();
+    }
+
+    @Override
+    public void evaluate(RangerAccessRequest request, RangerAccessResult 
result) {
+        delegate.evaluate(request, result);
+    }
+
+    @Override
+    public boolean isMatch(RangerResource resource) {
+        return false;
+    }
+
+    @Override
+    public boolean isSingleAndExactMatch(RangerResource resource) {
+        return false;
+    }
+
+    @Override
+    public int compareTo(RangerPolicyEvaluatorFacade other) {
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("==> RangerPolicyEvaluatorFacade.compareTo()");
+        }
+        int result;
+
+        if (this.getComputedPriority() == other.getComputedPriority()) {
+            Map<String, RangerConditionEvaluator> myConditionEvaluators = 
this.delegate.getConditionEvaluators();
+            Map<String, RangerConditionEvaluator> otherConditionEvaluators = 
other.delegate.getConditionEvaluators();
+
+            int myConditionEvaluatorCount = myConditionEvaluators == null ? 0 
: myConditionEvaluators.size();
+            int otherConditionEvaluatorCount = otherConditionEvaluators == 
null ? 0 : otherConditionEvaluators.size();
+
+            result = Integer.compare(myConditionEvaluatorCount, 
otherConditionEvaluatorCount);
+        } else {
+            int myComputedPriority = this.getComputedPriority();
+            int otherComputedPriority = other.getComputedPriority();
+            result = Integer.compare(myComputedPriority, 
otherComputedPriority);
+        }
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("<== RangerPolicyEvaluatorFacade.compareTo(), result:" + 
result);
+        }
+
+        return result;
+    }
+
+    private int getComputedPriority() {
+        return computedPriority;
+    }
+
+    private int computePriority() {
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("==> RangerPolicyEvaluatorFacade.computePriority()");
+        }
+        int result = delegate.computePriority();
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("<==RangerPolicyEvaluatorFacade.computePriority(), 
result:" + result);
+        }
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2e0be82d/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java
new file mode 100644
index 0000000..700b3ad
--- /dev/null
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java
@@ -0,0 +1,231 @@
+/*
+ * 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.policyengine;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.authorization.hadoop.config.RangerConfiguration;
+import org.apache.ranger.plugin.contextenricher.RangerContextEnricher;
+import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+public class RangerPolicyRepository {
+    private static final Log LOG = 
LogFactory.getLog(RangerPolicyRepository.class);
+
+    private String serviceName                               = null;
+    private List<RangerPolicyEvaluatorFacade> policyEvaluators  = null;
+    private List<RangerContextEnricher> contextEnrichers        = null;
+    private RangerServiceDef serviceDef                         = null;
+    // Not used at this time
+    private boolean useCachePolicyEngine                                = 
false;
+    private Map<String, RangerAccessData<Boolean>> accessAuditCache     = null;
+
+    private static int RANGER_POLICYENGINE_AUDITRESULT_CACHE_SIZE = 64*1024;
+
+    RangerPolicyRepository(String serviceName) {
+        super();
+        this.serviceName = serviceName;
+    }
+    String getRepositoryName() {
+        return serviceName;
+    }
+    List<RangerPolicyEvaluatorFacade> getPolicyEvaluators() {
+        return policyEvaluators;
+    }
+    List<RangerContextEnricher> getContextEnrichers() {
+        return contextEnrichers;
+    }
+    RangerServiceDef getServiceDef() {
+        return serviceDef;
+    }
+
+    void init(RangerServiceDef serviceDef, List<RangerPolicy> policies) {
+
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("==> RangerPolicyRepository.init(" + serviceDef + ", 
policies.count=" + (policies == null ? 0 : policies.size()) + ")");
+        }
+
+        this.serviceDef = serviceDef;
+
+        contextEnrichers = new ArrayList<RangerContextEnricher>();
+
+        if (!CollectionUtils.isEmpty(serviceDef.getContextEnrichers())) {
+            for (RangerServiceDef.RangerContextEnricherDef enricherDef : 
serviceDef.getContextEnrichers()) {
+                if (enricherDef == null) {
+                    continue;
+                }
+
+                RangerContextEnricher contextEnricher = 
buildContextEnricher(enricherDef);
+
+                contextEnrichers.add(contextEnricher);
+            }
+        }
+
+        policyEvaluators = new ArrayList<RangerPolicyEvaluatorFacade>();
+
+        for (RangerPolicy policy : policies) {
+            if (!policy.getIsEnabled()) {
+                continue;
+            }
+
+            RangerPolicyEvaluatorFacade evaluator = 
buildPolicyEvaluator(policy, serviceDef);
+
+            if (evaluator != null) {
+                policyEvaluators.add(evaluator);
+            }
+
+            Collections.sort(policyEvaluators);
+
+        }
+
+        String propertyName = "ranger.plugin." + serviceName + 
".policyengine.auditcachesize";
+
+        int auditResultCacheSize = 
RangerConfiguration.getInstance().getInt(propertyName, 
RANGER_POLICYENGINE_AUDITRESULT_CACHE_SIZE);
+
+        accessAuditCache = new CacheMap<String, 
RangerAccessData<Boolean>>(auditResultCacheSize);
+
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("<== RangerPolicyRepository.init(" + serviceDef + ", 
policies.count=" + (policies == null ? 0 : policies.size()) + ")");
+        }
+    }
+
+    private RangerContextEnricher 
buildContextEnricher(RangerServiceDef.RangerContextEnricherDef enricherDef) {
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("==> RangerPolicyRepository.buildContextEnricher(" + 
enricherDef + ")");
+        }
+
+        RangerContextEnricher ret = null;
+
+        String name    = enricherDef != null ? enricherDef.getName()     : 
null;
+        String clsName = enricherDef != null ? enricherDef.getEnricher() : 
null;
+
+        if(! StringUtils.isEmpty(clsName)) {
+            try {
+                @SuppressWarnings("unchecked")
+                Class<RangerContextEnricher> enricherClass = 
(Class<RangerContextEnricher>)Class.forName(clsName);
+
+                ret = enricherClass.newInstance();
+            } catch(Exception excp) {
+                LOG.error("failed to instantiate context enricher '" + clsName 
+ "' for '" + name + "'", excp);
+            }
+        }
+
+        if(ret != null) {
+            ret.init(enricherDef);
+        }
+
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("<== RangerPolicyRepository.buildContextEnricher(" + 
enricherDef + "): " + ret);
+        }
+        return ret;
+    }
+
+    private RangerPolicyEvaluatorFacade buildPolicyEvaluator(RangerPolicy 
policy, RangerServiceDef serviceDef) {
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("==> RangerPolicyRepository.buildPolicyEvaluator(" + 
policy + "," + serviceDef + ")");
+        }
+
+        RangerPolicyEvaluatorFacade ret = null;
+
+        ret = new RangerPolicyEvaluatorFacade(useCachePolicyEngine);
+        ret.init(policy, serviceDef);
+
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("<== RangerPolicyRepository.buildPolicyEvaluator(" + 
policy + "," + serviceDef + "): " + ret);
+        }
+        return ret;
+    }
+
+    synchronized void retrieveAuditEnabled(RangerAccessRequest request, 
RangerAccessResult ret) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> RangerPolicyRepository.retrieveAuditEnabled()");
+        }
+        RangerAccessData<Boolean> value = 
accessAuditCache.get(request.getResource().toString());
+        if ((value != null)) {
+            ret.setIsAudited(value.getAccessDetails());
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== RangerPolicyRepository.retrieveAuditEnabled()");
+        }
+    }
+
+    synchronized void storeAuditEnabled(RangerAccessRequest request, 
RangerAccessResult ret) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> RangerPolicyRepository.storeAuditEnabled()");
+        }
+        RangerAccessData<Boolean> lookup = 
accessAuditCache.get(request.getResource().toString());
+        if ((lookup == null && ret.getIsAuditedDetermined() == true)) {
+            RangerAccessData<Boolean> value = new 
RangerAccessData<Boolean>(request.toString());
+            value.setAccessDetails(ret.getIsAudited());
+            accessAuditCache.put(request.getResource().toString(), value);
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== RangerPolicyRepository.storeAuditEnabled()");
+        }
+    }
+
+    @Override
+    public String toString( ) {
+        StringBuilder sb = new StringBuilder();
+
+        toString(sb);
+
+        return sb.toString();
+    }
+
+    public StringBuilder toString(StringBuilder sb) {
+
+        sb.append("RangerPolicyRepository={");
+
+        sb.append("serviceName={").append(serviceName).append("} ");
+        sb.append("serviceDef={").append(serviceDef).append("} ");
+        sb.append("policyEvaluators={");
+        if (policyEvaluators != null) {
+            for (RangerPolicyEvaluator policyEvaluator : policyEvaluators) {
+                if (policyEvaluator != null) {
+                    sb.append(policyEvaluator).append(" ");
+                }
+            }
+        }
+        if (contextEnrichers != null) {
+            for (RangerContextEnricher contextEnricher : contextEnrichers) {
+                if (contextEnricher != null) {
+                    sb.append(contextEnricher).append(" ");
+                }
+            }
+        }
+        
sb.append("useCachePolicyEngine={").append(useCachePolicyEngine).append("} ");
+
+        sb.append("} ");
+
+        return sb;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2e0be82d/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
index 0ac5eed..30b36fa 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
@@ -19,13 +19,7 @@
 
 package org.apache.ranger.plugin.policyevaluator;
 
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-
+import com.google.common.base.Strings;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.logging.Log;
@@ -47,7 +41,7 @@ import org.apache.ranger.plugin.policyengine.RangerResource;
 import org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher;
 import org.apache.ranger.plugin.resourcematcher.RangerResourceMatcher;
 
-import com.google.common.base.Strings;
+import java.util.*;
 
 
 public class RangerDefaultPolicyEvaluator extends 
RangerAbstractPolicyEvaluator {
@@ -92,7 +86,13 @@ public class RangerDefaultPolicyEvaluator extends 
RangerAbstractPolicyEvaluator
                }
        }
 
-       /**
+    public Map<String, RangerConditionEvaluator> getConditionEvaluators() {
+        return conditionEvaluators;
+    }
+    public int computePriority() { return 0;}
+
+
+    /**
         * Non-private only for testability.
         * @param policy
         * @param serviceDef
@@ -129,7 +129,7 @@ public class RangerDefaultPolicyEvaluator extends 
RangerAbstractPolicyEvaluator
                                                        if 
(Strings.isNullOrEmpty(evaluatorClassName)) {
                                                                
LOG.error("initializeConditionEvaluators: Serious Configuration error: Couldn't 
get condition evaluator class name for condition[" + conditionName + "]!  
Disabling all checks for this condition.");
                                                        } else {
-                                                               
RangerConditionEvaluator anEvaluator = newConditionEvauator(evaluatorClassName);
+                                                               
RangerConditionEvaluator anEvaluator = 
newConditionEvaluator(evaluatorClassName);
                                                                if (anEvaluator 
== null) {
                                                                        
LOG.error("initializeConditionEvaluators: Serious Configuration error: Couldn't 
instantiate condition evaluator for class[" + evaluatorClassName + "].  All 
checks for condition[" + conditionName + "] disabled.");
                                                                } else {
@@ -179,9 +179,9 @@ public class RangerDefaultPolicyEvaluator extends 
RangerAbstractPolicyEvaluator
                return result;
        }
 
-       RangerConditionEvaluator newConditionEvauator(String className) {
+       RangerConditionEvaluator newConditionEvaluator(String className) {
                if(LOG.isDebugEnabled()) {
-                       LOG.debug(String.format("==> 
RangerDefaultPolicyEvaluator.newConditionEvauator(%s)", className));
+                       LOG.debug(String.format("==> 
RangerDefaultPolicyEvaluator.newConditionEvaluator(%s)", className));
                }
 
                RangerConditionEvaluator evaluator = null;
@@ -195,92 +195,135 @@ public class RangerDefaultPolicyEvaluator extends 
RangerAbstractPolicyEvaluator
                }
        
                if(LOG.isDebugEnabled()) {
-                       LOG.debug(String.format("<== 
RangerDefaultPolicyEvaluator.newConditionEvauator(%s)", evaluator == null ? 
null : evaluator.toString()));
+                       LOG.debug(String.format("<== 
RangerDefaultPolicyEvaluator.newConditionEvaluator(%s)", evaluator == null ? 
null : evaluator.toString()));
                }
                return evaluator;
        }
 
        @Override
-       public void evaluate(RangerAccessRequest request, RangerAccessResult 
result) {
-               if(LOG.isDebugEnabled()) {
-                       LOG.debug("==> RangerDefaultPolicyEvaluator.evaluate(" 
+ request + ", " + result + ")");
-               }
-
-               RangerPolicy policy = getPolicy();
-
-               if(policy != null && request != null && result != null) {
-                       boolean isResourceMatch     = 
isMatch(request.getResource());
-                       boolean isResourceHeadMatch = isResourceMatch || 
matchResourceHead(request.getResource());
-                       String  accessType          = request.getAccessType();
-
-                       if(StringUtils.isEmpty(accessType)) {
-                               accessType = RangerPolicyEngine.ANY_ACCESS;
-                       }
-
-                       boolean isAnyAccess   = StringUtils.equals(accessType, 
RangerPolicyEngine.ANY_ACCESS);
-                       boolean isAdminAccess = StringUtils.equals(accessType, 
RangerPolicyEngine.ADMIN_ACCESS);
-
-                       if(isResourceMatch || (isResourceHeadMatch && 
isAnyAccess)) {
-                               if(policy.getIsAuditEnabled()) {
-                                       result.setIsAudited(true);
-                               }
-
-                               for(RangerPolicyItem policyItem : 
policy.getPolicyItems()) {
-                                       if(isAdminAccess) {
-                                               
if(policyItem.getDelegateAdmin()) {
-                                                       
result.setIsAllowed(true);
-                                                       
result.setPolicyId(policy.getId());
-                                                       break;
-                                               }
-
-                                               continue;
-                                       }
-
-                                       
if(CollectionUtils.isEmpty(policyItem.getAccesses())) {
-                                               continue;
-                                       }
-
-                                       boolean isUserGroupMatch = 
matchUserGroup(policyItem, request.getUser(), request.getUserGroups());
-
-                                       if(! isUserGroupMatch) {
-                                               continue;
-                                       }
-
-                                       boolean isCustomConditionsMatch = 
matchCustomConditions(policyItem, request, conditionEvaluators);
-
-                                       if(! isCustomConditionsMatch) {
-                                               continue;
-                                       }
-
-                                       if(isAnyAccess) {
-                                               for(RangerPolicyItemAccess 
access : policyItem.getAccesses()) {
-                                                       
if(access.getIsAllowed()) {
-                                                               
result.setIsAllowed(true);
-                                                               
result.setPolicyId(policy.getId());
-                                                               break;
-                                                       }
-                                               }
-                                       } else {
-                                               RangerPolicyItemAccess access = 
getAccess(policyItem, accessType);
-
-                                               if(access != null && 
access.getIsAllowed()) {
-                                                       
result.setIsAllowed(true);
-                                                       
result.setPolicyId(policy.getId());
-                                               }
-                                       }
-
-                                       if(result.getIsAllowed()) {
-                                               break;
-                                       }
-                               }
-                       }
-               }
-
-               if(LOG.isDebugEnabled()) {
+    public void evaluate(RangerAccessRequest request, RangerAccessResult 
result) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> RangerDefaultPolicyEvaluator.evaluate(" + request + 
", " + result + ")");
+        }
+        RangerPolicy policy = getPolicy();
+
+        if (policy != null && request != null && result != null) {
+
+            String accessType = request.getAccessType();
+            if (StringUtils.isEmpty(accessType)) {
+                accessType = RangerPolicyEngine.ANY_ACCESS;
+            }
+            boolean isAnyAccess = StringUtils.equals(accessType, 
RangerPolicyEngine.ANY_ACCESS);
+
+            boolean isMatchAttempted = false;
+            boolean matchResult = false;
+            boolean headMatchResult = false;
+
+            if (!result.getIsAuditedDetermined()) {
+                // Need to match request.resource first. If it matches (or 
head matches), then only more progress can be made
+                matchResult = isMatch(request.getResource());
+                isMatchAttempted = true;
+
+                if (matchResult) {
+                    // Do all stuff.
+                    if (policy.getIsAuditEnabled()) {
+                        result.setIsAudited(true);
+                    }
+                }
+            }
+
+            if (!result.getIsAccessDetermined()) {
+                if (!isMatchAttempted) {
+                    // Need to match request.resource first. If it matches (or 
head matches), then only more progress can be made
+                    matchResult = isMatch(request.getResource());
+                    isMatchAttempted = true;
+                }
+
+                // Try head match only if it is useful
+                if (isAnyAccess) {
+                    headMatchResult = matchResult || 
matchResourceHead(request.getResource());
+                }
+
+                if (matchResult || (isAnyAccess && headMatchResult)) {
+                    // A match was found earlier
+                    evaluatePolicyItemsForAccess(request, result);
+                }
+            }
+        }
+
+        if(LOG.isDebugEnabled()) {
                        LOG.debug("<== RangerDefaultPolicyEvaluator.evaluate(" 
+ request + ", " + result + ")");
                }
        }
 
+    protected void evaluatePolicyItemsForAccess(RangerAccessRequest request, 
RangerAccessResult result) {
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("==> 
RangerDefaultPolicyEvaluator.evaluatePolicyItemsForAccess()");
+        }
+        String accessType = request.getAccessType();
+        if (StringUtils.isEmpty(accessType)) {
+            accessType = RangerPolicyEngine.ANY_ACCESS;
+        }
+        boolean isAnyAccess = StringUtils.equals(accessType, 
RangerPolicyEngine.ANY_ACCESS);
+        boolean isAdminAccess = StringUtils.equals(accessType, 
RangerPolicyEngine.ADMIN_ACCESS);
+
+        for (RangerPolicy.RangerPolicyItem policyItem : 
getPolicy().getPolicyItems()) {
+
+            boolean isUserGroupMatch = matchUserGroup(policyItem, 
request.getUser(), request.getUserGroups());
+
+            if (!isUserGroupMatch) {
+                continue;
+            }
+            // This is only for Grant and Revoke access requests sent by the 
component. For those cases
+            // Our plugin will fill in the accessType as ADMIN_ACCESS.
+
+            if (isAdminAccess) {
+                if (policyItem.getDelegateAdmin()) {
+                    result.setIsAllowed(true);
+                    result.setPolicyId(getPolicy().getId());
+                    break;
+                }
+                continue;
+            }
+
+            if (CollectionUtils.isEmpty(policyItem.getAccesses())) {
+                continue;
+            }
+
+            boolean accessAllowed = false;
+            if (isAnyAccess) {
+                for (RangerPolicy.RangerPolicyItemAccess access : 
policyItem.getAccesses()) {
+                    if (access.getIsAllowed()) {
+                        accessAllowed = true;
+                        break;
+                    }
+                }
+            } else {
+                RangerPolicy.RangerPolicyItemAccess access = 
getAccess(policyItem, accessType);
+
+                if (access != null && access.getIsAllowed()) {
+                    accessAllowed = true;
+                }
+            }
+            if (accessAllowed == false) {
+                continue;
+            }
+
+            boolean isCustomConditionsMatch = 
matchCustomConditions(policyItem, request, getConditionEvaluators());
+
+            if (!isCustomConditionsMatch) {
+                continue;
+            }
+
+            result.setIsAllowed(true);
+            result.setPolicyId(getPolicy().getId());
+            break;
+        }
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("<== 
RangerDefaultPolicyEvaluator.evaluatePolicyItemsForAccess()");
+        }
+    }
+
        @Override
        public boolean isMatch(RangerResource resource) {
                if(LOG.isDebugEnabled()) {
@@ -554,7 +597,7 @@ public class RangerDefaultPolicyEvaluator extends 
RangerAbstractPolicyEvaluator
                }
 
                if(LOG.isDebugEnabled()) {
-                       LOG.debug("==> 
RangerDefaultPolicyEvaluator.createResourceMatcher(" + resourceDef + ", " + 
resource + "): " + ret);
+                       LOG.debug("<== 
RangerDefaultPolicyEvaluator.createResourceMatcher(" + resourceDef + ", " + 
resource + "): " + ret);
                }
 
                return ret;

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2e0be82d/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java
new file mode 100644
index 0000000..59fb87c
--- /dev/null
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java
@@ -0,0 +1,247 @@
+/*
+ * 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.policyevaluator;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
+import org.apache.ranger.plugin.policyengine.RangerAccessResult;
+import org.apache.ranger.plugin.policyengine.RangerPolicyEngine;
+
+import java.util.*;
+import java.lang.Math;
+
+public class RangerOptimizedPolicyEvaluator extends 
RangerDefaultPolicyEvaluator {
+    private static final Log LOG = 
LogFactory.getLog(RangerOptimizedPolicyEvaluator.class);
+
+    private Set<String> groups         = null;
+    private Set<String> users          = null;
+    private Set<String> accessPerms    = null;
+    private boolean     delegateAdmin  = false;
+    private boolean     hasAllPerms    = false;
+    private boolean     hasPublicGroup = false;
+
+
+    // For computation of priority
+    private static final String RANGER_POLICY_EVAL_MATCH_ANY_PATTERN_STRING    
               = "*";
+    private static final String RANGER_POLICY_EVAL_MATCH_ONE_CHARACTER_STRING  
               = "?";
+    private static final int RANGER_POLICY_EVAL_MATCH_ANY_WILDCARD_PREMIUM     
               = 25;
+    private static final int 
RANGER_POLICY_EVAL_CONTAINS_MATCH_ANY_WILDCARD_PREMIUM           = 10;
+    private static final int 
RANGER_POLICY_EVAL_CONTAINS_MATCH_ONE_CHARACTER_WILDCARD_PREMIUM = 10;
+    private static final int RANGER_POLICY_EVAL_HAS_EXCLUDES_PREMIUM           
               = 25;
+    private static final int RANGER_POLICY_EVAL_IS_RECURSIVE_PREMIUM           
               = 25;
+    private static final int RANGER_POLICY_EVAL_PUBLIC_GROUP_ACCESS_PREMIUM    
               = 25;
+    private static final int RANGER_POLICY_EVAL_ALL_ACCESS_TYPES_PREMIUM       
               = 25;
+    private static final int RANGER_POLICY_EVAL_RESERVED_SLOTS_NUMBER          
               = 10000;
+    private static final int 
RANGER_POLICY_EVAL_RESERVED_SLOTS_PER_LEVEL_NUMBER               = 1000;
+
+    @Override
+    public void init(RangerPolicy policy, RangerServiceDef serviceDef) {
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("==> RangerOptimizedPolicyEvaluator.init()");
+        }
+
+        super.init(policy, serviceDef);
+
+        accessPerms = new HashSet<String>();
+        groups = new HashSet<String>();
+        users = new HashSet<String>();
+
+        for (RangerPolicy.RangerPolicyItem item : policy.getPolicyItems()) {
+            delegateAdmin = delegateAdmin || item.getDelegateAdmin();
+
+            List<RangerPolicy.RangerPolicyItemAccess> policyItemAccesses = 
item.getAccesses();
+            for(RangerPolicy.RangerPolicyItemAccess policyItemAccess : 
policyItemAccesses) {
+
+                if (policyItemAccess.getIsAllowed()) {
+                    String accessType = policyItemAccess.getType();
+                    accessPerms.add(accessType);
+                }
+            }
+
+            groups.addAll(item.getGroups());
+            users.addAll(item.getUsers());
+        }
+
+        hasAllPerms = checkIfHasAllPerms();
+
+        for (String group : groups) {
+            if (group.equalsIgnoreCase(RangerPolicyEngine.GROUP_PUBLIC)) {
+                hasPublicGroup = true;
+            }
+        }
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("<== RangerOptimizedPolicyEvaluator.init()");
+        }
+    }
+
+    @Override
+    public int computePriority() {
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("==> RangerOptimizedPolicyEvaluator.computePriority()");
+        }
+        RangerServiceDef serviceDef = getServiceDef();
+        RangerPolicy policy = getPolicy();
+
+        class LevelResourceNames implements Comparable<LevelResourceNames> {
+            int level;
+            RangerPolicy.RangerPolicyResource policyResource;
+
+            @Override
+            public int compareTo(LevelResourceNames other) {
+                // Sort in ascending order of level numbers
+                return Integer.compare(this.level, other.level);
+            }
+        }
+        List<LevelResourceNames> tmpList = new ArrayList<LevelResourceNames>();
+
+        List<RangerServiceDef.RangerResourceDef> resourceDefs = 
serviceDef.getResources();
+
+        for (Map.Entry<String, RangerPolicy.RangerPolicyResource> keyValuePair 
: policy.getResources().entrySet()) {
+            String serviceDefResourceName = keyValuePair.getKey();
+            RangerPolicy.RangerPolicyResource policyResource = 
keyValuePair.getValue();
+            List<String> policyResourceNames = policyResource.getValues();
+
+            RangerServiceDef.RangerResourceDef found = null;
+            for (RangerServiceDef.RangerResourceDef resourceDef : 
resourceDefs) {
+                if (serviceDefResourceName.equals(resourceDef.getName())) {
+                    found = resourceDef;
+                    break;
+                }
+            }
+            if (found != null) {
+                int level = found.getLevel();
+                if (policyResourceNames != null) {
+                    LevelResourceNames item = new LevelResourceNames();
+                    item.level = level;
+                    item.policyResource = policyResource;
+                    tmpList.add(item);
+                }
+
+            }
+
+        }
+        Collections.sort(tmpList); // Sort in ascending order of levels
+
+        CharSequence matchesAnySeq = 
RANGER_POLICY_EVAL_MATCH_ANY_PATTERN_STRING.subSequence(0, 1);
+        CharSequence matchesSingleCharacterSeq = 
RANGER_POLICY_EVAL_MATCH_ONE_CHARACTER_STRING.subSequence(0, 1);
+
+        int priorityLevel = RANGER_POLICY_EVAL_RESERVED_SLOTS_NUMBER;
+        boolean seenFirstMatchAny = false;
+
+        for (LevelResourceNames item : tmpList) {
+            // Expect lowest level first
+            List<String> resourceNames = item.policyResource.getValues();
+            boolean foundStarWildcard = false;
+            boolean foundQuestionWildcard = false;
+            boolean foundMatchAny = false;
+
+            for (String resourceName : resourceNames) {
+                if (resourceName.isEmpty() 
||resourceName.equals(RANGER_POLICY_EVAL_MATCH_ANY_PATTERN_STRING)) {
+                    foundMatchAny = true;
+                    break;
+                }
+                if (resourceName.contains(matchesAnySeq))
+                    foundStarWildcard = true;
+                else if (resourceName.contains(matchesSingleCharacterSeq))
+                    foundQuestionWildcard = true;
+            }
+            if (foundMatchAny) {
+                if (seenFirstMatchAny)
+                    priorityLevel -= 
RANGER_POLICY_EVAL_MATCH_ANY_WILDCARD_PREMIUM;
+                else {
+                    seenFirstMatchAny = true;
+                }
+            } else {
+                priorityLevel +=  
RANGER_POLICY_EVAL_RESERVED_SLOTS_PER_LEVEL_NUMBER;
+                if (foundStarWildcard) priorityLevel -= 
RANGER_POLICY_EVAL_CONTAINS_MATCH_ANY_WILDCARD_PREMIUM;
+                else if (foundQuestionWildcard) priorityLevel -= 
RANGER_POLICY_EVAL_CONTAINS_MATCH_ONE_CHARACTER_WILDCARD_PREMIUM;
+
+                RangerPolicy.RangerPolicyResource resource = 
item.policyResource;
+                if (resource.getIsExcludes()) priorityLevel -= 
RANGER_POLICY_EVAL_HAS_EXCLUDES_PREMIUM;
+                if (resource.getIsRecursive()) priorityLevel -= 
RANGER_POLICY_EVAL_IS_RECURSIVE_PREMIUM;
+            }
+        }
+
+        if (hasPublicGroup) {
+            priorityLevel -= RANGER_POLICY_EVAL_PUBLIC_GROUP_ACCESS_PREMIUM;
+        } else {
+            priorityLevel -= groups.size();
+        }
+        priorityLevel -= users.size();
+
+        priorityLevel -= 
Math.round(((float)RANGER_POLICY_EVAL_ALL_ACCESS_TYPES_PREMIUM * 
accessPerms.size()) / serviceDef.getAccessTypes().size());
+
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("<== RangerOptimizedPolicyEvaluator.computePriority(), 
policyName:" + policy.getName() + ", priority:" + priorityLevel);
+        }
+        return priorityLevel;
+    }
+    @Override
+    protected void evaluatePolicyItemsForAccess(RangerAccessRequest request, 
RangerAccessResult result) {
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("==> 
RangerOptimizedPolicyEvaluator.evaluatePolicyItemsForAccess()");
+        }
+        String accessType = request.getAccessType();
+        if (StringUtils.isEmpty(accessType)) {
+            accessType = RangerPolicyEngine.ANY_ACCESS;
+        }
+        boolean isAnyAccess = StringUtils.equals(accessType, 
RangerPolicyEngine.ANY_ACCESS);
+        boolean isAdminAccess = StringUtils.equals(accessType, 
RangerPolicyEngine.ADMIN_ACCESS);
+
+        if (hasPublicGroup || users.contains(request.getUser()) || 
CollectionUtils.containsAny(groups, request.getUserGroups())) {
+            // No need to reject based on users and groups
+
+            if (isAnyAccess || (isAdminAccess && delegateAdmin) || hasAllPerms 
|| accessPerms.contains(accessType)) {
+                // No need to reject based on aggregated access permissions
+                super.evaluatePolicyItemsForAccess(request, result);
+            }
+        }
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("<== 
RangerOptimizedPolicyEvaluator.evaluatePolicyItemsForAccess()");
+        }
+
+    }
+    private boolean checkIfHasAllPerms() {
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("==> 
RangerOptimizedPolicyEvaluator.checkIfHasAllPerms()");
+        }
+
+        boolean result = true;
+
+        List<RangerServiceDef.RangerAccessTypeDef> serviceAccessTypes = 
getServiceDef().getAccessTypes();
+        for (RangerServiceDef.RangerAccessTypeDef serviceAccessType : 
serviceAccessTypes) {
+            if(! accessPerms.contains(serviceAccessType.getName())) {
+                return false;
+            }
+        }
+
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("==> 
RangerOptimizedPolicyEvaluator.checkIfHasAllPerms(), " + result);
+        }
+
+        return result;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2e0be82d/agents-common/src/test/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluatorTest.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/test/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluatorTest.java
 
b/agents-common/src/test/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluatorTest.java
index 9256995..9efbcaf 100644
--- 
a/agents-common/src/test/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluatorTest.java
+++ 
b/agents-common/src/test/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluatorTest.java
@@ -59,15 +59,15 @@ public class RangerDefaultPolicyEvaluatorTest {
        }
 
        @Test
-       public void test_newConditionEvauator() {
+       public void test_newConditionEvaulator() {
                RangerDefaultPolicyEvaluator evaluator = new 
RangerDefaultPolicyEvaluator();
-               RangerConditionEvaluator ipMatcher = 
evaluator.newConditionEvauator("org.apache.ranger.plugin.conditionevaluator.RangerIpMatcher");
+               RangerConditionEvaluator ipMatcher = 
evaluator.newConditionEvaluator("org.apache.ranger.plugin.conditionevaluator.RangerIpMatcher");
                assertTrue(ipMatcher.getClass().equals(RangerIpMatcher.class));
                
                // bogus value will lead to null object from coming back
-               ipMatcher = 
evaluator.newConditionEvauator("org.apache.ranger.plugin.conditionevaluator.RangerIpMatcha");
+               ipMatcher = 
evaluator.newConditionEvaluator("org.apache.ranger.plugin.conditionevaluator.RangerIpMatcha");
                assertNull(ipMatcher);
-               ipMatcher = evaluator.newConditionEvauator("RangerIpMatcher");
+               ipMatcher = evaluator.newConditionEvaluator("RangerIpMatcher");
                assertNull(ipMatcher);
        }
        

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2e0be82d/agents-common/src/test/resources/policyengine/test_policyengine_hdfs.json
----------------------------------------------------------------------
diff --git 
a/agents-common/src/test/resources/policyengine/test_policyengine_hdfs.json 
b/agents-common/src/test/resources/policyengine/test_policyengine_hdfs.json
index 943fe80..2acf868 100644
--- a/agents-common/src/test/resources/policyengine/test_policyengine_hdfs.json
+++ b/agents-common/src/test/resources/policyengine/test_policyengine_hdfs.json
@@ -23,7 +23,7 @@
     }
     ,
     {"id":2,"name":"allow-read-to-all under 
/public/","isEnabled":true,"isAuditEnabled":false,
-     "resources":{"path":{"values":["/public/"],"isRecursive":true}},
+     "resources":{"path":{"values":["/public/*"],"isRecursive":true}},
      "policyItems":[
        
{"accesses":[{"type":"read","isAllowed":true},{"type":"execute","isAllowed":true}],"users":[],"groups":["public"],"delegateAdmin":false}
      ]

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2e0be82d/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 7df033d..fe340c4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -333,9 +333,9 @@
              <descriptor>src/main/assembly/plugin-yarn.xml</descriptor>
              <descriptor>src/main/assembly/admin-web.xml</descriptor>
              <descriptor>src/main/assembly/usersync.xml</descriptor>
-             <descriptor>src/main/assembly/ranger-src.xml</descriptor>
              <descriptor>src/main/assembly/migration-util.xml</descriptor>
              <descriptor>src/main/assembly/kms.xml</descriptor>
+             <descriptor>src/main/assembly/ranger-src.xml</descriptor>
            </descriptors>
          </configuration>
       </plugin>

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2e0be82d/src/main/assembly/ranger-src.xml
----------------------------------------------------------------------
diff --git a/src/main/assembly/ranger-src.xml b/src/main/assembly/ranger-src.xml
index cf6b1da..077fa42 100644
--- a/src/main/assembly/ranger-src.xml
+++ b/src/main/assembly/ranger-src.xml
@@ -16,45 +16,46 @@
   limitations under the License.
 -->
 <assembly>
-  <id>src</id>
-  <formats>
-     <format>tar.gz</format>
-     <format>zip</format>
-  </formats>
-  <baseDirectory>${project.name}-${project.version}-src</baseDirectory>
-  <includeBaseDirectory>true</includeBaseDirectory>
-  <fileSets>
-    <fileSet>
-      <directory>.</directory>
-      <includes>
-        <include>LICENCE.txt</include>
-        <include>README.txt</include>
-        <include>NOTICE.txt</include>
-       <include>DISCLAIMER.txt</include>
-      </includes>
-    </fileSet>
-    <fileSet>
-      <directory>.</directory>
-      <useDefaultExcludes>true</useDefaultExcludes>
-      <excludes>
-        <exclude>.git/**</exclude>
-        <exclude>**/.gitignore</exclude>
-        <exclude>**/.svn</exclude>
-        <exclude>**/*.iws</exclude>
-        <exclude>**/*.ipr</exclude>
-        <exclude>**/*.iml</exclude>
-        <exclude>**/.classpath</exclude>
-        <exclude>**/.project</exclude>
-        <exclude>**/.settings</exclude>
-        <exclude>**/target/**</exclude>
-        <!-- until the code that does this is fixed -->
-        <exclude>**/*.log</exclude>
-        <exclude>**/build/**</exclude>
-        <exclude>**/file:/**</exclude>
-       <exclude>**/debugfiles.list</exclude>
-       <exclude>**/debuglinks.list</exclude>
-       <exclude>**/debugsources.list</exclude>
-      </excludes>
-    </fileSet>
-  </fileSets>
+    <id>src</id>
+    <formats>
+        <format>tar.gz</format>
+        <format>zip</format>
+    </formats>
+    <baseDirectory>${project.name}-${project.version}-src</baseDirectory>
+    <includeBaseDirectory>true</includeBaseDirectory>
+    <fileSets>
+        <fileSet>
+            <directory>.</directory>
+            <includes>
+                <include>LICENCE.txt</include>
+                <include>README.txt</include>
+                <include>NOTICE.txt</include>
+                <include>DISCLAIMER.txt</include>
+            </includes>
+            <useDefaultExcludes>true</useDefaultExcludes>
+        </fileSet>
+        <fileSet>
+            <directory>.</directory>
+            <excludes>
+                <exclude>.git/**</exclude>
+                <exclude>**/.gitignore</exclude>
+                <exclude>**/.svn</exclude>
+                <exclude>**/*.iws</exclude>
+                <exclude>**/*.ipr</exclude>
+                <exclude>**/*.iml</exclude>
+                <exclude>**/.classpath</exclude>
+                <exclude>**/.project</exclude>
+                <exclude>**/.settings</exclude>
+                <exclude>**/target/**</exclude>
+                <exclude>.idea/**</exclude>
+                <!-- until the code that does this is fixed -->
+                <exclude>**/*.log</exclude>
+                <exclude>**/build/**</exclude>
+                <exclude>**/file:/**</exclude>
+                <exclude>**/debugfiles.list</exclude>
+                <exclude>**/debuglinks.list</exclude>
+                <exclude>**/debugsources.list</exclude>
+            </excludes>
+        </fileSet>
+    </fileSets>
 </assembly>

Reply via email to