ranger-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mad...@apache.org
Subject incubator-ranger git commit: RANGER-307: Policy evaluation optimization: reorder policies and short-circuit evaluation
Date Sat, 14 Mar 2015 02:50:45 GMT
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 <akulkarni@hortonworks.com>
Authored: Fri Mar 13 19:50:19 2015 -0700
Committer: Madhan Neethiraj <madhan@apache.org>
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>


Mime
View raw message