RangerPolicyRepository(ServicePolicies servicePolicies, RangerPolicyEngineOptions options) {
    super();

    serviceName = servicePolicies.getServiceName();
    serviceDef = servicePolicies.getServiceDef();
    policies = Collections.unmodifiableList(servicePolicies.getPolicies());
    policyVersion =
        servicePolicies.getPolicyVersion() != null
            ? servicePolicies.getPolicyVersion().longValue()
            : -1;

    List<RangerContextEnricher> contextEnrichers = new ArrayList<RangerContextEnricher>();
    if (!options.disableContextEnrichers
        && !CollectionUtils.isEmpty(serviceDef.getContextEnrichers())) {
      for (RangerServiceDef.RangerContextEnricherDef enricherDef :
          serviceDef.getContextEnrichers()) {
        if (enricherDef == null) {
          continue;
        }

        RangerContextEnricher contextEnricher = buildContextEnricher(enricherDef);

        if (contextEnricher != null) {
          contextEnrichers.add(contextEnricher);
        }
      }
    }
    this.contextEnrichers = Collections.unmodifiableList(contextEnrichers);

    List<RangerPolicyEvaluator> policyEvaluators = new ArrayList<RangerPolicyEvaluator>();
    for (RangerPolicy policy : servicePolicies.getPolicies()) {
      if (!policy.getIsEnabled()) {
        continue;
      }

      RangerPolicyEvaluator evaluator = buildPolicyEvaluator(policy, serviceDef, options);

      if (evaluator != null) {
        policyEvaluators.add(evaluator);
      }
    }
    Collections.sort(policyEvaluators);
    this.policyEvaluators = Collections.unmodifiableList(policyEvaluators);

    String propertyName = "ranger.plugin." + serviceName + ".policyengine.auditcachesize";

    if (options.cacheAuditResults) {
      int auditResultCacheSize =
          RangerConfiguration.getInstance()
              .getInt(propertyName, RANGER_POLICYENGINE_AUDITRESULT_CACHE_SIZE);

      accessAuditCache =
          Collections.synchronizedMap(new CacheMap<String, Boolean>(auditResultCacheSize));
    } else {
      accessAuditCache = null;
    }
  }
  private void runTests(InputStreamReader reader, String testName) {
    PolicyEngineTestCase testCase = gsonBuilder.fromJson(reader, PolicyEngineTestCase.class);

    assertTrue(
        "invalid input: " + testName,
        testCase != null
            && testCase.serviceDef != null
            && testCase.policies != null
            && testCase.tests != null);

    ServicePolicies servicePolicies = new ServicePolicies();
    servicePolicies.setServiceName(testCase.serviceName);
    servicePolicies.setServiceDef(testCase.serviceDef);
    servicePolicies.setPolicies(testCase.policies);

    if (null != testCase.tagPolicyInfo) {
      ServicePolicies.TagPolicies tagPolicies = new ServicePolicies.TagPolicies();
      tagPolicies.setServiceName(testCase.tagPolicyInfo.serviceName);
      tagPolicies.setServiceDef(testCase.tagPolicyInfo.serviceDef);
      tagPolicies.setPolicies(testCase.tagPolicyInfo.tagPolicies);

      servicePolicies.setTagPolicies(tagPolicies);
    }

    RangerPolicyEngineOptions policyEngineOptions = new RangerPolicyEngineOptions();

    policyEngineOptions.disableTagPolicyEvaluation = false;

    boolean useForwardedIPAddress =
        RangerConfiguration.getInstance()
            .getBoolean("ranger.plugin.hive.use.x-forwarded-for.ipaddress", false);
    String trustedProxyAddressString =
        RangerConfiguration.getInstance().get("ranger.plugin.hive.trusted.proxy.ipaddresses");
    String[] trustedProxyAddresses = StringUtils.split(trustedProxyAddressString, ';');
    if (trustedProxyAddresses != null) {
      for (int i = 0; i < trustedProxyAddresses.length; i++) {
        trustedProxyAddresses[i] = trustedProxyAddresses[i].trim();
      }
    }
    policyEngine = new RangerPolicyEngineImpl(testName, servicePolicies, policyEngineOptions);
    policyEngine.setUseForwardedIPAddress(useForwardedIPAddress);
    policyEngine.setTrustedProxyAddresses(trustedProxyAddresses);

    RangerAccessRequest request = null;

    for (TestData test : testCase.tests) {
      request = test.request;
      if (request.getContext().containsKey(RangerAccessRequestUtil.KEY_CONTEXT_TAGS)
          || request
              .getContext()
              .containsKey(RangerAccessRequestUtil.KEY_CONTEXT_REQUESTED_RESOURCES)) {
        // Create a new AccessRequest
        RangerAccessRequestImpl newRequest =
            new RangerAccessRequestImpl(
                request.getResource(),
                request.getAccessType(),
                request.getUser(),
                request.getUserGroups());

        newRequest.setClientType(request.getClientType());
        newRequest.setAccessTime(request.getAccessTime());
        newRequest.setAction(request.getAction());
        newRequest.setRemoteIPAddress(request.getRemoteIPAddress());
        newRequest.setForwardedAddresses(request.getForwardedAddresses());
        newRequest.setRequestData(request.getRequestData());
        newRequest.setSessionId(request.getSessionId());

        Map<String, Object> context = request.getContext();
        String tagsJsonString = (String) context.get(RangerAccessRequestUtil.KEY_CONTEXT_TAGS);
        context.remove(RangerAccessRequestUtil.KEY_CONTEXT_TAGS);

        if (!StringUtils.isEmpty(tagsJsonString)) {
          try {
            Type listType = new TypeToken<List<RangerTag>>() {}.getType();
            List<RangerTag> tagList = gsonBuilder.fromJson(tagsJsonString, listType);

            context.put(RangerAccessRequestUtil.KEY_CONTEXT_TAGS, tagList);
          } catch (Exception e) {
            System.err.println(
                "TestPolicyEngine.runTests(): error parsing TAGS JSON string in file "
                    + testName
                    + ", tagsJsonString="
                    + tagsJsonString
                    + ", exception="
                    + e);
          }
        } else if (request
            .getContext()
            .containsKey(RangerAccessRequestUtil.KEY_CONTEXT_REQUESTED_RESOURCES)) {
          String resourcesJsonString =
              (String) context.get(RangerAccessRequestUtil.KEY_CONTEXT_REQUESTED_RESOURCES);
          context.remove(RangerAccessRequestUtil.KEY_CONTEXT_REQUESTED_RESOURCES);
          if (!StringUtils.isEmpty(resourcesJsonString)) {
            try {
              /*
              Reader stringReader = new StringReader(resourcesJsonString);
              RangerRequestedResources resources = gsonBuilder.fromJson(stringReader, RangerRequestedResources.class);
              */

              Type myType = new TypeToken<RangerRequestedResources>() {}.getType();
              RangerRequestedResources resources =
                  gsonBuilder.fromJson(resourcesJsonString, myType);

              context.put(RangerAccessRequestUtil.KEY_CONTEXT_REQUESTED_RESOURCES, resources);
            } catch (Exception e) {
              System.err.println(
                  "TestPolicyEngine.runTests(): error parsing REQUESTED_RESOURCES string in file "
                      + testName
                      + ", resourcesJsonString="
                      + resourcesJsonString
                      + ", exception="
                      + e);
            }
          }
        }
        newRequest.setContext(context);

        // accessResource.ServiceDef is set here, so that we can skip call to
        // policyEngine.preProcess() which
        // sets the serviceDef in the resource AND calls enrichers. We dont want enrichers to be
        // called when
        // context already contains tags -- This may change when we want enrichers to enrich request
        // in the
        // presence of tags!!!

        // Safe cast
        RangerAccessResourceImpl accessResource = (RangerAccessResourceImpl) request.getResource();
        accessResource.setServiceDef(testCase.serviceDef);

        request = newRequest;

      } else if (!request
          .getContext()
          .containsKey(RangerAccessRequestUtil.KEY_CONTEXT_REQUESTED_RESOURCES)) {
        policyEngine.preProcess(request);
      }

      RangerAccessResultProcessor auditHandler = new RangerDefaultAuditHandler();

      if (test.result != null) {
        RangerAccessResult expected = test.result;
        RangerAccessResult result = policyEngine.isAccessAllowed(request, auditHandler);

        assertNotNull("result was null! - " + test.name, result);
        assertEquals(
            "isAllowed mismatched! - " + test.name, expected.getIsAllowed(), result.getIsAllowed());
        assertEquals(
            "isAudited mismatched! - " + test.name, expected.getIsAudited(), result.getIsAudited());
        assertEquals(
            "policyId mismatched! - " + test.name, expected.getPolicyId(), result.getPolicyId());
      }

      if (test.dataMaskResult != null) {
        RangerDataMaskResult expected = test.dataMaskResult;
        RangerDataMaskResult result = policyEngine.evalDataMaskPolicies(request, auditHandler);

        assertNotNull("result was null! - " + test.name, result);
        assertEquals(
            "maskType mismatched! - " + test.name, expected.getMaskType(), result.getMaskType());
        assertEquals(
            "maskCondition mismatched! - " + test.name,
            expected.getMaskCondition(),
            result.getMaskCondition());
        assertEquals(
            "maskedValue mismatched! - " + test.name,
            expected.getMaskedValue(),
            result.getMaskedValue());
        assertEquals(
            "policyId mismatched! - " + test.name, expected.getPolicyId(), result.getPolicyId());
      }

      if (test.rowFilterResult != null) {
        RangerRowFilterResult expected = test.rowFilterResult;
        RangerRowFilterResult result = policyEngine.evalRowFilterPolicies(request, auditHandler);

        assertNotNull("result was null! - " + test.name, result);
        assertEquals(
            "filterExpr mismatched! - " + test.name,
            expected.getFilterExpr(),
            result.getFilterExpr());
        assertEquals(
            "policyId mismatched! - " + test.name, expected.getPolicyId(), result.getPolicyId());
      }

      if (test.resourceAccessInfo != null) {
        RangerResourceAccessInfo expected = new RangerResourceAccessInfo(test.resourceAccessInfo);
        RangerResourceAccessInfo result = policyEngine.getResourceAccessInfo(test.request);

        assertNotNull("result was null! - " + test.name, result);
        assertEquals(
            "allowedUsers mismatched! - " + test.name,
            expected.getAllowedUsers(),
            result.getAllowedUsers());
        assertEquals(
            "allowedGroups mismatched! - " + test.name,
            expected.getAllowedGroups(),
            result.getAllowedGroups());
        assertEquals(
            "deniedUsers mismatched! - " + test.name,
            expected.getDeniedUsers(),
            result.getDeniedUsers());
        assertEquals(
            "deniedGroups mismatched! - " + test.name,
            expected.getDeniedGroups(),
            result.getDeniedGroups());
      }
    }
  }