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

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


The following commit(s) were added to refs/heads/ranger-2.8 by this push:
     new 80225d4f3 RANGER-5324: replace iterations with streams in 
RangerRequestScriptEvaluator
80225d4f3 is described below

commit 80225d4f330e04d30fee63636efd2a4f14e66b71
Author: Madhan Neethiraj <[email protected]>
AuthorDate: Tue Sep 16 12:40:31 2025 -0700

    RANGER-5324: replace iterations with streams in RangerRequestScriptEvaluator
    
    (cherry picked from commit b34f856715b01abd77ee226386009c5d1104e910)
---
 .../policyengine/RangerRequestScriptEvaluator.java | 2188 ++++++++++----------
 1 file changed, 1052 insertions(+), 1136 deletions(-)

diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerRequestScriptEvaluator.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerRequestScriptEvaluator.java
index 5bd36e22c..4b9ff23d1 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerRequestScriptEvaluator.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerRequestScriptEvaluator.java
@@ -20,1391 +20,1307 @@
 package org.apache.ranger.plugin.policyengine;
 
 import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.ranger.authorization.utils.JsonUtils;
 import org.apache.ranger.authorization.utils.StringUtil;
 import org.apache.ranger.plugin.contextenricher.RangerTagForEval;
+import org.apache.ranger.plugin.util.JavaScriptEdits;
 import org.apache.ranger.plugin.util.MacroProcessor;
 import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
 import org.apache.ranger.plugin.util.RangerPerfTracer;
 import org.apache.ranger.plugin.util.RangerTimeRangeChecker;
 import org.apache.ranger.plugin.util.RangerUserStore;
-import org.apache.ranger.plugin.util.JavaScriptEdits;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import javax.script.Bindings;
 import javax.script.ScriptEngine;
 import javax.script.ScriptException;
+
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.Date;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.TimeZone;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-
-import static org.apache.ranger.plugin.util.RangerCommonConstants.*;
-
+import java.util.stream.Collectors;
+
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD_ACCESS_TIME;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD_ACCESS_TYPE;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD_ACTION;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD_CLIENT_IP_ADDRESS;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD_CLIENT_TYPE;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD_CLUSTER_NAME;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD_CLUSTER_TYPE;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD_FORWARDED_ADDRESSES;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD_REMOTE_IP_ADDRESS;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD_REQUEST;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD_REQUEST_DATA;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD_RESOURCE;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD_RESOURCE_MATCHING_SCOPE;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD_TAG;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD_TAGS;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD_TAG_NAMES;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD_UGA;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD_USER;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD_USER_ATTRIBUTES;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD_USER_GROUPS;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD_USER_GROUP_ATTRIBUTES;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD_USER_ROLES;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD__MATCH_TYPE;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD__NAME;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD__OWNER_USER;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD__TYPE;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_GET_TAG_ATTR;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_GET_TAG_ATTR_CSV;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_GET_TAG_ATTR_NAMES;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_GET_TAG_ATTR_NAMES_Q;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_GET_TAG_ATTR_Q;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_GET_TAG_ATTR_Q_CSV;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_GET_TAG_NAMES;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_GET_TAG_NAMES_Q;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_GET_UG_ATTR;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_GET_UG_ATTR_CSV;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_GET_UG_ATTR_NAMES;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_GET_UG_ATTR_NAMES_Q;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_GET_UG_ATTR_Q;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_GET_UG_ATTR_Q_CSV;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_GET_UG_NAMES;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_GET_UG_NAMES_Q;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_GET_UR_NAMES;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_GET_UR_NAMES_Q;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_GET_USER_ATTR;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_GET_USER_ATTR_NAMES;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_GET_USER_ATTR_NAMES_Q;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_GET_USER_ATTR_Q;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_HAS_ANY_TAG;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_HAS_NO_TAG;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_HAS_TAG;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_HAS_TAG_ATTR;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_HAS_UG_ATTR;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_HAS_USER_ATTR;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_IS_ACCESS_TIME_AFTER;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_IS_ACCESS_TIME_BEFORE;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_IS_ACCESS_TIME_BETWEEN;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_IS_IN_ANY_GROUP;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_IS_IN_ANY_ROLE;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_IS_IN_GROUP;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_IS_IN_ROLE;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_IS_NOT_IN_ANY_GROUP;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_IS_NOT_IN_ANY_ROLE;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_TAG_ATTR_NAMES_CSV;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_TAG_ATTR_NAMES_Q_CSV;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_TAG_NAMES_CSV;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_TAG_NAMES_Q_CSV;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_UG_ATTR_NAMES_CSV;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_UG_ATTR_NAMES_Q_CSV;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_UG_NAMES_CSV;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_UG_NAMES_Q_CSV;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_UR_NAMES_CSV;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_UR_NAMES_Q_CSV;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_USER_ATTR_NAMES_CSV;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_MACRO_USER_ATTR_NAMES_Q_CSV;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_POLYFILL_INCLUDES;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_POLYFILL_INTERSECTS;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_VAR_REQ;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_VAR_RES;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_VAR_TAG;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_VAR_TAGNAMES;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_VAR_TAGS;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_VAR_UG;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_VAR_UGA;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_VAR_UGNAMES;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_VAR_URNAMES;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_VAR_USER;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_VAR__CTX;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_VAR__CTX_JSON;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_VAR_ctx;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_VAR_tag;
+import static 
org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_VAR_tagAttr;
 
 public final class RangerRequestScriptEvaluator {
-       private static final Logger LOG = 
LoggerFactory.getLogger(RangerRequestScriptEvaluator.class);
-
-       private static final Logger    PERF_POLICY_CONDITION_SCRIPT_TOJSON      
   = RangerPerfTracer.getPerfLogger("policy.condition.script.tojson");
-       private static final Logger    PERF_POLICY_CONDITION_SCRIPT_EVAL        
   = RangerPerfTracer.getPerfLogger("policy.condition.script.eval");
-       private static final String TAG_ATTR_DATE_FORMAT_PROP                   
= "ranger.plugin.tag.attr.additional.date.formats";
-       private static final String TAG_ATTR_DATE_FORMAT_SEPARATOR              
= "||";
-       private static final String TAG_ATTR_DATE_FORMAT_SEPARATOR_REGEX        
= "\\|\\|";
-       private static final String DEFAULT_RANGER_TAG_ATTRIBUTE_DATE_FORMAT    
= "yyyy/MM/dd";
-       private static final String 
DEFAULT_ATLAS_TAG_ATTRIBUTE_DATE_FORMAT_NAME = "ATLAS_DATE_FORMAT";
-       private static final String DEFAULT_ATLAS_TAG_ATTRIBUTE_DATE_FORMAT     
= "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
-       private static final String SCRIPT_SAFE_PREEXEC                         
= "exit=null;quit=null;";
-       private static final String SCRIPT_PREEXEC                              
= SCRIPT_VAR__CTX + "=JSON.parse(" + SCRIPT_VAR__CTX_JSON + "); 
J=JSON.stringify;" +
-                       SCRIPT_VAR_REQ + "=" + SCRIPT_VAR__CTX + "." + 
SCRIPT_FIELD_REQUEST + ";" +
-                       SCRIPT_VAR_RES + "=" + SCRIPT_VAR_REQ + "." + 
SCRIPT_FIELD_RESOURCE + ";" +
-                       SCRIPT_VAR_USER + "=" + SCRIPT_VAR_REQ + "." + 
SCRIPT_FIELD_USER_ATTRIBUTES + ";" +
-                       SCRIPT_VAR_UGNAMES + "=" + SCRIPT_VAR_REQ + "." + 
SCRIPT_FIELD_USER_GROUPS + ";" +
-                       SCRIPT_VAR_UG + "=" + SCRIPT_VAR_REQ + "." + 
SCRIPT_FIELD_USER_GROUP_ATTRIBUTES + ";" +
-                       SCRIPT_VAR_UGA + "=" + SCRIPT_VAR_REQ + "." + 
SCRIPT_FIELD_UGA + ";" +
-                       SCRIPT_VAR_URNAMES + "=" + SCRIPT_VAR_REQ + "." + 
SCRIPT_FIELD_USER_ROLES + ";" +
-                       SCRIPT_VAR_TAG + "=" + SCRIPT_VAR__CTX + "." + 
SCRIPT_FIELD_TAG + ";" +
-                       SCRIPT_VAR_TAGS + "=" + SCRIPT_VAR__CTX + "." + 
SCRIPT_FIELD_TAGS + ";" +
-                       SCRIPT_VAR_TAGNAMES + "=" + SCRIPT_VAR__CTX + "." + 
SCRIPT_FIELD_TAG_NAMES + ";";
-       private static final Pattern JSON_VAR_NAMES_PATTERN   = 
Pattern.compile(getJsonVarNamesPattern());
-       private static final Pattern USER_ATTRIBUTES_PATTERN  = 
Pattern.compile(getUserAttributesPattern());
-       private static final Pattern GROUP_ATTRIBUTES_PATTERN = 
Pattern.compile(getGroupAttributesPattern());
-       private static final String  STR_QUOTE  = "'";
-       private static final String  STR_COMMA  = ",";
-
-       private static final MacroProcessor MACRO_PROCESSOR = new 
MacroProcessor(getMacrosMap());
-
-       private static String[] dateFormatStrings = null;
-
-       private final RangerAccessRequest              accessRequest;
-       private final ScriptEngine                     scriptEngine;
-       private final Bindings                         bindings;
-       private       boolean                          initDone   = false;
-       private       Map<String, String>              userAttrs  = 
Collections.emptyMap();
-       private       Map<String, Map<String, String>> groupAttrs = 
Collections.emptyMap();
-       private       Map<String, Map<String, Object>> tags       = 
Collections.emptyMap();
-       private       Map<String, Object>              tag        = 
Collections.emptyMap();
-       private       Collection<String>               userGroups = 
Collections.emptySet();
-       private       Collection<String>               userRoles  = 
Collections.emptySet();
-       private       Collection<String>               tagNames   = 
Collections.emptySet();
-       private       Boolean                          result     = false;
-
-       static {
-               init(null);
-       }
-
-       private static final ThreadLocal<List<SimpleDateFormat>> 
THREADLOCAL_DATE_FORMATS =
-                       new ThreadLocal<List<SimpleDateFormat>>() {
-                               @Override protected List<SimpleDateFormat> 
initialValue() {
-                                       List<SimpleDateFormat> ret = new 
ArrayList<>();
-
-                                       for (String dateFormatString : 
dateFormatStrings) {
-                                               try {
-                                                       if 
(StringUtils.isNotBlank(dateFormatString)) {
-                                                               if 
(StringUtils.equalsIgnoreCase(dateFormatString, 
DEFAULT_ATLAS_TAG_ATTRIBUTE_DATE_FORMAT_NAME)) {
-                                                                       
dateFormatString = DEFAULT_ATLAS_TAG_ATTRIBUTE_DATE_FORMAT;
-                                                               }
-                                                               
SimpleDateFormat df = new SimpleDateFormat(dateFormatString);
-                                                               
df.setLenient(false);
-                                                               ret.add(df);
-                                                       }
-                                               } catch (Exception exception) {
-                                                       // Ignore
-                                               }
-                                       }
-
-                                       return ret;
-                               }
-                       };
-
-
-       public static boolean needsJsonCtxEnabled(String script) {
-               boolean ret = false;
-
-               if (script != null) {
-                       Matcher matcher = 
JSON_VAR_NAMES_PATTERN.matcher(script);
-
-                       ret = matcher.find();
-               }
-
-               return ret;
-       }
-
-       public static boolean hasUserAttributeReference(String script) {
-               boolean ret = false;
-
-               if (script != null) {
-                       Matcher matcher = 
USER_ATTRIBUTES_PATTERN.matcher(script);
-
-                       ret = matcher.find();
-               }
-
-               return ret;
-       }
-
-       public static boolean hasGroupAttributeReference(String script) {
-               boolean ret = false;
-
-               if (script != null) {
-                       Matcher matcher = 
GROUP_ATTRIBUTES_PATTERN.matcher(script);
-
-                       ret = matcher.find();
-               }
-
-               return ret;
-       }
-
-       public static boolean hasUserGroupAttributeReference(String script) {
-               return hasUserAttributeReference(script) || 
hasGroupAttributeReference(script);
-       }
-
-       public static boolean hasUserGroupAttributeReference(Collection<String> 
scripts) {
-               boolean ret = false;
-
-               if (scripts != null) {
-                       for (String script : scripts) {
-                               if (hasUserGroupAttributeReference(script)) {
-                                       ret = true;
-
-                                       break;
-                               }
-                       }
-               }
-
-               return ret;
-       }
-
-       public static String expandMacros(String script) {
-               return MACRO_PROCESSOR.expandMacros(script);
-       }
-
-       public RangerRequestScriptEvaluator(RangerAccessRequest accessRequest, 
ScriptEngine scriptEngine) {
-               this(accessRequest, scriptEngine, true);
-       }
-
-       public RangerRequestScriptEvaluator(RangerAccessRequest accessRequest, 
ScriptEngine scriptEngine, boolean enableJsonCtx) {
-               this.accessRequest = accessRequest.getReadOnlyCopy();
-               this.scriptEngine  = scriptEngine;
-               this.bindings      = scriptEngine.createBindings();
-
-               RangerTagForEval    currentTag = this.getCurrentTag();
-               Map<String, String> tagAttribs = currentTag != null ? 
currentTag.getAttributes() : Collections.emptyMap();
-
-               bindings.put(SCRIPT_VAR_ctx, this);
-               bindings.put(SCRIPT_VAR_tag, currentTag);
-               bindings.put(SCRIPT_VAR_tagAttr, tagAttribs);
-
-               String preExecScript = "";
-
-               if (enableJsonCtx) {
-                       bindings.put(SCRIPT_VAR__CTX_JSON, this.toJson());
-
-                       preExecScript += SCRIPT_PREEXEC;
-               }
-
-               if (StringUtils.isNotBlank(preExecScript)) {
-                       try {
-                               scriptEngine.eval(preExecScript, bindings);
-                       } catch (ScriptException excp) {
-                               LOG.error("RangerRequestScriptEvaluator(): 
initialization failed", excp);
-                       }
-               }
-       }
-
-       public Object evaluateScript(String script) {
-               script = expandMacros(script);
-
-               return evaluateScriptImpl(script);
-       }
-
-       public Object evaluateConditionScript(String script) {
-               Object ret = evaluateScript(script);
-
-               if (ret == null) {
-                       ret = getResult();
-               }
-
-               if (ret instanceof Boolean) {
-                       result = (Boolean) ret;
-               }
-
-               return ret;
-       }
-
-       private Object evaluateScriptImpl(String script) {
-               Object           ret  = null;
-               RangerPerfTracer perf = null;
-
-               try {
-                       if 
(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_CONDITION_SCRIPT_EVAL)) {
-                               perf = 
RangerPerfTracer.getPerfTracer(PERF_POLICY_CONDITION_SCRIPT_EVAL, 
"RangerRequestScriptEvaluator.evaluateScript(requestHash=" + 
accessRequest.hashCode() + ")");
-                       }
-
-                       String preExec = SCRIPT_SAFE_PREEXEC;
-
-                       if (script.contains(".includes(")) {
-                               preExec += SCRIPT_POLYFILL_INCLUDES;
-                       }
-
-                       if (script.contains(".intersects(")) {
-                               preExec += SCRIPT_POLYFILL_INTERSECTS;
-                       }
-
-                       if (JavaScriptEdits.hasDoubleBrackets(script)) {
-                               script = 
JavaScriptEdits.replaceDoubleBrackets(script);
-                       }
-
-                       ret = scriptEngine.eval(preExec + script, bindings);
-               } catch (NullPointerException nullp) {
-                       
LOG.error("RangerRequestScriptEvaluator.evaluateScript(): eval called with NULL 
argument(s)", nullp);
-               } catch (ScriptException excp) {
-                       
LOG.error("RangerRequestScriptEvaluator.evaluateScript(): failed to evaluate 
script", excp);
-               } catch (Throwable t) {
-                       
LOG.error("RangerRequestScriptEvaluator.evaluateScript(): failed to evaluate 
script", t);
-               } finally {
-                       RangerPerfTracer.log(perf);
-               }
-
-               return ret;
-       }
-
-       private String toJson() {
-               RangerPerfTracer perf = null;
-
-               if 
(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_CONDITION_SCRIPT_TOJSON)) {
-                       perf = 
RangerPerfTracer.getPerfTracer(PERF_POLICY_CONDITION_SCRIPT_TOJSON, 
"RangerRequestScriptEvaluator.toJson(requestHash=" + accessRequest.hashCode() + 
")");
-               }
+    private static final Logger LOG = 
LoggerFactory.getLogger(RangerRequestScriptEvaluator.class);
+
+    private static final Logger  PERF_POLICY_CONDITION_SCRIPT_TOJSON          
= RangerPerfTracer.getPerfLogger("policy.condition.script.tojson");
+    private static final Logger  PERF_POLICY_CONDITION_SCRIPT_EVAL            
= RangerPerfTracer.getPerfLogger("policy.condition.script.eval");
+    private static final String  TAG_ATTR_DATE_FORMAT_PROP                    
= "ranger.plugin.tag.attr.additional.date.formats";
+    private static final String  TAG_ATTR_DATE_FORMAT_SEPARATOR               
= "||";
+    private static final String  TAG_ATTR_DATE_FORMAT_SEPARATOR_REGEX         
= "\\|\\|";
+    private static final String  DEFAULT_RANGER_TAG_ATTRIBUTE_DATE_FORMAT     
= "yyyy/MM/dd";
+    private static final String  DEFAULT_ATLAS_TAG_ATTRIBUTE_DATE_FORMAT_NAME 
= "ATLAS_DATE_FORMAT";
+    private static final String  DEFAULT_ATLAS_TAG_ATTRIBUTE_DATE_FORMAT      
= "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
+    private static final String  SCRIPT_SAFE_PREEXEC                          
= 
"Object.defineProperty(this,'engine',{value:null,writable:false});exit=null;quit=null;";
+    private static final String  SCRIPT_PREEXEC                               
= SCRIPT_VAR__CTX + "=JSON.parse(" + SCRIPT_VAR__CTX_JSON + "); 
J=JSON.stringify;" +
+            SCRIPT_VAR_REQ + "=" + SCRIPT_VAR__CTX + "." + 
SCRIPT_FIELD_REQUEST + ";" +
+            SCRIPT_VAR_RES + "=" + SCRIPT_VAR_REQ + "." + 
SCRIPT_FIELD_RESOURCE + ";" +
+            SCRIPT_VAR_USER + "=" + SCRIPT_VAR_REQ + "." + 
SCRIPT_FIELD_USER_ATTRIBUTES + ";" +
+            SCRIPT_VAR_UGNAMES + "=" + SCRIPT_VAR_REQ + "." + 
SCRIPT_FIELD_USER_GROUPS + ";" +
+            SCRIPT_VAR_UG + "=" + SCRIPT_VAR_REQ + "." + 
SCRIPT_FIELD_USER_GROUP_ATTRIBUTES + ";" +
+            SCRIPT_VAR_UGA + "=" + SCRIPT_VAR_REQ + "." + SCRIPT_FIELD_UGA + 
";" +
+            SCRIPT_VAR_URNAMES + "=" + SCRIPT_VAR_REQ + "." + 
SCRIPT_FIELD_USER_ROLES + ";" +
+            SCRIPT_VAR_TAG + "=" + SCRIPT_VAR__CTX + "." + SCRIPT_FIELD_TAG + 
";" +
+            SCRIPT_VAR_TAGS + "=" + SCRIPT_VAR__CTX + "." + SCRIPT_FIELD_TAGS 
+ ";" +
+            SCRIPT_VAR_TAGNAMES + "=" + SCRIPT_VAR__CTX + "." + 
SCRIPT_FIELD_TAG_NAMES + ";";
+    private static final Pattern JSON_VAR_NAMES_PATTERN                       
= Pattern.compile(getJsonVarNamesPattern());
+    private static final Pattern USER_ATTRIBUTES_PATTERN                      
= Pattern.compile(getUserAttributesPattern());
+    private static final Pattern GROUP_ATTRIBUTES_PATTERN                     
= Pattern.compile(getGroupAttributesPattern());
+    private static final String  STR_QUOTE                                    
= "'";
+    private static final String  STR_COMMA                                    
= ",";
+
+    private static final MacroProcessor MACRO_PROCESSOR = new 
MacroProcessor(getMacrosMap());
+
+    private static       String[]                            dateFormatStrings 
       = {};
+    private static final ThreadLocal<List<SimpleDateFormat>> 
THREADLOCAL_DATE_FORMATS = ThreadLocal.withInitial(() -> {
+        List<SimpleDateFormat> ret = new ArrayList<>();
+
+        for (String dateFormatString : dateFormatStrings) {
+            try {
+                if (StringUtils.isNotBlank(dateFormatString)) {
+                    if (StringUtils.equalsIgnoreCase(dateFormatString, 
DEFAULT_ATLAS_TAG_ATTRIBUTE_DATE_FORMAT_NAME)) {
+                        dateFormatString = 
DEFAULT_ATLAS_TAG_ATTRIBUTE_DATE_FORMAT;
+                    }
+                    SimpleDateFormat df = new 
SimpleDateFormat(dateFormatString);
+                    df.setLenient(false);
+                    ret.add(df);
+                }
+            } catch (Exception exception) {
+                // Ignore
+            }
+        }
+
+        return ret;
+    });
+
+    private final RangerAccessRequest                 accessRequest;
+    private final ScriptEngine                        scriptEngine;
+    private final Bindings                            bindings;
+    private       boolean                             initDone;
+    private       Map<String, String>                 userAttrs  = 
Collections.emptyMap();
+    private       Map<String, Map<String, String>>    groupAttrs = 
Collections.emptyMap();
+    private       Map<String, Map<String, Object>>    tags       = 
Collections.emptyMap();
+    private       Map<String, Object>                 tag        = 
Collections.emptyMap();
+    private       Collection<String>                  userGroups = 
Collections.emptySet();
+    private       Collection<String>                  userRoles  = 
Collections.emptySet();
+    private       Collection<String>                  tagNames   = 
Collections.emptySet();
+    private       boolean                             result;
+
+    public RangerRequestScriptEvaluator(RangerAccessRequest accessRequest, 
ScriptEngine scriptEngine) {
+        this(accessRequest, scriptEngine, true);
+    }
+
+    public RangerRequestScriptEvaluator(RangerAccessRequest accessRequest, 
ScriptEngine scriptEngine, boolean enableJsonCtx) {
+        this.accessRequest = accessRequest.getReadOnlyCopy();
+        this.scriptEngine  = scriptEngine;
+        this.bindings      = scriptEngine.createBindings();
+
+        RangerTagForEval    currentTag = this.getCurrentTag();
+        Map<String, String> tagAttribs = currentTag != null ? 
currentTag.getAttributes() : Collections.emptyMap();
+
+        bindings.put(SCRIPT_VAR_ctx, this);
+        bindings.put(SCRIPT_VAR_tag, currentTag);
+        bindings.put(SCRIPT_VAR_tagAttr, tagAttribs);
+
+        String preExecScript = "";
+
+        if (enableJsonCtx) {
+            bindings.put(SCRIPT_VAR__CTX_JSON, this.toJson());
+
+            preExecScript += SCRIPT_PREEXEC;
+        }
+
+        if (StringUtils.isNotBlank(preExecScript)) {
+            try {
+                scriptEngine.eval(preExecScript, bindings);
+            } catch (ScriptException excp) {
+                LOG.error("RangerRequestScriptEvaluator(): initialization 
failed", excp);
+            }
+        }
+    }
+
+    public static boolean needsJsonCtxEnabled(String script) {
+        boolean ret = false;
+
+        if (script != null) {
+            Matcher matcher = JSON_VAR_NAMES_PATTERN.matcher(script);
+
+            ret = matcher.find();
+        }
+
+        return ret;
+    }
 
-               Map<String, Object> ret        = new HashMap<>();
-               Map<String, Object> request    = new HashMap<>();
-               Date                accessTime = accessRequest.getAccessTime();
+    public static boolean hasUserAttributeReference(String script) {
+        boolean ret = false;
 
-               init();
+        if (script != null) {
+            Matcher matcher = USER_ATTRIBUTES_PATTERN.matcher(script);
 
-               if (accessTime != null) {
-                       request.put(SCRIPT_FIELD_ACCESS_TIME, 
accessTime.getTime());
-               }
+            ret = matcher.find();
+        }
 
-               request.put(SCRIPT_FIELD_ACCESS_TYPE, 
accessRequest.getAccessType());
-               request.put(SCRIPT_FIELD_ACTION, accessRequest.getAction());
-               request.put(SCRIPT_FIELD_CLIENT_IP_ADDRESS, 
accessRequest.getClientIPAddress());
-               request.put(SCRIPT_FIELD_CLIENT_TYPE, 
accessRequest.getClientType());
-               request.put(SCRIPT_FIELD_CLUSTER_NAME, 
accessRequest.getClusterName());
-               request.put(SCRIPT_FIELD_CLUSTER_TYPE, 
accessRequest.getClusterType());
-               request.put(SCRIPT_FIELD_FORWARDED_ADDRESSES, 
accessRequest.getForwardedAddresses());
-               request.put(SCRIPT_FIELD_REMOTE_IP_ADDRESS, 
accessRequest.getRemoteIPAddress());
-               request.put(SCRIPT_FIELD_REQUEST_DATA, 
accessRequest.getRequestData());
+        return ret;
+    }
 
-               if (accessRequest.getResource() != null) {
-                       Map<String, Object> resource = new 
HashMap<>(accessRequest.getResource().getAsMap());
+    public static boolean hasGroupAttributeReference(String script) {
+        boolean ret = false;
 
-                       resource.put(SCRIPT_FIELD__OWNER_USER, 
accessRequest.getResource().getOwnerUser());
+        if (script != null) {
+            Matcher matcher = GROUP_ATTRIBUTES_PATTERN.matcher(script);
 
-                       request.put(SCRIPT_FIELD_RESOURCE, resource);
-               }
+            ret = matcher.find();
+        }
 
-               request.put(SCRIPT_FIELD_RESOURCE_MATCHING_SCOPE, 
accessRequest.getResourceMatchingScope());
+        return ret;
+    }
 
-               request.put(SCRIPT_FIELD_USER, getUser());
-               request.put(SCRIPT_FIELD_USER_GROUPS, userGroups);
-               request.put(SCRIPT_FIELD_USER_ROLES, userRoles);
+    public static boolean hasUserGroupAttributeReference(String script) {
+        return hasUserAttributeReference(script) || 
hasGroupAttributeReference(script);
+    }
 
-               request.put(SCRIPT_FIELD_USER_ATTRIBUTES, userAttrs);
+    public static boolean hasUserGroupAttributeReference(Collection<String> 
scripts) {
+        return scripts != null && 
scripts.stream().anyMatch(RangerRequestScriptEvaluator::hasUserGroupAttributeReference);
+    }
 
-               request.put(SCRIPT_FIELD_USER_GROUP_ATTRIBUTES, groupAttrs);
-               request.put(SCRIPT_FIELD_UGA, new 
UserGroupsAttributes(userGroups, groupAttrs).getAttributes());
+    public static String expandMacros(String script) {
+        return MACRO_PROCESSOR.expandMacros(script);
+    }
 
-               ret.put(SCRIPT_FIELD_REQUEST, request);
+    public static void init(Configuration config) {
+        StringBuilder sb = new 
StringBuilder(DEFAULT_RANGER_TAG_ATTRIBUTE_DATE_FORMAT);
 
-               ret.put(SCRIPT_FIELD_TAGS, tags);
-               ret.put(SCRIPT_FIELD_TAG_NAMES, tagNames);
-               ret.put(SCRIPT_FIELD_TAG, tag);
+        
sb.append(TAG_ATTR_DATE_FORMAT_SEPARATOR).append(DEFAULT_ATLAS_TAG_ATTRIBUTE_DATE_FORMAT_NAME);
 
-               String strRet = JsonUtils.objectToJson(ret);
+        String additionalDateFormatsValue = config != null ? 
config.get(TAG_ATTR_DATE_FORMAT_PROP) : null;
 
-               RangerPerfTracer.log(perf);
+        if (StringUtils.isNotBlank(additionalDateFormatsValue)) {
+            
sb.append(TAG_ATTR_DATE_FORMAT_SEPARATOR).append(additionalDateFormatsValue);
+        }
 
-               return strRet;
-       }
+        String[] formatStrings = 
sb.toString().split(TAG_ATTR_DATE_FORMAT_SEPARATOR_REGEX);
 
-       public static void init(Configuration config) {
-               StringBuilder sb = new 
StringBuilder(DEFAULT_RANGER_TAG_ATTRIBUTE_DATE_FORMAT);
+        Arrays.sort(formatStrings, (first, second) -> 
Integer.compare(second.length(), first.length()));
 
-               
sb.append(TAG_ATTR_DATE_FORMAT_SEPARATOR).append(DEFAULT_ATLAS_TAG_ATTRIBUTE_DATE_FORMAT_NAME);
+        RangerRequestScriptEvaluator.dateFormatStrings = formatStrings;
+    }
 
-               String additionalDateFormatsValue = config != null ? 
config.get(TAG_ATTR_DATE_FORMAT_PROP) : null;
+    public Object evaluateScript(String script) {
+        script = expandMacros(script);
 
-               if (StringUtils.isNotBlank(additionalDateFormatsValue)) {
-                       
sb.append(TAG_ATTR_DATE_FORMAT_SEPARATOR).append(additionalDateFormatsValue);
-               }
+        return evaluateScriptImpl(script);
+    }
 
-               String[] formatStrings = 
sb.toString().split(TAG_ATTR_DATE_FORMAT_SEPARATOR_REGEX);
+    public Object evaluateConditionScript(String script) {
+        Object ret = evaluateScript(script);
 
-               Arrays.sort(formatStrings, new Comparator<String>() {
-                       @Override
-                       public int compare(String first, String second) {
-                               return Integer.compare(second.length(), 
first.length());
-                       }
-               });
+        if (ret == null) {
+            ret = getResult();
+        }
 
-               RangerRequestScriptEvaluator.dateFormatStrings = formatStrings;
-       }
+        if (ret instanceof Boolean) {
+            result = (Boolean) ret;
+        }
 
-       public String getResource() {
-               String ret = null;
-               RangerAccessResource val = 
RangerAccessRequestUtil.getCurrentResourceFromContext(getRequestContext());
+        return ret;
+    }
 
-               if(val != null) {
-                       ret = val.getAsString();
-               }
+    public String getResource() {
+        String               ret = null;
+        RangerAccessResource val = 
RangerAccessRequestUtil.getCurrentResourceFromContext(getRequestContext());
 
-               return ret;
-       }
+        if (val != null) {
+            ret = val.getAsString();
+        }
 
-       public String getResourceZone() {
-               String ret = 
RangerAccessRequestUtil.getResourceZoneNameFromContext(getRequestContext());
+        return ret;
+    }
 
-               return ret != null ? ret : StringUtils.EMPTY;
-       }
+    public String getResourceZone() {
+        String ret = 
RangerAccessRequestUtil.getResourceZoneNameFromContext(getRequestContext());
 
-       public Set<String> getResourceZones() {
-               Set<String> ret = 
RangerAccessRequestUtil.getResourceZoneNamesFromContext(getRequestContext());
+        return ret != null ? ret : StringUtils.EMPTY;
+    }
 
-               return ret != null ? Collections.emptySet() : ret;
-       }
+    public Set<String> getResourceZones() {
+        Set<String> ret = 
RangerAccessRequestUtil.getResourceZoneNamesFromContext(getRequestContext());
 
-       public String getRequestContextAttribute(String attributeName) {
-               String ret = null;
+        return ret != null ? ret : Collections.emptySet();
+    }
 
-               if (StringUtils.isNotBlank(attributeName)) {
-                       Object val = getRequestContext().get(attributeName);
+    public String getRequestContextAttribute(String attributeName) {
+        String ret = null;
 
-                       if(val != null) {
-                               ret = val.toString();
-                       }
-               }
+        if (StringUtils.isNotBlank(attributeName)) {
+            Object val = getRequestContext().get(attributeName);
 
-               return ret;
-       }
+            if (val != null) {
+                ret = val.toString();
+            }
+        }
 
-       public boolean isAccessTypeAny() { return 
accessRequest.isAccessTypeAny(); }
+        return ret;
+    }
 
-       public boolean isAccessTypeDelegatedAdmin() { return 
accessRequest.isAccessTypeDelegatedAdmin(); }
+    public boolean isAccessTypeAny() {
+        return accessRequest.isAccessTypeAny();
+    }
 
-       public String getUser() { return accessRequest.getUser(); }
+    public boolean isAccessTypeDelegatedAdmin() {
+        return accessRequest.isAccessTypeDelegatedAdmin();
+    }
 
-       public Set<String> getUserGroups() { return 
accessRequest.getUserGroups(); }
+    public String getUser() {
+        return accessRequest.getUser();
+    }
 
-       public Set<String> getUserRoles() {
-               return RangerAccessRequestUtil.getUserRoles(accessRequest);
-       }
+    public Set<String> getUserGroups() {
+        return accessRequest.getUserGroups();
+    }
 
-       public Date getAccessTime() { return accessRequest.getAccessTime() != 
null ? accessRequest.getAccessTime() : new Date(); }
+    public Set<String> getUserRoles() {
+        return RangerAccessRequestUtil.getUserRoles(accessRequest);
+    }
 
-       public String getClientIPAddress() { return 
accessRequest.getClientIPAddress(); }
+    public Date getAccessTime() {
+        return accessRequest.getAccessTime() != null ? 
accessRequest.getAccessTime() : new Date();
+    }
 
-       public String getClientType() { return accessRequest.getClientType(); }
+    public String getClientIPAddress() {
+        return accessRequest.getClientIPAddress();
+    }
 
-       public String getAction() { return accessRequest.getAction(); }
+    public String getClientType() {
+        return accessRequest.getClientType();
+    }
 
-       public String getRequestData() { return accessRequest.getRequestData(); 
}
+    public String getAction() {
+        return accessRequest.getAction();
+    }
 
-       public String getSessionId() { return accessRequest.getSessionId(); }
+    public String getRequestData() {
+        return accessRequest.getRequestData();
+    }
 
-       public RangerTagForEval getCurrentTag() {
-               RangerTagForEval ret = 
RangerAccessRequestUtil.getCurrentTagFromContext(getRequestContext());
+    public String getSessionId() {
+        return accessRequest.getSessionId();
+    }
 
-               if(ret == null ) {
-                       if (LOG.isDebugEnabled()) {
-                               
logDebug("RangerRequestScriptEvaluator.getCurrentTag() - No current TAG object. 
Script execution must be for resource-based policy.");
-                       }
-               }
-               return ret;
-       }
+    public RangerTagForEval getCurrentTag() {
+        RangerTagForEval ret = 
RangerAccessRequestUtil.getCurrentTagFromContext(getRequestContext());
 
-       public String getCurrentTagType() {
-               RangerTagForEval tagObject = getCurrentTag();
-               return (tagObject != null) ? tagObject.getType() : null;
-       }
+        if (ret == null) {
+            if (LOG.isDebugEnabled()) {
+                logDebug("RangerRequestScriptEvaluator.getCurrentTag() - No 
current TAG object. Script execution must be for resource-based policy.");
+            }
+        }
+        return ret;
+    }
 
-       public Set<String> getAllTagTypes() {
-               Set<String>     allTagTypes   = null;
-               Set<RangerTagForEval> tagObjectList = getAllTags();
+    public String getCurrentTagType() {
+        RangerTagForEval tagObject = getCurrentTag();
+        return (tagObject != null) ? tagObject.getType() : null;
+    }
 
-               if (CollectionUtils.isNotEmpty(tagObjectList)) {
-                       for (RangerTagForEval tag : tagObjectList) {
-                               String tagType = tag.getType();
-                               if (allTagTypes == null) {
-                                       allTagTypes = new HashSet<>();
-                               }
-                               allTagTypes.add(tagType);
-                       }
-               }
-
-               return allTagTypes;
-       }
-
-       public Map<String, String> getTagAttributes(final String tagType) {
-               Map<String, String> ret = null;
-
-               if (StringUtils.isNotBlank(tagType)) {
-                       Set<RangerTagForEval> tagObjectList = getAllTags();
-
-                       // Assumption: There is exactly one tag with given 
tagType in the list of tags - may not be true ***TODO***
-                       // This will get attributes of the first tagType that 
matches
-                       if (CollectionUtils.isNotEmpty(tagObjectList)) {
-                               for (RangerTagForEval tag : tagObjectList) {
-                                       if (tag.getType().equals(tagType)) {
-                                               ret = tag.getAttributes();
-                                               break;
-                                       }
-                               }
-                       }
-               }
-
-               return ret;
-       }
-
-       public List<Map<String, String>> 
getTagAttributesForAllMatchingTags(final String tagType) {
-               List<Map<String, String>> ret = null;
-
-               if (StringUtils.isNotBlank(tagType)) {
-                       Set<RangerTagForEval> tagObjectList = getAllTags();
-
-                       // Assumption: There is exactly one tag with given 
tagType in the list of tags - may not be true ***TODO***
-                       // This will get attributes of the first tagType that 
matches
-                       if (CollectionUtils.isNotEmpty(tagObjectList)) {
-                               for (RangerTagForEval tag : tagObjectList) {
-                                       if (tag.getType().equals(tagType)) {
-                                               Map<String, String> 
tagAttributes = tag.getAttributes();
-                                               if (tagAttributes != null) {
-                                                       if (ret == null) {
-                                                               ret = new 
ArrayList<>();
-                                                       }
-                                                       ret.add(tagAttributes);
-                                               }
-                                               break;
-                                       }
-                               }
-                       }
-               }
-
-               return ret;
-       }
-
-       public Set<String> getAttributeNames(final String tagType) {
-               Set<String>         ret        = null;
-               Map<String, String> attributes = getTagAttributes(tagType);
-
-               if (attributes != null) {
-                       ret = attributes.keySet();
-               }
-
-               return ret;
-       }
-
-       public String getAttributeValue(final String tagType, final String 
attributeName) {
-               String ret = null;
-
-               if (StringUtils.isNotBlank(tagType) || 
StringUtils.isNotBlank(attributeName)) {
-                       Map<String, String> attributes = 
getTagAttributes(tagType);
-
-                       if (attributes != null) {
-                               ret = attributes.get(attributeName);
-                       }
-               }
-               return ret;
-       }
-
-       public List<String> getAttributeValueForAllMatchingTags(final String 
tagType, final String attributeName) {
-               List<String> ret = null;
-
-               if (StringUtils.isNotBlank(tagType) || 
StringUtils.isNotBlank(attributeName)) {
-                       Map<String, String> attributes = 
getTagAttributes(tagType);
-
-                       if (attributes != null && attributes.get(attributeName) 
!= null) {
-                               if (ret == null) {
-                                       ret = new ArrayList<>();
-                               }
-                               ret.add(attributes.get(attributeName));
-                       }
-               }
-               return ret;
-       }
-
-       public String getAttributeValue(final String attributeName) {
-               String ret = null;
-
-               if (StringUtils.isNotBlank(attributeName)) {
-                       RangerTagForEval tag = getCurrentTag();
-                       Map<String, String> attributes = null;
-                       if (tag != null) {
-                               attributes = tag.getAttributes();
-                       }
-                       if (attributes != null) {
-                               ret = attributes.get(attributeName);
-                       }
-               }
-
-               return ret;
-       }
-
-       public boolean getResult() {
-               return result;
-
-       }
-
-       public void setResult(final boolean result) {
-               this.result = result;
-       }
-
-       private Date getAsDate(String value, SimpleDateFormat df) {
-               Date ret = null;
-
-               TimeZone savedTimeZone = df.getTimeZone();
-               try {
-                       ret = df.parse(value);
-               } catch (ParseException exception) {
-                       // Ignore
-               } finally {
-                       df.setTimeZone(savedTimeZone);
-               }
-
-               return ret;
-       }
-
-       public Date getAsDate(String value) {
-               Date ret = null;
-
-               if (StringUtils.isNotBlank(value)) {
-                       for (SimpleDateFormat simpleDateFormat : 
THREADLOCAL_DATE_FORMATS.get()) {
-                               ret = getAsDate(value, simpleDateFormat);
-                               if (ret != null) {
-                                       if (LOG.isDebugEnabled()) {
-                                               
logDebug("RangerRequestScriptEvaluator.getAsDate() -The best match found for 
Format-String:[" + simpleDateFormat.toPattern() + "], date:[" + ret +"]");
-                                       }
-                                       break;
-                               }
-                       }
-               }
+    public Set<String> getAllTagTypes() {
+        Set<RangerTagForEval> tags = getAllTags();
 
-               if (ret == null) {
-                       logError("RangerRequestScriptEvaluator.getAsDate() - 
Could not convert [" + value + "] to Date using any of the Format-Strings: " + 
Arrays.toString(dateFormatStrings));
-               } else {
-                       ret = StringUtil.getUTCDateForLocalDate(ret);
-               }
+        return CollectionUtils.isEmpty(tags) ? null : 
tags.stream().map(RangerTagForEval::getType).collect(Collectors.toSet());
+    }
 
-               return ret;
-       }
+    public Map<String, String> getTagAttributes(final String tagType) {
+        Set<RangerTagForEval> tags = StringUtils.isBlank(tagType) ? null : 
getAllTags();
 
-       public Date getTagAttributeAsDate(String tagType, String attributeName) 
{
-               String attrValue = getAttributeValue(tagType, attributeName);
+        // Assumption: There is exactly one tag with given tagType in the list 
of tags - may not be true ***TODO**
+        // This will get attributes of the first tagType that matches
+        return CollectionUtils.isEmpty(tags) ? null :
+                tags.stream()
+                        .filter(tag -> tagType.equals(tag.getType()))
+                        .findFirst()
+                        .map(RangerTagForEval::getAttributes)
+                        .orElse(null);
+    }
 
-               return getAsDate(attrValue);
-       }
+    public List<Map<String, String>> getTagAttributesForAllMatchingTags(final 
String tagType) {
+        Set<RangerTagForEval> tags = StringUtils.isBlank(tagType) ? null : 
getAllTags();
 
-       public boolean isAccessedAfter(String tagType, String attributeName) {
-               boolean ret        = false;
-               Date    accessDate = getAccessTime();
-               Date    expiryDate = getTagAttributeAsDate(tagType, 
attributeName);
+        return CollectionUtils.isEmpty(tags) ? null :
+                tags.stream()
+                        .filter(tag -> tagType.equals(tag.getType()))
+                        .map(RangerTagForEval::getAttributes)
+                        .filter(MapUtils::isNotEmpty)
+                        .collect(Collectors.toList());
+    }
 
-               if (expiryDate == null || accessDate.after(expiryDate) || 
accessDate.equals(expiryDate)) {
-                       ret = true;
-               }
+    public Set<String> getAttributeNames(final String tagType) {
+        Map<String, String> attributes = getTagAttributes(tagType);
 
-               return ret;
-       }
+        return attributes == null ? null : attributes.keySet();
+    }
 
-       public boolean isAccessedAfter(String attributeName) {
-               boolean ret        = false;
-               Date    accessDate = getAccessTime();
-               Date    expiryDate = 
getAsDate(getAttributeValue(attributeName));
+    public String getAttributeValue(final String tagType, final String 
attributeName) {
+        Map<String, String> attributes = (StringUtils.isBlank(tagType) || 
StringUtils.isBlank(attributeName)) ? null : getTagAttributes(tagType);
 
-               if (expiryDate == null || accessDate.after(expiryDate) || 
accessDate.equals(expiryDate)) {
-                       ret = true;
-               }
+        return attributes == null ? null : attributes.get(attributeName);
+    }
 
-               return ret;
-       }
+    public List<String> getAttributeValueForAllMatchingTags(final String 
tagType, final String attributeName) {
+        List<Map<String, String>> attributes = (StringUtils.isBlank(tagType) 
|| StringUtils.isBlank(attributeName)) ? null : 
getTagAttributesForAllMatchingTags(tagType);
 
-       public boolean isAccessedBefore(String tagType, String attributeName) {
-               boolean ret        = true;
-               Date    accessDate = getAccessTime();
-               Date    expiryDate = getTagAttributeAsDate(tagType, 
attributeName);
+        return attributes == null ? null :
+                attributes.stream().map(tagAttrs -> 
tagAttrs.get(attributeName)).filter(Objects::nonNull).collect(Collectors.toList());
+    }
 
-               if (expiryDate == null || accessDate.after(expiryDate)) {
-                       ret = false;
-               }
+    public String getAttributeValue(final String attributeName) {
+        RangerTagForEval    tag        = StringUtils.isBlank(attributeName) ? 
null : getCurrentTag();
+        Map<String, String> attributes = tag == null ? null : 
tag.getAttributes();
 
-               return ret;
-       }
+        return attributes == null ? null : attributes.get(attributeName);
+    }
 
-       public boolean isAccessedBefore(String attributeName) {
-               boolean ret        = true;
-               Date    accessDate = getAccessTime();
-               Date    expiryDate = 
getAsDate(getAttributeValue(attributeName));
+    public boolean getResult() {
+        return result;
+    }
 
-               if (expiryDate == null || accessDate.after(expiryDate)) {
-                       ret = false;
-               }
+    public void setResult(final boolean result) {
+        this.result = result;
+    }
 
-               return ret;
-       }
+    public Date getAsDate(String value) {
+        Date ret = StringUtils.isBlank(value) ? null : 
THREADLOCAL_DATE_FORMATS.get().stream()
+                .map(dateFormat -> getAsDate(value, dateFormat))
+                .filter(Objects::nonNull)
+                .findFirst()
+                .orElse(null);
 
-       public String tagNames(Object... args) {
-               init();
+        if (ret == null) {
+            logError("RangerRequestScriptEvaluator.getAsDate() - Could not 
convert [" + value + "] to Date using any of the Format-Strings: " + 
Arrays.toString(dateFormatStrings));
+        } else {
+            ret = StringUtil.getUTCDateForLocalDate(ret);
+        }
 
-               return toCsv(tagNames, args);
-       }
+        return ret;
+    }
 
-       public String tagNamesQ(Object... args) {
-               init();
+    public Date getTagAttributeAsDate(String tagType, String attributeName) {
+        String attrValue = getAttributeValue(tagType, attributeName);
 
-               return toCsvQ(tagNames, args);
-       }
+        return getAsDate(attrValue);
+    }
 
-       public String tagAttrNames(Object... args) {
-               init();
+    public boolean isAccessedAfter(String tagType, String attributeName) {
+        Date accessDate = getAccessTime();
+        Date expiryDate = getTagAttributeAsDate(tagType, attributeName);
 
-               return toCsv(getTagAttrNames(), args);
-       }
+        return expiryDate == null || accessDate.after(expiryDate) || 
accessDate.equals(expiryDate);
+    }
 
-       public String tagAttrNamesQ(Object... args) {
-               init();
+    public boolean isAccessedAfter(String attributeName) {
+        Date accessDate = getAccessTime();
+        Date expiryDate = getAsDate(getAttributeValue(attributeName));
 
-               return toCsvQ(getTagAttrNames(), args);
-       }
+        return expiryDate == null || accessDate.after(expiryDate) || 
accessDate.equals(expiryDate);
+    }
 
-       public String tagAttr(String attrName, Object... args) {
-               init();
+    public boolean isAccessedBefore(String tagType, String attributeName) {
+        Date accessDate = getAccessTime();
+        Date expiryDate = getTagAttributeAsDate(tagType, attributeName);
 
-               return toCsv(getTagAttr(attrName), args);
-       }
+        return !(expiryDate == null || accessDate.after(expiryDate));
+    }
 
-       public String tagAttrQ(String attrName, Object... args) {
-               init();
+    public boolean isAccessedBefore(String attributeName) {
+        Date accessDate = getAccessTime();
+        Date expiryDate = getAsDate(getAttributeValue(attributeName));
 
-               return toCsvQ(getTagAttr(attrName), args);
-       }
+        return !(expiryDate == null || accessDate.after(expiryDate));
+    }
 
-       public String ugNames(Object... args) {
-               init();
+    public String tagNames(Object... args) {
+        init();
 
-               return toCsv(userGroups, args);
-       }
+        return toCsv(tagNames, args);
+    }
 
-       public String ugNamesQ(Object... args) {
-               init();
+    public String tagNamesQ(Object... args) {
+        init();
 
-               return toCsvQ(userGroups, args);
-       }
+        return toCsvQ(tagNames, args);
+    }
 
-       public String ugAttrNames(Object... args) {
-               init();
+    public String tagAttrNames(Object... args) {
+        init();
 
-               return toCsv(getUgAttrNames(), args);
-       }
+        return toCsv(getTagAttrNames(), args);
+    }
 
-       public String ugAttrNamesQ(Object... args) {
-               init();
+    public String tagAttrNamesQ(Object... args) {
+        init();
 
-               return toCsvQ(getUgAttrNames(), args);
-       }
+        return toCsvQ(getTagAttrNames(), args);
+    }
 
-       public String ugAttr(String attrName, Object... args) {
-               init();
+    public String tagAttr(String attrName, Object... args) {
+        init();
 
-               return toCsv(getUgAttr(attrName), args);
-       }
+        return toCsv(getTagAttr(attrName), args);
+    }
 
-       public String ugAttrQ(String attrName, Object... args) {
-               init();
+    public String tagAttrQ(String attrName, Object... args) {
+        init();
 
-               return toCsvQ(getUgAttr(attrName), args);
-       }
+        return toCsvQ(getTagAttr(attrName), args);
+    }
 
-       public String urNames(Object... args) {
-               init();
+    public String ugNames(Object... args) {
+        init();
 
-               return toCsv(userRoles, args);
-       }
+        return toCsv(userGroups, args);
+    }
 
-       public String urNamesQ(Object... args) {
-               init();
+    public String ugNamesQ(Object... args) {
+        init();
 
-               return toCsvQ(userRoles, args);
-       }
+        return toCsvQ(userGroups, args);
+    }
 
-       public String userAttrNames(Object... args) {
-               init();
+    public String ugAttrNames(Object... args) {
+        init();
 
-               return toCsv(getUserAttrNames(), args);
-       }
+        return toCsv(getUgAttrNames(), args);
+    }
 
-       public String userAttrNamesQ(Object... args) {
-               init();
+    public String ugAttrNamesQ(Object... args) {
+        init();
 
-               return toCsvQ(getUserAttrNames(), args);
-       }
+        return toCsvQ(getUgAttrNames(), args);
+    }
 
-       public String userAttr(String attrName, Object... args) {
-               init();
+    public String ugAttr(String attrName, Object... args) {
+        init();
 
-               String attrVal = userAttrs.get(attrName);
+        return toCsv(getUgAttr(attrName), args);
+    }
 
-               return toCsv(Collections.singletonList(attrVal), args);
-       }
+    public String ugAttrQ(String attrName, Object... args) {
+        init();
 
-       public String userAttrQ(String attrName, Object... args) {
-               init();
+        return toCsvQ(getUgAttr(attrName), args);
+    }
 
-               String attrVal = userAttrs.get(attrName);
+    public String urNames(Object... args) {
+        init();
 
-               return toCsvQ(Collections.singletonList(attrVal), args);
-       }
+        return toCsv(userRoles, args);
+    }
 
-       public boolean hasTag(String tagName) {
-               init();
+    public String urNamesQ(Object... args) {
+        init();
 
-               return tags.containsKey(tagName);
-       }
+        return toCsvQ(userRoles, args);
+    }
 
-       public boolean hasAnyTag() {
-               init();
+    public String userAttrNames(Object... args) {
+        init();
 
-               return !tags.isEmpty();
-       }
+        return toCsv(getUserAttrNames(), args);
+    }
 
-       public boolean hasUserAttr(String attrName) {
-               init();
+    public String userAttrNamesQ(Object... args) {
+        init();
 
-               return userAttrs.containsKey(attrName);
-       }
+        return toCsvQ(getUserAttrNames(), args);
+    }
 
-       public boolean hasUgAttr(String attrName) {
-               init();
+    public String userAttr(String attrName, Object... args) {
+        init();
 
-               boolean ret = false;
+        String attrVal = userAttrs.get(attrName);
 
-               for (Map<String, String> attrs : groupAttrs.values()) {
-                       if (attrs.containsKey(attrName)) {
-                               ret = true;
+        return toCsv(Collections.singletonList(attrVal), args);
+    }
 
-                               break;
-                       }
-               }
+    public String userAttrQ(String attrName, Object... args) {
+        init();
 
-               return ret;
-       }
+        String attrVal = userAttrs.get(attrName);
 
-       public boolean hasTagAttr(String attrName) {
-               init();
+        return toCsvQ(Collections.singletonList(attrVal), args);
+    }
 
-               boolean               ret  = false;
-               Set<RangerTagForEval> tags = 
RangerAccessRequestUtil.getRequestTagsFromContext(accessRequest.getContext());
+    public boolean hasTag(String tagName) {
+        init();
 
-               if (tags != null) {
-                       for (RangerTagForEval tag : tags) {
-                               if (tag.getAttributes().containsKey(attrName)) {
-                                       ret = true;
+        return tags.containsKey(tagName);
+    }
 
-                                       break;
-                               }
-                       }
-               }
+    public boolean hasAnyTag() {
+        init();
 
-               return ret;
-       }
+        return !tags.isEmpty();
+    }
 
-       public boolean isInGroup(String groupName) {
-               init();
+    public boolean hasUserAttr(String attrName) {
+        init();
 
-               return userGroups.contains(groupName);
-       }
+        return userAttrs.containsKey(attrName);
+    }
 
-       public boolean isInRole(String roleName) {
-               init();
+    public boolean hasUgAttr(String attrName) {
+        init();
 
-               return userRoles.contains(roleName);
-       }
+        return groupAttrs.values().stream().anyMatch(attrs -> 
attrs.containsKey(attrName));
+    }
 
-       public boolean isInAnyGroup() {
-               init();
+    public boolean hasTagAttr(String attrName) {
+        init();
 
-               return !userGroups.isEmpty();
-       }
+        Set<RangerTagForEval> tags = 
RangerAccessRequestUtil.getRequestTagsFromContext(accessRequest.getContext());
 
-       public boolean isInAnyRole() {
-               init();
+        return tags != null && tags.stream().anyMatch(tag -> 
tag.getAttributes().containsKey(attrName));
+    }
 
-               return !userRoles.isEmpty();
-       }
+    public boolean isInGroup(String groupName) {
+        init();
 
-       public boolean isAccessTimeAfter(String strTime) {
-               return isAccessTimeBetween(strTime, null, null);
-       }
+        return userGroups.contains(groupName);
+    }
 
-       public boolean isAccessTimeAfter(String strTime, String timeZone) {
-               return isAccessTimeBetween(strTime, null, timeZone);
-       }
+    public boolean isInRole(String roleName) {
+        init();
 
-       public boolean isAccessTimeBefore(String strTime) {
-               return isAccessTimeBetween(null, strTime, null);
-       }
+        return userRoles.contains(roleName);
+    }
 
-       public boolean isAccessTimeBefore(String strTime, String timeZone) {
-               return isAccessTimeBetween(null, strTime, timeZone);
-       }
+    public boolean isInAnyGroup() {
+        init();
 
-       public boolean isAccessTimeBetween(String fromTime, String toTime) {
-               return isAccessTimeBetween(fromTime, toTime, null);
-       }
+        return !userGroups.isEmpty();
+    }
 
-       public boolean isAccessTimeBetween(String fromTime, String toTime, 
String timeZone) {
-               RangerTimeRangeChecker evaluator = new 
RangerTimeRangeChecker(fromTime, toTime, timeZone);
+    public boolean isInAnyRole() {
+        init();
 
-               return evaluator.isInRange(getAccessTime().getTime());
-       }
+        return !userRoles.isEmpty();
+    }
 
-       // for backward compatibility
-       public String ugNamesCsv() {
-               return ugNames(null, STR_COMMA);
-       }
+    public boolean isAccessTimeAfter(String strTime) {
+        return isAccessTimeBetween(strTime, null, null);
+    }
 
-       public String ugNamesCsvQ() {
-               return ugNamesQ(null, STR_COMMA, STR_QUOTE);
-       }
+    public boolean isAccessTimeAfter(String strTime, String timeZone) {
+        return isAccessTimeBetween(strTime, null, timeZone);
+    }
 
-       public String urNamesCsv() {
-               return urNames(null, STR_COMMA);
-       }
+    public boolean isAccessTimeBefore(String strTime) {
+        return isAccessTimeBetween(null, strTime, null);
+    }
 
-       public String urNamesCsvQ() {
-               return urNamesQ(null, STR_COMMA, STR_QUOTE);
-       }
+    public boolean isAccessTimeBefore(String strTime, String timeZone) {
+        return isAccessTimeBetween(null, strTime, timeZone);
+    }
 
-       public String tagNamesCsv() {
-               return tagNames(null, STR_COMMA);
-       }
+    public boolean isAccessTimeBetween(String fromTime, String toTime) {
+        return isAccessTimeBetween(fromTime, toTime, null);
+    }
 
-       public String tagNamesCsvQ() {
-               return tagNamesQ(null, STR_COMMA, STR_QUOTE);
-       }
+    public boolean isAccessTimeBetween(String fromTime, String toTime, String 
timeZone) {
+        RangerTimeRangeChecker evaluator = new 
RangerTimeRangeChecker(fromTime, toTime, timeZone);
 
-       public String userAttrNamesCsv() {
-               return userAttrNames(null, STR_COMMA);
-       }
+        return evaluator.isInRange(getAccessTime().getTime());
+    }
 
-       public String userAttrNamesCsvQ() {
-               return userAttrNamesQ(null, STR_COMMA, STR_QUOTE);
-       }
+    // for backward compatibility
+    public String ugNamesCsv() {
+        return ugNames(null, STR_COMMA);
+    }
 
-       public String ugAttrNamesCsv() {
-               return ugAttrNames(null, STR_COMMA);
-       }
+    public String ugNamesCsvQ() {
+        return ugNamesQ(null, STR_COMMA, STR_QUOTE);
+    }
 
-       public String ugAttrNamesCsvQ() {
-               return ugAttrNamesQ(null, STR_COMMA, STR_QUOTE);
-       }
+    public String urNamesCsv() {
+        return urNames(null, STR_COMMA);
+    }
 
-       public String tagAttrNamesCsv() {
-               return tagAttrNames(null, STR_COMMA);
-       }
+    public String urNamesCsvQ() {
+        return urNamesQ(null, STR_COMMA, STR_QUOTE);
+    }
 
-       public String tagAttrNamesCsvQ() {
-               return tagAttrNamesQ(null, STR_COMMA, STR_QUOTE);
-       }
+    public String tagNamesCsv() {
+        return tagNames(null, STR_COMMA);
+    }
 
-       public String ugAttrCsv(String attrName) {
-               return ugAttr(attrName, null, STR_COMMA);
-       }
+    public String tagNamesCsvQ() {
+        return tagNamesQ(null, STR_COMMA, STR_QUOTE);
+    }
 
-       public String ugAttrCsvQ(String attrName) {
-               return ugAttrQ(attrName, null, STR_COMMA, STR_QUOTE);
-       }
+    public String userAttrNamesCsv() {
+        return userAttrNames(null, STR_COMMA);
+    }
 
-       public String tagAttrCsv(String attrName) {
-               return tagAttr(attrName, null, STR_COMMA);
-       }
+    public String userAttrNamesCsvQ() {
+        return userAttrNamesQ(null, STR_COMMA, STR_QUOTE);
+    }
 
-       public String tagAttrCsvQ(String attrName) {
-               return tagAttrQ(attrName, null, STR_COMMA, STR_QUOTE);
-       }
+    public String ugAttrNamesCsv() {
+        return ugAttrNames(null, STR_COMMA);
+    }
 
-       private void init() {
-               if (!initDone) {
-                       RangerUserStore                  userStore        = 
RangerAccessRequestUtil.getRequestUserStoreFromContext(accessRequest.getContext());
-                       Map<String, Map<String, String>> userAttrMapping  = 
userStore != null ? userStore.getUserAttrMapping() : Collections.emptyMap();
-                       Map<String, Map<String, String>> groupAttrMapping = 
userStore != null ? userStore.getGroupAttrMapping() : Collections.emptyMap();
+    public String ugAttrNamesCsvQ() {
+        return ugAttrNamesQ(null, STR_COMMA, STR_QUOTE);
+    }
 
-                       userGroups = getSorted(getUserGroups());
-                       userRoles  = getSorted(getUserRoles());
-                       userAttrs  = 
copyMap(userAttrMapping.get(accessRequest.getUser()));
-                       groupAttrs = new HashMap<>();
+    public String tagAttrNamesCsv() {
+        return tagAttrNames(null, STR_COMMA);
+    }
 
-                       userAttrs.put(SCRIPT_FIELD__NAME, getUser());
+    public String tagAttrNamesCsvQ() {
+        return tagAttrNamesQ(null, STR_COMMA, STR_QUOTE);
+    }
 
-                       for (String groupName : userGroups) {
-                               Map<String, String> attrs = 
groupAttrMapping.get(groupName);
+    public String ugAttrCsv(String attrName) {
+        return ugAttr(attrName, null, STR_COMMA);
+    }
 
-                               attrs = attrs != null ? new HashMap<>(attrs) : 
new HashMap<>();
+    public String ugAttrCsvQ(String attrName) {
+        return ugAttrQ(attrName, null, STR_COMMA, STR_QUOTE);
+    }
 
-                               attrs.put(SCRIPT_FIELD__NAME, groupName);
+    public String tagAttrCsv(String attrName) {
+        return tagAttr(attrName, null, STR_COMMA);
+    }
 
-                               groupAttrs.put(groupName, attrs);
-                       }
+    public String tagAttrCsvQ(String attrName) {
+        return tagAttrQ(attrName, null, STR_COMMA, STR_QUOTE);
+    }
 
-                       Set<RangerTagForEval> requestTags = 
RangerAccessRequestUtil.getRequestTagsFromContext(getRequestContext());
+    public void logDebug(Object msg) {
+        LOG.debug(Objects.toString(msg));
+    }
 
-                       if (CollectionUtils.isNotEmpty(requestTags)) {
-                               RangerTagForEval currentTag = 
RangerAccessRequestUtil.getCurrentTagFromContext(getRequestContext());
+    public void logInfo(Object msg) {
+        LOG.info(Objects.toString(msg));
+    }
 
-                               tags = new HashMap();
-                               tag  = (currentTag != null) ? toMap(currentTag) 
: Collections.emptyMap();
+    public void logWarn(Object msg) {
+        LOG.warn(Objects.toString(msg));
+    }
 
-                               for (RangerTagForEval tag : requestTags) {
-                                       tags.put(tag.getType(), toMap(tag));
-                               }
+    public void logError(Object msg) {
+        LOG.error(Objects.toString(msg));
+    }
 
-                               tagNames = getSorted(tags.keySet());
-                       } else {
-                               tags     = Collections.emptyMap();
-                               tagNames = Collections.emptySet();
-                               tag      = Collections.emptyMap();
-                       }
+    public void logFatal(Object msg) {
+        LOG.error(Objects.toString(msg));
+    }
 
-                       initDone = true;
-               }
-       }
+    private Object evaluateScriptImpl(String script) {
+        Object           ret  = null;
+        RangerPerfTracer perf = null;
 
-       private Map<String, Object> getRequestContext() {
-               return accessRequest.getContext();
-       }
+        try {
+            if 
(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_CONDITION_SCRIPT_EVAL)) {
+                perf = 
RangerPerfTracer.getPerfTracer(PERF_POLICY_CONDITION_SCRIPT_EVAL, 
"RangerRequestScriptEvaluator.evaluateScript(requestHash=" + 
accessRequest.hashCode() + ")");
+            }
 
-       private Set<RangerTagForEval> getAllTags() {
-               Set<RangerTagForEval> ret = 
RangerAccessRequestUtil.getRequestTagsFromContext(accessRequest.getContext());
-               if(ret == null) {
-                       if (LOG.isDebugEnabled()) {
-                               String resource = 
accessRequest.getResource().getAsString();
+            String preExec = SCRIPT_SAFE_PREEXEC;
 
-                               
logDebug("RangerRequestScriptEvaluator.getAllTags() - No TAGS. No TAGS for the 
RangerAccessResource=" + resource);
-                       }
-               }
+            if (script.contains(".includes(")) {
+                preExec += SCRIPT_POLYFILL_INCLUDES;
+            }
 
-               return ret;
-       }
+            if (script.contains(".intersects(")) {
+                preExec += SCRIPT_POLYFILL_INTERSECTS;
+            }
 
-       private static Map<String, Object> toMap(RangerTagForEval tag) {
-               Map<String, Object> ret = new HashMap<>();
+            if (JavaScriptEdits.hasDoubleBrackets(script)) {
+                script = JavaScriptEdits.replaceDoubleBrackets(script);
+            }
 
-               if (tag.getAttributes() != null) {
-                       ret.putAll(tag.getAttributes());
-               }
+            ret = scriptEngine.eval(preExec + script, bindings);
+        } catch (NullPointerException nullp) {
+            LOG.error("RangerRequestScriptEvaluator.evaluateScript(): eval 
called with NULL argument(s)", nullp);
+        } catch (ScriptException excp) {
+            LOG.error("RangerRequestScriptEvaluator.evaluateScript(): failed 
to evaluate script", excp);
+        } catch (Throwable t) {
+            LOG.error("RangerRequestScriptEvaluator.evaluateScript(): failed 
to evaluate script", t);
+        } finally {
+            RangerPerfTracer.log(perf);
+        }
 
-               ret.put(SCRIPT_FIELD__TYPE, tag.getType());
-               ret.put(SCRIPT_FIELD__MATCH_TYPE, tag.getMatchType());
+        return ret;
+    }
 
-               return ret;
-       }
+    private String toJson() {
+        RangerPerfTracer perf = null;
 
-       private Collection<String> getSorted(Collection<String> values) {
-               final Collection<String> ret;
+        if 
(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_CONDITION_SCRIPT_TOJSON)) {
+            perf = 
RangerPerfTracer.getPerfTracer(PERF_POLICY_CONDITION_SCRIPT_TOJSON, 
"RangerRequestScriptEvaluator.toJson(requestHash=" + accessRequest.hashCode() + 
")");
+        }
 
-               if (values == null) {
-                       ret = Collections.emptyList();
-               } else if (values.size() > 1) {
-                       List lst = new ArrayList<>(values);
+        Map<String, Object> ret        = new HashMap<>();
+        Map<String, Object> request    = new HashMap<>();
+        Date                accessTime = accessRequest.getAccessTime();
 
-                       Collections.sort(lst);
+        init();
 
-                       ret = lst;
-               } else {
-                       ret = values;
-               }
+        if (accessTime != null) {
+            request.put(SCRIPT_FIELD_ACCESS_TIME, accessTime.getTime());
+        }
 
-               return ret;
-       }
+        request.put(SCRIPT_FIELD_ACCESS_TYPE, accessRequest.getAccessType());
+        request.put(SCRIPT_FIELD_ACTION, accessRequest.getAction());
+        request.put(SCRIPT_FIELD_CLIENT_IP_ADDRESS, 
accessRequest.getClientIPAddress());
+        request.put(SCRIPT_FIELD_CLIENT_TYPE, accessRequest.getClientType());
+        request.put(SCRIPT_FIELD_CLUSTER_NAME, accessRequest.getClusterName());
+        request.put(SCRIPT_FIELD_CLUSTER_TYPE, accessRequest.getClusterType());
+        request.put(SCRIPT_FIELD_FORWARDED_ADDRESSES, 
accessRequest.getForwardedAddresses());
+        request.put(SCRIPT_FIELD_REMOTE_IP_ADDRESS, 
accessRequest.getRemoteIPAddress());
+        request.put(SCRIPT_FIELD_REQUEST_DATA, accessRequest.getRequestData());
 
-       private Map<String, String> copyMap(Map<String, String> obj) { return 
obj == null ? new HashMap<>() : new HashMap<>(obj); }
+        if (accessRequest.getResource() != null) {
+            Map<String, Object> resource = new 
HashMap<>(accessRequest.getResource().getAsMap());
 
-       private List<Object> getUgAttr(String attrName) {
-               List<Object> ret = new ArrayList<>();
+            resource.put(SCRIPT_FIELD__OWNER_USER, 
accessRequest.getResource().getOwnerUser());
 
-               for (String groupName : userGroups) {
-                       Map<String, String> attrs = groupAttrs.get(groupName);
-                       Object      val           = attrs != null ? 
attrs.get(attrName) : null;
+            request.put(SCRIPT_FIELD_RESOURCE, resource);
+        }
 
-                       if (val != null) {
-                               ret.add(val);
-                       }
-               }
+        request.put(SCRIPT_FIELD_RESOURCE_MATCHING_SCOPE, 
accessRequest.getResourceMatchingScope());
 
-               return ret;
-       }
+        request.put(SCRIPT_FIELD_USER, getUser());
+        request.put(SCRIPT_FIELD_USER_GROUPS, userGroups);
+        request.put(SCRIPT_FIELD_USER_ROLES, userRoles);
 
-       private List<Object> getTagAttr(String attrName) {
-               List<Object> ret = new ArrayList<>();
+        request.put(SCRIPT_FIELD_USER_ATTRIBUTES, userAttrs);
 
-               for (String tagName : tagNames) {
-                       Map<String, Object> attrs = tags.get(tagName);
-                       Object              val   = attrs != null ? 
attrs.get(attrName) : null;
+        request.put(SCRIPT_FIELD_USER_GROUP_ATTRIBUTES, groupAttrs);
+        request.put(SCRIPT_FIELD_UGA, new UserGroupsAttributes(userGroups, 
groupAttrs).getAttributes());
 
-                       if (val != null) {
-                               ret.add(val);
-                       }
-               }
+        ret.put(SCRIPT_FIELD_REQUEST, request);
 
-               return ret;
-       }
+        ret.put(SCRIPT_FIELD_TAGS, tags);
+        ret.put(SCRIPT_FIELD_TAG_NAMES, tagNames);
+        ret.put(SCRIPT_FIELD_TAG, tag);
 
-       private Collection<String> getUserAttrNames() {
-               Collection<String> ret = getSorted(userAttrs.keySet());
+        String strRet = JsonUtils.objectToJson(ret);
 
-               if (ret.contains(SCRIPT_FIELD__NAME)) {
-                       ret.remove(SCRIPT_FIELD__NAME);
-               }
+        RangerPerfTracer.log(perf);
 
-               return ret;
-       }
+        return strRet;
+    }
 
-       private Collection<String> getUgAttrNames() {
-               Set<String> ret = new HashSet<>();
+    private Date getAsDate(String value, SimpleDateFormat df) {
+        Date ret = null;
 
-               for (Map<String, String> attrs : groupAttrs.values()) {
-                       ret.addAll(attrs.keySet());
-               }
+        TimeZone savedTimeZone = df.getTimeZone();
+        try {
+            ret = df.parse(value);
+        } catch (ParseException exception) {
+            // Ignore
+        } finally {
+            df.setTimeZone(savedTimeZone);
+        }
 
-               ret.remove(SCRIPT_FIELD__NAME);
+        return ret;
+    }
 
-               return getSorted(ret);
-       }
+    private void init() {
+        if (!initDone) {
+            RangerUserStore                  userStore        = 
RangerAccessRequestUtil.getRequestUserStoreFromContext(accessRequest.getContext());
+            Map<String, Map<String, String>> userAttrMapping  = userStore != 
null ? userStore.getUserAttrMapping() : Collections.emptyMap();
+            Map<String, Map<String, String>> groupAttrMapping = userStore != 
null ? userStore.getGroupAttrMapping() : Collections.emptyMap();
 
-       private Collection<String> getTagAttrNames() {
-               Set<String> ret = new HashSet<>();
+            userGroups = getSorted(getUserGroups());
+            userRoles  = getSorted(getUserRoles());
+            userAttrs  = copyMap(userAttrMapping.get(accessRequest.getUser()));
+            groupAttrs = new HashMap<>();
 
-               for (Map<String, Object> attrs : tags.values()) {
-                       ret.addAll(attrs.keySet());
-               }
+            userAttrs.put(SCRIPT_FIELD__NAME, getUser());
 
-               ret.remove(SCRIPT_FIELD__TYPE);
-               ret.remove(SCRIPT_FIELD__MATCH_TYPE);
+            for (String groupName : userGroups) {
+                Map<String, String> attrs = groupAttrMapping.get(groupName);
 
-               return getSorted(ret);
-       }
+                attrs = attrs != null ? new HashMap<>(attrs) : new HashMap<>();
 
-       private String toCsv(Collection<? extends Object> values, Object[] 
args) {
-               StringBuilder sb        = new StringBuilder();
-               String        separator = getSeparator(args);
+                attrs.put(SCRIPT_FIELD__NAME, groupName);
 
-               for (Object value : values) {
-                       if (value == null) {
-                               continue;
-                       }
+                groupAttrs.put(groupName, attrs);
+            }
 
-                       if (sb.length() > 0) {
-                               sb.append(separator);
-                       }
+            Set<RangerTagForEval> requestTags = 
RangerAccessRequestUtil.getRequestTagsFromContext(getRequestContext());
 
-                       sb.append(value);
-               }
+            if (CollectionUtils.isNotEmpty(requestTags)) {
+                RangerTagForEval currentTag = 
RangerAccessRequestUtil.getCurrentTagFromContext(getRequestContext());
 
-               if (sb.length() == 0) {
-                       String defValue = getDefaultValue(args);
+                tag  = (currentTag != null) ? toMap(currentTag) : 
Collections.emptyMap();
+                tags = 
requestTags.stream().collect(Collectors.toMap(RangerTagForEval::getType, 
RangerRequestScriptEvaluator::toMap, (oldVal, newVal) -> newVal));
 
-                       if (defValue != null) {
-                               sb.append(getDefaultValue(args));
-                       }
-               }
+                tagNames = getSorted(tags.keySet());
+            } else {
+                tags     = Collections.emptyMap();
+                tagNames = Collections.emptySet();
+                tag      = Collections.emptyMap();
+            }
 
-               return sb.toString();
-       }
+            initDone = true;
+        }
+    }
 
-       private String toCsvQ(Collection<? extends Object> values, Object[] 
args) {
-               StringBuilder sb         = new StringBuilder();
-               String        openQuote  = getOpenQuote(args);
-               String        closeQuote = getCloseQuote(args, openQuote);
-               String        separator  = getSeparator(args);
+    private Map<String, Object> getRequestContext() {
+        return accessRequest.getContext();
+    }
 
-               for (Object value : values) {
-                       if (value == null) {
-                               continue;
-                       }
+    private Set<RangerTagForEval> getAllTags() {
+        Set<RangerTagForEval> ret = 
RangerAccessRequestUtil.getRequestTagsFromContext(accessRequest.getContext());
+        if (ret == null) {
+            if (LOG.isDebugEnabled()) {
+                String resource = accessRequest.getResource().getAsString();
 
-                       if (sb.length() > 0) {
-                               sb.append(separator);
-                       }
+                logDebug("RangerRequestScriptEvaluator.getAllTags() - No TAGS. 
No TAGS for the RangerAccessResource=" + resource);
+            }
+        }
 
-                       sb.append(openQuote).append(value).append(closeQuote);
-               }
+        return ret;
+    }
 
-               if (sb.length() == 0) {
-                       String defValue = getDefaultValue(args);
+    private static Map<String, Object> toMap(RangerTagForEval tag) {
+        Map<String, Object> ret = new HashMap<>();
 
-                       if (defValue != null) {
-                               
sb.append(openQuote).append(getDefaultValue(args)).append(closeQuote);
-                       }
-               }
+        if (tag.getAttributes() != null) {
+            ret.putAll(tag.getAttributes());
+        }
 
-               return sb.toString();
-       }
+        ret.put(SCRIPT_FIELD__TYPE, tag.getType());
+        ret.put(SCRIPT_FIELD__MATCH_TYPE, tag.getMatchType());
 
-       private String getDefaultValue(Object[] args) {
-               Object ret = (args != null && args.length > 0) ? args[0] : null;
+        return ret;
+    }
 
-               return ret != null ? ret.toString() : null;
-       }
+    private Collection<String> getSorted(Collection<String> values) {
+        final Collection<String> ret;
 
-       private String getSeparator(Object[] args) {
-               Object ret = (args != null && args.length > 1) ? args[1] : 
STR_COMMA;
+        if (values == null) {
+            ret = Collections.emptyList();
+        } else if (values.size() > 1) {
+            List<String> lst = new ArrayList<>(values);
 
-               return ret != null ? ret.toString() : "";
-       }
+            Collections.sort(lst);
 
-       private String getOpenQuote(Object[] args) {
-               Object ret = (args != null && args.length > 2) ? args[2] : 
STR_QUOTE;
+            ret = lst;
+        } else {
+            ret = values;
+        }
 
-               return ret != null ? ret.toString() : "";
-       }
+        return ret;
+    }
 
-       private String getCloseQuote(Object[] args, String openQuote) {
-               Object ret = (args != null && args.length > 3) ? args[3] : null;
+    private Map<String, String> copyMap(Map<String, String> obj) {
+        return obj == null ? new HashMap<>() : new HashMap<>(obj);
+    }
 
-               return ret != null ? ret.toString() : openQuote;
-       }
-
-       private static String getJsonVarNamesPattern() {
-               List<String> varNames = new ArrayList<>();
-
-               /* include only variables setup by JSON.parse()
-                *
-               varNames.add(SCRIPT_VAR_ctx);
-               varNames.add(SCRIPT_VAR_tag);
-               varNames.add(SCRIPT_VAR_tagAttr);
-                *
-                */
-               varNames.add(SCRIPT_VAR__CTX);
-               varNames.add(SCRIPT_VAR_REQ);
-               varNames.add(SCRIPT_VAR_RES);
-               varNames.add(SCRIPT_VAR_TAG);
-               varNames.add(SCRIPT_VAR_TAGNAMES);
-               varNames.add(SCRIPT_VAR_TAGS);
-               varNames.add(SCRIPT_VAR_UGA);
-               varNames.add(SCRIPT_VAR_UG);
-               varNames.add(SCRIPT_VAR_UGNAMES);
-               varNames.add(SCRIPT_VAR_URNAMES);
-               varNames.add(SCRIPT_VAR_USER);
-
-               return "\\b(" + StringUtils.join(varNames, '|') + ")\\b";
-       }
-
-       private static String getUserAttributesPattern() {
-               List<String> varNames = new ArrayList<>();
-
-               varNames.add(SCRIPT_VAR_USER);
-
-               varNames.add(SCRIPT_MACRO_GET_USER_ATTR);
-               varNames.add(SCRIPT_MACRO_GET_USER_ATTR_Q);
-
-               varNames.add(SCRIPT_MACRO_GET_USER_ATTR_NAMES);
-               varNames.add(SCRIPT_MACRO_GET_USER_ATTR_NAMES_Q);
-               varNames.add(SCRIPT_MACRO_USER_ATTR_NAMES_CSV);
-               varNames.add(SCRIPT_MACRO_USER_ATTR_NAMES_Q_CSV);
-
-               varNames.add(SCRIPT_MACRO_HAS_USER_ATTR);
-
-               varNames.add("userAttr");
-               varNames.add("userAttrQ");
-               varNames.add("userAttrNames");
-               varNames.add("userAttrNamesQ");
-               varNames.add("userAttrNamesCsv");
-               varNames.add("userAttrNamesCsvQ");
-               varNames.add("hasUserAttr");
-
-               return "\\b(" + StringUtils.join(varNames, '|') + ")\\b";
-       }
-
-       private static String getGroupAttributesPattern() {
-               List<String> varNames = new ArrayList<>();
-
-               varNames.add(SCRIPT_VAR_UG);
-               varNames.add(SCRIPT_VAR_UGA);
-
-               varNames.add(SCRIPT_MACRO_GET_UG_ATTR);
-               varNames.add(SCRIPT_MACRO_GET_UG_ATTR_Q);
-               varNames.add(SCRIPT_MACRO_GET_UG_ATTR_CSV);
-               varNames.add(SCRIPT_MACRO_GET_UG_ATTR_Q_CSV);
-
-               varNames.add(SCRIPT_MACRO_GET_UG_ATTR_NAMES);
-               varNames.add(SCRIPT_MACRO_GET_UG_ATTR_NAMES_Q);
-               varNames.add(SCRIPT_MACRO_UG_ATTR_NAMES_CSV);
-               varNames.add(SCRIPT_MACRO_UG_ATTR_NAMES_Q_CSV);
-
-               varNames.add(SCRIPT_MACRO_HAS_UG_ATTR);
-
-               varNames.add("ugAttr");
-               varNames.add("ugAttrQ");
-               varNames.add("ugAttrCsv");
-               varNames.add("ugAttrCsvQ");
-
-               varNames.add("ugAttrNames");
-               varNames.add("ugAttrNamesQ");
-               varNames.add("ugAttrNamesCsv");
-               varNames.add("ugAttrNamesCsvQ");
-
-               varNames.add("hasUgAttr");
-
-               return "\\b(" + StringUtils.join(varNames, '|') + ")\\b";
-       }
-
-       private static Map<String, String> getMacrosMap() {
-               Map<String, String> ret = new HashMap<>();
-
-               ret.put(SCRIPT_MACRO_GET_TAG_NAMES,         "ctx.tagNames");
-               ret.put(SCRIPT_MACRO_GET_TAG_NAMES_Q,       "ctx.tagNamesQ");
-               ret.put(SCRIPT_MACRO_GET_TAG_ATTR_NAMES,    "ctx.tagAttrNames");
-               ret.put(SCRIPT_MACRO_GET_TAG_ATTR_NAMES_Q,  
"ctx.tagAttrNamesQ");
-               ret.put(SCRIPT_MACRO_GET_TAG_ATTR,          "ctx.tagAttr");
-               ret.put(SCRIPT_MACRO_GET_TAG_ATTR_Q,        "ctx.tagAttrQ");
-               ret.put(SCRIPT_MACRO_GET_UG_NAMES,          "ctx.ugNames");
-               ret.put(SCRIPT_MACRO_GET_UG_NAMES_Q,        "ctx.ugNamesQ");
-               ret.put(SCRIPT_MACRO_GET_UG_ATTR_NAMES,     "ctx.ugAttrNames");
-               ret.put(SCRIPT_MACRO_GET_UG_ATTR_NAMES_Q,   "ctx.ugAttrNamesQ");
-               ret.put(SCRIPT_MACRO_GET_UG_ATTR,           "ctx.ugAttr");
-               ret.put(SCRIPT_MACRO_GET_UG_ATTR_Q,         "ctx.ugAttrQ");
-               ret.put(SCRIPT_MACRO_GET_UR_NAMES,          "ctx.urNames");
-               ret.put(SCRIPT_MACRO_GET_UR_NAMES_Q,        "ctx.urNamesQ");
-               ret.put(SCRIPT_MACRO_GET_USER_ATTR_NAMES,   
"ctx.userAttrNames");
-               ret.put(SCRIPT_MACRO_GET_USER_ATTR_NAMES_Q, 
"ctx.userAttrNamesQ");
-               ret.put(SCRIPT_MACRO_GET_USER_ATTR,         "ctx.userAttr");
-               ret.put(SCRIPT_MACRO_GET_USER_ATTR_Q,       "ctx.userAttrQ");
-
-               ret.put(SCRIPT_MACRO_GET_TAG_ATTR_CSV,      "ctx.tagAttrCsv");
-               ret.put(SCRIPT_MACRO_GET_TAG_ATTR_Q_CSV,    "ctx.tagAttrCsvQ");
-               ret.put(SCRIPT_MACRO_GET_UG_ATTR_CSV,       "ctx.ugAttrCsv");
-               ret.put(SCRIPT_MACRO_GET_UG_ATTR_Q_CSV,     "ctx.ugAttrCsvQ");
-               ret.put(SCRIPT_MACRO_TAG_ATTR_NAMES_CSV,    
"ctx.tagAttrNamesCsv()");
-               ret.put(SCRIPT_MACRO_TAG_ATTR_NAMES_Q_CSV,  
"ctx.tagAttrNamesCsvQ()");
-               ret.put(SCRIPT_MACRO_TAG_NAMES_CSV,         
"ctx.tagNamesCsv()");
-               ret.put(SCRIPT_MACRO_TAG_NAMES_Q_CSV,       
"ctx.tagNamesCsvQ()");
-               ret.put(SCRIPT_MACRO_UG_ATTR_NAMES_CSV,     
"ctx.ugAttrNamesCsv()");
-               ret.put(SCRIPT_MACRO_UG_ATTR_NAMES_Q_CSV,   
"ctx.ugAttrNamesCsvQ()");
-               ret.put(SCRIPT_MACRO_UG_NAMES_CSV,          "ctx.ugNamesCsv()");
-               ret.put(SCRIPT_MACRO_UG_NAMES_Q_CSV,        
"ctx.ugNamesCsvQ()");
-               ret.put(SCRIPT_MACRO_UR_NAMES_CSV,          "ctx.urNamesCsv()");
-               ret.put(SCRIPT_MACRO_UR_NAMES_Q_CSV,        
"ctx.urNamesCsvQ()");
-               ret.put(SCRIPT_MACRO_USER_ATTR_NAMES_CSV,   
"ctx.userAttrNamesCsv()");
-               ret.put(SCRIPT_MACRO_USER_ATTR_NAMES_Q_CSV, 
"ctx.userAttrNamesCsvQ()");
-               ret.put(SCRIPT_MACRO_HAS_TAG,               "ctx.hasTag");
-               ret.put(SCRIPT_MACRO_HAS_ANY_TAG,           "ctx.hasAnyTag()");
-               ret.put(SCRIPT_MACRO_HAS_NO_TAG,            "!ctx.hasAnyTag()");
-               ret.put(SCRIPT_MACRO_HAS_USER_ATTR,         "ctx.hasUserAttr");
-               ret.put(SCRIPT_MACRO_HAS_UG_ATTR,           "ctx.hasUgAttr");
-               ret.put(SCRIPT_MACRO_HAS_TAG_ATTR,          "ctx.hasTagAttr");
-               ret.put(SCRIPT_MACRO_IS_IN_GROUP,           "ctx.isInGroup");
-               ret.put(SCRIPT_MACRO_IS_IN_ROLE,            "ctx.isInRole");
-               ret.put(SCRIPT_MACRO_IS_IN_ANY_GROUP,       
"ctx.isInAnyGroup()");
-               ret.put(SCRIPT_MACRO_IS_IN_ANY_ROLE,        
"ctx.isInAnyRole()");
-               ret.put(SCRIPT_MACRO_IS_NOT_IN_ANY_GROUP,   
"!ctx.isInAnyGroup()");
-               ret.put(SCRIPT_MACRO_IS_NOT_IN_ANY_ROLE,    
"!ctx.isInAnyRole()");
-               ret.put(SCRIPT_MACRO_IS_ACCESS_TIME_AFTER,   
"ctx.isAccessTimeAfter");
-               ret.put(SCRIPT_MACRO_IS_ACCESS_TIME_BEFORE,  
"ctx.isAccessTimeBefore");
-               ret.put(SCRIPT_MACRO_IS_ACCESS_TIME_BETWEEN, 
"ctx.isAccessTimeBetween");
-
-               return ret;
-       }
-
-
-       public void logDebug(Object msg) {
-               LOG.debug("", msg);
-       }
-
-       public void logInfo(Object msg) {
-               LOG.info("", msg);
-       }
-
-       public void logWarn(Object msg) {
-               LOG.warn("", msg);
-       }
-
-       public void logError(Object msg) {
-               LOG.error("", msg);
-       }
-
-       public void logFatal(Object msg) {
-               LOG.error("", msg);
-       }
-
-       public static class UserGroupsAttributes {
-               private final Collection<String>               groupNames;
-               private final Map<String, Map<String, String>> groupAttributes;
-
-               public UserGroupsAttributes(Collection<String> groupNames, 
Map<String, Map<String, String>> groupAttributes) {
-                       this.groupNames      = groupNames;
-                       this.groupAttributes = groupAttributes;
-               }
-
-               /*
-                 {
-                   sVal: {
-                     attr1: val1,
-                     attr2: val2
-                   },
-                   mVal: {
-                     attr1: [ val1, val1_2 ],
-                     attr2: [ val2, val2_2 ]
-                   }
-                 }
-                */
-               public Map<String, Map<String, Object>> getAttributes() {
-                       Map<String, Map<String, Object>> ret       = new 
HashMap<>();
-                       Map<String, String>              valueMap  = new 
HashMap<>();
-                       Map<String, List<String>>        valuesMap = new 
HashMap<>();
-
-                       ret.put("sVal", (Map) valueMap);
-                       ret.put("mVal", (Map) valuesMap);
-
-                       if (groupNames != null && groupAttributes != null) {
-                               for (String groupName : groupNames) {
-                                       Map<String, String> attributes = 
groupAttributes.get(groupName);
-
-                                       if (attributes != null) {
-                                               for (Map.Entry<String, String> 
entry : attributes.entrySet()) {
-                                                       String attrName  = 
entry.getKey();
-                                                       String attrValue = 
entry.getValue();
-
-                                                       if 
(!valueMap.containsKey(attrName)) {
-                                                               
valueMap.put(attrName, attrValue);
-                                                       }
-
-                                                       List<String> values = 
valuesMap.get(attrName);
-
-                                                       if (values == null) {
-                                                               values = new 
ArrayList<>();
-
-                                                               
valuesMap.put(attrName, values);
-                                                       }
-
-                                                       values.add(attrValue);
-                                               }
-                                       }
-                               }
-                       }
-
-                       return ret;
-               }
-       }
+    private List<Object> getUgAttr(String attrName) {
+        return userGroups.stream()
+                .map(groupAttrs::get)
+                .filter(Objects::nonNull)
+                .map(attrs -> attrs.get(attrName))
+                .filter(Objects::nonNull)
+                .collect(Collectors.toList());
+    }
+
+    private List<Object> getTagAttr(String attrName) {
+        return tagNames.stream()
+                .map(tags::get)
+                .filter(Objects::nonNull)
+                .map(attrs -> attrs.get(attrName))
+                .filter(Objects::nonNull)
+                .collect(Collectors.toList());
+    }
+
+    private Collection<String> getUserAttrNames() {
+        Collection<String> ret = getSorted(userAttrs.keySet());
+
+        if (ret.contains(SCRIPT_FIELD__NAME)) { // this is needed to avoid 
calling remove() on unmodifiable collection
+            ret.remove(SCRIPT_FIELD__NAME);
+        }
+
+        return ret;
+    }
+
+    private Collection<String> getUgAttrNames() {
+        return getSorted(
+                groupAttrs.values().stream()
+                        .flatMap(attrs -> attrs.keySet().stream())
+                        .filter(attr -> !SCRIPT_FIELD__NAME.equals(attr))
+                        .collect(Collectors.toSet()));
+    }
+
+    private Collection<String> getTagAttrNames() {
+        return getSorted(
+                tags.values().stream()
+                        .flatMap(attrs -> attrs.keySet().stream())
+                        .filter(attr -> !SCRIPT_FIELD__TYPE.equals(attr) && 
!SCRIPT_FIELD__MATCH_TYPE.equals(attr))
+                        .collect(Collectors.toSet()));
+    }
+
+    private String toCsv(Collection<?> values, Object[] args) {
+        String separator = getSeparator(args);
+        String ret       = 
values.stream().filter(Objects::nonNull).map(String::valueOf).collect(Collectors.joining(separator));
+
+        if (StringUtils.isEmpty(ret)) {
+            ret = getDefaultValue(args);
+        }
+
+        return ret == null ? StringUtils.EMPTY : ret;
+    }
+
+    private String toCsvQ(Collection<?> values, Object[] args) {
+        String openQuote  = getOpenQuote(args);
+        String closeQuote = getCloseQuote(args, openQuote);
+        String separator  = getSeparator(args);
+        String ret        = values.stream().filter(Objects::nonNull).map(value 
-> openQuote + value + closeQuote).collect(Collectors.joining(separator));
+
+        if (StringUtils.isEmpty(ret)) {
+            String defValue = getDefaultValue(args);
+
+            if (defValue != null) {
+                ret = (openQuote + defValue + closeQuote);
+            }
+        }
+
+        return ret;
+    }
+
+    private String getDefaultValue(Object[] args) {
+        Object ret = (args != null && args.length > 0) ? args[0] : null;
+
+        return ret != null ? ret.toString() : null;
+    }
+
+    private String getSeparator(Object[] args) {
+        Object ret = (args != null && args.length > 1) ? args[1] : STR_COMMA;
+
+        return ret != null ? ret.toString() : "";
+    }
+
+    private String getOpenQuote(Object[] args) {
+        Object ret = (args != null && args.length > 2) ? args[2] : STR_QUOTE;
+
+        return ret != null ? ret.toString() : "";
+    }
+
+    private String getCloseQuote(Object[] args, String openQuote) {
+        Object ret = (args != null && args.length > 3) ? args[3] : null;
+
+        return ret != null ? ret.toString() : openQuote;
+    }
+
+    private static String getJsonVarNamesPattern() {
+        List<String> varNames = new ArrayList<>();
+
+        /* include only variables setup by JSON.parse()
+         *
+        varNames.add(SCRIPT_VAR_ctx);
+        varNames.add(SCRIPT_VAR_tag);
+        varNames.add(SCRIPT_VAR_tagAttr);
+         *
+         */
+        varNames.add(SCRIPT_VAR__CTX);
+        varNames.add(SCRIPT_VAR_REQ);
+        varNames.add(SCRIPT_VAR_RES);
+        varNames.add(SCRIPT_VAR_TAG);
+        varNames.add(SCRIPT_VAR_TAGNAMES);
+        varNames.add(SCRIPT_VAR_TAGS);
+        varNames.add(SCRIPT_VAR_UGA);
+        varNames.add(SCRIPT_VAR_UG);
+        varNames.add(SCRIPT_VAR_UGNAMES);
+        varNames.add(SCRIPT_VAR_URNAMES);
+        varNames.add(SCRIPT_VAR_USER);
+
+        return "\\b(" + StringUtils.join(varNames, '|') + ")\\b";
+    }
+
+    private static String getUserAttributesPattern() {
+        List<String> varNames = new ArrayList<>();
+
+        varNames.add(SCRIPT_VAR_USER);
+
+        varNames.add(SCRIPT_MACRO_GET_USER_ATTR);
+        varNames.add(SCRIPT_MACRO_GET_USER_ATTR_Q);
+
+        varNames.add(SCRIPT_MACRO_GET_USER_ATTR_NAMES);
+        varNames.add(SCRIPT_MACRO_GET_USER_ATTR_NAMES_Q);
+        varNames.add(SCRIPT_MACRO_USER_ATTR_NAMES_CSV);
+        varNames.add(SCRIPT_MACRO_USER_ATTR_NAMES_Q_CSV);
+
+        varNames.add(SCRIPT_MACRO_HAS_USER_ATTR);
+
+        varNames.add("userAttr");
+        varNames.add("userAttrQ");
+        varNames.add("userAttrNames");
+        varNames.add("userAttrNamesQ");
+        varNames.add("userAttrNamesCsv");
+        varNames.add("userAttrNamesCsvQ");
+        varNames.add("hasUserAttr");
+
+        return "\\b(" + StringUtils.join(varNames, '|') + ")\\b";
+    }
+
+    private static String getGroupAttributesPattern() {
+        List<String> varNames = new ArrayList<>();
+
+        varNames.add(SCRIPT_VAR_UG);
+        varNames.add(SCRIPT_VAR_UGA);
+
+        varNames.add(SCRIPT_MACRO_GET_UG_ATTR);
+        varNames.add(SCRIPT_MACRO_GET_UG_ATTR_Q);
+        varNames.add(SCRIPT_MACRO_GET_UG_ATTR_CSV);
+        varNames.add(SCRIPT_MACRO_GET_UG_ATTR_Q_CSV);
+
+        varNames.add(SCRIPT_MACRO_GET_UG_ATTR_NAMES);
+        varNames.add(SCRIPT_MACRO_GET_UG_ATTR_NAMES_Q);
+        varNames.add(SCRIPT_MACRO_UG_ATTR_NAMES_CSV);
+        varNames.add(SCRIPT_MACRO_UG_ATTR_NAMES_Q_CSV);
+
+        varNames.add(SCRIPT_MACRO_HAS_UG_ATTR);
+
+        varNames.add("ugAttr");
+        varNames.add("ugAttrQ");
+        varNames.add("ugAttrCsv");
+        varNames.add("ugAttrCsvQ");
+
+        varNames.add("ugAttrNames");
+        varNames.add("ugAttrNamesQ");
+        varNames.add("ugAttrNamesCsv");
+        varNames.add("ugAttrNamesCsvQ");
+
+        varNames.add("hasUgAttr");
+
+        return "\\b(" + StringUtils.join(varNames, '|') + ")\\b";
+    }
+
+    private static Map<String, String> getMacrosMap() {
+        Map<String, String> ret = new HashMap<>();
+
+        ret.put(SCRIPT_MACRO_GET_TAG_NAMES, "ctx.tagNames");
+        ret.put(SCRIPT_MACRO_GET_TAG_NAMES_Q, "ctx.tagNamesQ");
+        ret.put(SCRIPT_MACRO_GET_TAG_ATTR_NAMES, "ctx.tagAttrNames");
+        ret.put(SCRIPT_MACRO_GET_TAG_ATTR_NAMES_Q, "ctx.tagAttrNamesQ");
+        ret.put(SCRIPT_MACRO_GET_TAG_ATTR, "ctx.tagAttr");
+        ret.put(SCRIPT_MACRO_GET_TAG_ATTR_Q, "ctx.tagAttrQ");
+        ret.put(SCRIPT_MACRO_GET_UG_NAMES, "ctx.ugNames");
+        ret.put(SCRIPT_MACRO_GET_UG_NAMES_Q, "ctx.ugNamesQ");
+        ret.put(SCRIPT_MACRO_GET_UG_ATTR_NAMES, "ctx.ugAttrNames");
+        ret.put(SCRIPT_MACRO_GET_UG_ATTR_NAMES_Q, "ctx.ugAttrNamesQ");
+        ret.put(SCRIPT_MACRO_GET_UG_ATTR, "ctx.ugAttr");
+        ret.put(SCRIPT_MACRO_GET_UG_ATTR_Q, "ctx.ugAttrQ");
+        ret.put(SCRIPT_MACRO_GET_UR_NAMES, "ctx.urNames");
+        ret.put(SCRIPT_MACRO_GET_UR_NAMES_Q, "ctx.urNamesQ");
+        ret.put(SCRIPT_MACRO_GET_USER_ATTR_NAMES, "ctx.userAttrNames");
+        ret.put(SCRIPT_MACRO_GET_USER_ATTR_NAMES_Q, "ctx.userAttrNamesQ");
+        ret.put(SCRIPT_MACRO_GET_USER_ATTR, "ctx.userAttr");
+        ret.put(SCRIPT_MACRO_GET_USER_ATTR_Q, "ctx.userAttrQ");
+
+        ret.put(SCRIPT_MACRO_GET_TAG_ATTR_CSV, "ctx.tagAttrCsv");
+        ret.put(SCRIPT_MACRO_GET_TAG_ATTR_Q_CSV, "ctx.tagAttrCsvQ");
+        ret.put(SCRIPT_MACRO_GET_UG_ATTR_CSV, "ctx.ugAttrCsv");
+        ret.put(SCRIPT_MACRO_GET_UG_ATTR_Q_CSV, "ctx.ugAttrCsvQ");
+        ret.put(SCRIPT_MACRO_TAG_ATTR_NAMES_CSV, "ctx.tagAttrNamesCsv()");
+        ret.put(SCRIPT_MACRO_TAG_ATTR_NAMES_Q_CSV, "ctx.tagAttrNamesCsvQ()");
+        ret.put(SCRIPT_MACRO_TAG_NAMES_CSV, "ctx.tagNamesCsv()");
+        ret.put(SCRIPT_MACRO_TAG_NAMES_Q_CSV, "ctx.tagNamesCsvQ()");
+        ret.put(SCRIPT_MACRO_UG_ATTR_NAMES_CSV, "ctx.ugAttrNamesCsv()");
+        ret.put(SCRIPT_MACRO_UG_ATTR_NAMES_Q_CSV, "ctx.ugAttrNamesCsvQ()");
+        ret.put(SCRIPT_MACRO_UG_NAMES_CSV, "ctx.ugNamesCsv()");
+        ret.put(SCRIPT_MACRO_UG_NAMES_Q_CSV, "ctx.ugNamesCsvQ()");
+        ret.put(SCRIPT_MACRO_UR_NAMES_CSV, "ctx.urNamesCsv()");
+        ret.put(SCRIPT_MACRO_UR_NAMES_Q_CSV, "ctx.urNamesCsvQ()");
+        ret.put(SCRIPT_MACRO_USER_ATTR_NAMES_CSV, "ctx.userAttrNamesCsv()");
+        ret.put(SCRIPT_MACRO_USER_ATTR_NAMES_Q_CSV, "ctx.userAttrNamesCsvQ()");
+        ret.put(SCRIPT_MACRO_HAS_TAG, "ctx.hasTag");
+        ret.put(SCRIPT_MACRO_HAS_ANY_TAG, "ctx.hasAnyTag()");
+        ret.put(SCRIPT_MACRO_HAS_NO_TAG, "!ctx.hasAnyTag()");
+        ret.put(SCRIPT_MACRO_HAS_USER_ATTR, "ctx.hasUserAttr");
+        ret.put(SCRIPT_MACRO_HAS_UG_ATTR, "ctx.hasUgAttr");
+        ret.put(SCRIPT_MACRO_HAS_TAG_ATTR, "ctx.hasTagAttr");
+        ret.put(SCRIPT_MACRO_IS_IN_GROUP, "ctx.isInGroup");
+        ret.put(SCRIPT_MACRO_IS_IN_ROLE, "ctx.isInRole");
+        ret.put(SCRIPT_MACRO_IS_IN_ANY_GROUP, "ctx.isInAnyGroup()");
+        ret.put(SCRIPT_MACRO_IS_IN_ANY_ROLE, "ctx.isInAnyRole()");
+        ret.put(SCRIPT_MACRO_IS_NOT_IN_ANY_GROUP, "!ctx.isInAnyGroup()");
+        ret.put(SCRIPT_MACRO_IS_NOT_IN_ANY_ROLE, "!ctx.isInAnyRole()");
+        ret.put(SCRIPT_MACRO_IS_ACCESS_TIME_AFTER, "ctx.isAccessTimeAfter");
+        ret.put(SCRIPT_MACRO_IS_ACCESS_TIME_BEFORE, "ctx.isAccessTimeBefore");
+        ret.put(SCRIPT_MACRO_IS_ACCESS_TIME_BETWEEN, 
"ctx.isAccessTimeBetween");
+
+        return ret;
+    }
+
+    public static class UserGroupsAttributes {
+        private final Collection<String>               groupNames;
+        private final Map<String, Map<String, String>> groupAttributes;
+
+        public UserGroupsAttributes(Collection<String> groupNames, Map<String, 
Map<String, String>> groupAttributes) {
+            this.groupNames      = groupNames;
+            this.groupAttributes = groupAttributes;
+        }
+
+        /*
+          {
+            sVal: {
+              attr1: val1,
+              attr2: val2
+            },
+            mVal: {
+              attr1: [ val1, val1_2 ],
+              attr2: [ val2, val2_2 ]
+            }
+          }
+         */
+        public Map<String, Map<String, Object>> getAttributes() {
+            Map<String, Map<String, Object>> ret       = new HashMap<>();
+            Map<String, String>              valueMap  = new HashMap<>();
+            Map<String, List<String>>        valuesMap = new HashMap<>();
+
+            ret.put("sVal", (Map) valueMap);
+            ret.put("mVal", (Map) valuesMap);
+
+            if (groupNames != null && groupAttributes != null) {
+                for (String groupName : groupNames) {
+                    Map<String, String> attributes = 
groupAttributes.get(groupName);
+
+                    if (attributes != null) {
+                        for (Map.Entry<String, String> entry : 
attributes.entrySet()) {
+                            String attrName  = entry.getKey();
+                            String attrValue = entry.getValue();
+
+                            if (!valueMap.containsKey(attrName)) {
+                                valueMap.put(attrName, attrValue);
+                            }
+
+                            List<String> values = 
valuesMap.computeIfAbsent(attrName, k -> new ArrayList<>());
+
+                            values.add(attrValue);
+                        }
+                    }
+                }
+            }
+
+            return ret;
+        }
+    }
+
+    static {
+        init(null);
+    }
 }


Reply via email to