org.apache.ranger.rest.ServiceREST.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.ranger.rest.ServiceREST.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.ranger.rest;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ranger.admin.client.datatype.RESTResponse;
import org.apache.ranger.authorization.hadoop.config.RangerConfiguration;
import org.apache.ranger.biz.AssetMgr;
import org.apache.ranger.biz.RangerBizUtil;
import org.apache.ranger.biz.ServiceDBStore;
import org.apache.ranger.biz.ServiceMgr;
import org.apache.ranger.biz.TagDBStore;
import org.apache.ranger.biz.XUserMgr;
import org.apache.ranger.common.ContextUtil;
import org.apache.ranger.common.GUIDUtil;
import org.apache.ranger.common.MessageEnums;
import org.apache.ranger.common.PropertiesUtil;
import org.apache.ranger.common.RESTErrorUtil;
import org.apache.ranger.common.RangerSearchUtil;
import org.apache.ranger.common.RangerValidatorFactory;
import org.apache.ranger.common.ServiceUtil;
import org.apache.ranger.common.UserSessionBase;
import org.apache.ranger.db.RangerDaoManager;
import org.apache.ranger.entity.XXPolicyExportAudit;
import org.apache.ranger.entity.XXService;
import org.apache.ranger.entity.XXServiceDef;
import org.apache.ranger.plugin.model.RangerPluginInfo;
import org.apache.ranger.plugin.model.RangerPolicy;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
import org.apache.ranger.plugin.model.RangerService;
import org.apache.ranger.plugin.model.RangerServiceDef;
import org.apache.ranger.plugin.model.validation.RangerPolicyValidator;
import org.apache.ranger.plugin.model.validation.RangerServiceDefValidator;
import org.apache.ranger.plugin.model.validation.RangerServiceValidator;
import org.apache.ranger.plugin.model.validation.RangerValidator.Action;
import org.apache.ranger.plugin.policyengine.RangerAccessResource;
import org.apache.ranger.plugin.policyengine.RangerAccessResourceImpl;
import org.apache.ranger.plugin.policyengine.RangerPolicyEngine;
import org.apache.ranger.plugin.policyengine.RangerPolicyEngineCache;
import org.apache.ranger.plugin.policyengine.RangerPolicyEngineImpl;
import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions;
import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator;
import org.apache.ranger.plugin.service.ResourceLookupContext;
import org.apache.ranger.plugin.store.PList;
import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
import org.apache.ranger.plugin.util.GrantRevokeRequest;
import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
import org.apache.ranger.plugin.util.RangerPerfTracer;
import org.apache.ranger.plugin.util.SearchFilter;
import org.apache.ranger.plugin.util.ServicePolicies;
import org.apache.ranger.security.context.RangerAPIList;
import org.apache.ranger.security.web.filter.RangerCSRFPreventionFilter;
import org.apache.ranger.service.RangerPluginInfoService;
import org.apache.ranger.service.RangerPolicyService;
import org.apache.ranger.service.RangerServiceDefService;
import org.apache.ranger.service.RangerServiceService;
import org.apache.ranger.view.RangerPluginInfoList;
import org.apache.ranger.view.RangerPolicyList;
import org.apache.ranger.view.RangerServiceDefList;
import org.apache.ranger.view.RangerServiceList;
import org.apache.ranger.view.VXResponse;
import org.apache.ranger.view.VXString;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Path("plugins")
@Component
@Scope("request")
@Transactional(propagation = Propagation.REQUIRES_NEW)
public class ServiceREST {
    private static final Log LOG = LogFactory.getLog(ServiceREST.class);
    private static final Log PERF_LOG = RangerPerfTracer.getPerfLogger("rest.ServiceREST");

    final static public String PARAM_SERVICE_NAME = "serviceName";
    final static public String PARAM_POLICY_NAME = "policyName";
    final static public String PARAM_UPDATE_IF_EXISTS = "updateIfExists";
    public static final String Allowed_User_List_For_Download = "policy.download.auth.users";
    public static final String Allowed_User_List_For_Grant_Revoke = "policy.grantrevoke.auth.users";

    public static final String isCSRF_ENABLED = "ranger.rest-csrf.enabled";
    public static final String BROWSER_USER_AGENT_PARAM = "ranger.rest-csrf.browser-useragents-regex";
    public static final String CUSTOM_METHODS_TO_IGNORE_PARAM = "ranger.rest-csrf.methods-to-ignore";
    public static final String CUSTOM_HEADER_PARAM = "ranger.rest-csrf.custom-header";

    @Autowired
    RESTErrorUtil restErrorUtil;

    @Autowired
    ServiceMgr serviceMgr;

    @Autowired
    AssetMgr assetMgr;

    @Autowired
    XUserMgr userMgr;

    @Autowired
    ServiceDBStore svcStore;

    @Autowired
    ServiceUtil serviceUtil;

    @Autowired
    RangerPolicyService policyService;

    @Autowired
    RangerServiceService svcService;

    @Autowired
    RangerServiceDefService serviceDefService;

    @Autowired
    RangerPluginInfoService pluginInfoService;

    @Autowired
    RangerSearchUtil searchUtil;

    @Autowired
    RangerBizUtil bizUtil;

    @Autowired
    GUIDUtil guidUtil;

    @Autowired
    RangerValidatorFactory validatorFactory;

    @Autowired
    RangerDaoManager daoManager;

    @Autowired
    TagDBStore tagStore;

    public ServiceREST() {
    }

    @POST
    @Path("/definitions")
    @Produces({ "application/json", "application/xml" })
    @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.CREATE_SERVICE_DEF + "\")")
    public RangerServiceDef createServiceDef(RangerServiceDef serviceDef) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.createServiceDef(" + serviceDef + ")");
        }

        RangerServiceDef ret = null;
        RangerPerfTracer perf = null;

        try {
            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                perf = RangerPerfTracer.getPerfTracer(PERF_LOG,
                        "ServiceREST.createServiceDef(serviceDefName=" + serviceDef.getName() + ")");
            }
            RangerServiceDefValidator validator = validatorFactory.getServiceDefValidator(svcStore);
            validator.validate(serviceDef, Action.CREATE);

            bizUtil.hasAdminPermissions("Service-Def");
            bizUtil.hasKMSPermissions("Service-Def", serviceDef.getImplClass());

            ret = svcStore.createServiceDef(serviceDef);
        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("createServiceDef(" + serviceDef + ") failed", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        } finally {
            RangerPerfTracer.log(perf);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.createServiceDef(" + serviceDef + "): " + ret);
        }

        return ret;
    }

    @PUT
    @Path("/definitions/{id}")
    @Produces({ "application/json", "application/xml" })
    @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.UPDATE_SERVICE_DEF + "\")")
    public RangerServiceDef updateServiceDef(RangerServiceDef serviceDef) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.updateServiceDef(serviceDefName=" + serviceDef.getName() + ")");
        }

        RangerServiceDef ret = null;
        RangerPerfTracer perf = null;

        try {
            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                perf = RangerPerfTracer.getPerfTracer(PERF_LOG,
                        "ServiceREST.updateServiceDef(" + serviceDef.getName() + ")");
            }
            RangerServiceDefValidator validator = validatorFactory.getServiceDefValidator(svcStore);
            validator.validate(serviceDef, Action.UPDATE);

            bizUtil.hasAdminPermissions("Service-Def");
            bizUtil.hasKMSPermissions("Service-Def", serviceDef.getImplClass());

            ret = svcStore.updateServiceDef(serviceDef);
        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("updateServiceDef(" + serviceDef + ") failed", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        } finally {
            RangerPerfTracer.log(perf);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.updateServiceDef(" + serviceDef + "): " + ret);
        }

        return ret;
    }

    @DELETE
    @Path("/definitions/{id}")
    @Produces({ "application/json", "application/xml" })
    @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.DELETE_SERVICE_DEF + "\")")
    public void deleteServiceDef(@PathParam("id") Long id, @Context HttpServletRequest request) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.deleteServiceDef(" + id + ")");
        }

        RangerPerfTracer perf = null;

        try {
            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                perf = RangerPerfTracer.getPerfTracer(PERF_LOG,
                        "ServiceREST.deleteServiceDef(serviceDefId=" + id + ")");
            }
            RangerServiceDefValidator validator = validatorFactory.getServiceDefValidator(svcStore);
            validator.validate(id, Action.DELETE);

            bizUtil.hasAdminPermissions("Service-Def");
            XXServiceDef xServiceDef = daoManager.getXXServiceDef().getById(id);
            bizUtil.hasKMSPermissions("Service-Def", xServiceDef.getImplclassname());

            String forceDeleteStr = request.getParameter("forceDelete");
            boolean forceDelete = false;
            if (!StringUtils.isEmpty(forceDeleteStr) && forceDeleteStr.equalsIgnoreCase("true")) {
                forceDelete = true;
            }

            svcStore.deleteServiceDef(id, forceDelete);
        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("deleteServiceDef(" + id + ") failed", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        } finally {
            RangerPerfTracer.log(perf);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.deleteServiceDef(" + id + ")");
        }
    }

    @GET
    @Path("/definitions/{id}")
    @Produces({ "application/json", "application/xml" })
    @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.GET_SERVICE_DEF + "\")")
    public RangerServiceDef getServiceDef(@PathParam("id") Long id) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.getServiceDef(" + id + ")");
        }

        RangerServiceDef ret = null;
        RangerPerfTracer perf = null;

        try {
            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                perf = RangerPerfTracer.getPerfTracer(PERF_LOG,
                        "ServiceREST.getServiceDef(serviceDefId=" + id + ")");
            }
            XXServiceDef xServiceDef = daoManager.getXXServiceDef().getById(id);
            if (!bizUtil.hasAccess(xServiceDef, null)) {
                throw restErrorUtil.createRESTException(
                        "User is not allowed to access service-def, id: " + xServiceDef.getId(),
                        MessageEnums.OPER_NO_PERMISSION);
            }

            ret = svcStore.getServiceDef(id);
        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("getServiceDef(" + id + ") failed", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        } finally {
            RangerPerfTracer.log(perf);
        }

        if (ret == null) {
            throw restErrorUtil.createRESTException(HttpServletResponse.SC_NOT_FOUND, "Not found", true);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.getServiceDef(" + id + "): " + ret);
        }

        return ret;
    }

    @GET
    @Path("/definitions/name/{name}")
    @Produces({ "application/json", "application/xml" })
    @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.GET_SERVICE_DEF_BY_NAME
            + "\")")
    public RangerServiceDef getServiceDefByName(@PathParam("name") String name) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.getServiceDefByName(serviceDefName=" + name + ")");
        }

        RangerServiceDef ret = null;
        RangerPerfTracer perf = null;

        try {
            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "ServiceREST.getServiceDefByName(" + name + ")");
            }
            XXServiceDef xServiceDef = daoManager.getXXServiceDef().findByName(name);
            if (xServiceDef != null) {
                if (!bizUtil.hasAccess(xServiceDef, null)) {
                    throw restErrorUtil.createRESTException(
                            "User is not allowed to access service-def: " + xServiceDef.getName(),
                            MessageEnums.OPER_NO_PERMISSION);
                }
            }

            ret = svcStore.getServiceDefByName(name);
        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("getServiceDefByName(" + name + ") failed", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        } finally {
            RangerPerfTracer.log(perf);
        }

        if (ret == null) {
            throw restErrorUtil.createRESTException(HttpServletResponse.SC_NOT_FOUND, "Not found", true);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.getServiceDefByName(" + name + "): " + ret);
        }

        return ret;
    }

    @GET
    @Path("/definitions")
    @Produces({ "application/json", "application/xml" })
    @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.GET_SERVICE_DEFS + "\")")
    public RangerServiceDefList getServiceDefs(@Context HttpServletRequest request) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.getServiceDefs()");
        }

        RangerServiceDefList ret = null;
        RangerPerfTracer perf = null;

        PList<RangerServiceDef> paginatedSvcDefs = null;

        SearchFilter filter = searchUtil.getSearchFilter(request, serviceDefService.sortFields);

        try {
            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "ServiceREST.getServiceDefs()");
            }
            paginatedSvcDefs = svcStore.getPaginatedServiceDefs(filter);

            if (paginatedSvcDefs != null) {
                ret = new RangerServiceDefList();

                ret.setServiceDefs(paginatedSvcDefs.getList());
                ret.setPageSize(paginatedSvcDefs.getPageSize());
                ret.setResultSize(paginatedSvcDefs.getResultSize());
                ret.setStartIndex(paginatedSvcDefs.getStartIndex());
                ret.setTotalCount(paginatedSvcDefs.getTotalCount());
                ret.setSortBy(paginatedSvcDefs.getSortBy());
                ret.setSortType(paginatedSvcDefs.getSortType());
            }
        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("getServiceDefs() failed", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        } finally {
            RangerPerfTracer.log(perf);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.getServiceDefs(): count=" + (ret == null ? 0 : ret.getListSize()));
        }
        return ret;
    }

    @POST
    @Path("/services")
    @Produces({ "application/json", "application/xml" })
    @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.CREATE_SERVICE + "\")")
    public RangerService createService(RangerService service) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.createService(" + service + ")");
        }

        RangerService ret = null;
        RangerPerfTracer perf = null;

        try {
            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                perf = RangerPerfTracer.getPerfTracer(PERF_LOG,
                        "ServiceREST.createService(serviceName=" + service.getName() + ")");
            }
            RangerServiceValidator validator = validatorFactory.getServiceValidator(svcStore);
            validator.validate(service, Action.CREATE);

            UserSessionBase session = ContextUtil.getCurrentUserSession();
            XXServiceDef xxServiceDef = daoManager.getXXServiceDef().findByName(service.getType());
            if (session != null && !session.isSpnegoEnabled()) {
                bizUtil.hasAdminPermissions("Services");

                // TODO: As of now we are allowing SYS_ADMIN to create all the
                // services including KMS
                bizUtil.hasKMSPermissions("Service", xxServiceDef.getImplclassname());
            }
            if (session != null && session.isSpnegoEnabled()) {
                if (session.isKeyAdmin()
                        && !xxServiceDef.getImplclassname().equals(EmbeddedServiceDefsUtil.KMS_IMPL_CLASS_NAME)) {
                    throw restErrorUtil.createRESTException("KeyAdmin can create/update/delete only KMS ",
                            MessageEnums.OPER_NO_PERMISSION);
                }
                if ((!session.isKeyAdmin() && !session.isUserAdmin())
                        && xxServiceDef.getImplclassname().equals(EmbeddedServiceDefsUtil.KMS_IMPL_CLASS_NAME)) {
                    throw restErrorUtil.createRESTException("User cannot create/update/delete KMS Service",
                            MessageEnums.OPER_NO_PERMISSION);
                }
            }
            ret = svcStore.createService(service);
        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("createService(" + service + ") failed", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        } finally {
            RangerPerfTracer.log(perf);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.createService(" + service + "): " + ret);
        }

        return ret;
    }

    @PUT
    @Path("/services/{id}")
    @Produces({ "application/json", "application/xml" })
    @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.UPDATE_SERVICE + "\")")
    public RangerService updateService(RangerService service) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.updateService(): " + service);
        }

        RangerService ret = null;
        RangerPerfTracer perf = null;

        try {
            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                perf = RangerPerfTracer.getPerfTracer(PERF_LOG,
                        "ServiceREST.updateService(serviceName=" + service.getName() + ")");
            }
            RangerServiceValidator validator = validatorFactory.getServiceValidator(svcStore);
            validator.validate(service, Action.UPDATE);

            bizUtil.hasAdminPermissions("Services");

            // TODO: As of now we are allowing SYS_ADMIN to create all the
            // services including KMS

            XXServiceDef xxServiceDef = daoManager.getXXServiceDef().findByName(service.getType());
            bizUtil.hasKMSPermissions("Service", xxServiceDef.getImplclassname());

            ret = svcStore.updateService(service);
        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("updateService(" + service + ") failed", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        } finally {
            RangerPerfTracer.log(perf);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.updateService(" + service + "): " + ret);
        }

        return ret;
    }

    @DELETE
    @Path("/services/{id}")
    @Produces({ "application/json", "application/xml" })
    @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.DELETE_SERVICE + "\")")
    public void deleteService(@PathParam("id") Long id) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.deleteService(" + id + ")");
        }

        RangerPerfTracer perf = null;

        try {
            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "ServiceREST.deleteService(serviceId=" + id + ")");
            }
            RangerServiceValidator validator = validatorFactory.getServiceValidator(svcStore);
            validator.validate(id, Action.DELETE);

            bizUtil.hasAdminPermissions("Services");

            // TODO: As of now we are allowing SYS_ADMIN to create all the
            // services including KMS

            XXService service = daoManager.getXXService().getById(id);
            EmbeddedServiceDefsUtil embeddedServiceDefsUtil = EmbeddedServiceDefsUtil.instance();
            if (service.getType().equals(embeddedServiceDefsUtil.getTagServiceDefId())) {
                List<XXService> referringServices = daoManager.getXXService().findByTagServiceId(id);
                if (!CollectionUtils.isEmpty(referringServices)) {
                    Set<String> referringServiceNames = new HashSet<String>();
                    for (XXService xXService : referringServices) {
                        referringServiceNames.add(xXService.getName());
                        if (referringServiceNames.size() >= 10) {
                            break;
                        }
                    }
                    if (referringServices.size() <= 10) {
                        throw restErrorUtil.createRESTException(
                                "Tag service '" + service.getName() + "' is being referenced by "
                                        + referringServices.size() + " services: " + referringServiceNames,
                                MessageEnums.OPER_NOT_ALLOWED_FOR_STATE);
                    } else {
                        throw restErrorUtil.createRESTException("Tag service '" + service.getName()
                                + "' is being referenced by " + referringServices.size() + " services: "
                                + referringServiceNames + " and more..", MessageEnums.OPER_NOT_ALLOWED_FOR_STATE);
                    }
                }
            }
            XXServiceDef xxServiceDef = daoManager.getXXServiceDef().getById(service.getType());
            bizUtil.hasKMSPermissions("Service", xxServiceDef.getImplclassname());

            tagStore.deleteAllTagObjectsForService(service.getName());

            svcStore.deleteService(id);
        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("deleteService(" + id + ") failed", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        } finally {
            RangerPerfTracer.log(perf);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.deleteService(" + id + ")");
        }
    }

    @GET
    @Path("/services/{id}")
    @Produces({ "application/json", "application/xml" })
    @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.GET_SERVICE + "\")")
    public RangerService getService(@PathParam("id") Long id) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.getService(" + id + ")");
        }

        RangerService ret = null;
        RangerPerfTracer perf = null;

        try {
            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "ServiceREST.getService(serviceId=" + id + ")");
            }
            ret = svcStore.getService(id);
        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("getService(" + id + ") failed", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        } finally {
            RangerPerfTracer.log(perf);
        }

        if (ret == null) {
            throw restErrorUtil.createRESTException(HttpServletResponse.SC_NOT_FOUND, "Not found", true);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.getService(" + id + "): " + ret);
        }

        return ret;
    }

    @GET
    @Path("/services/name/{name}")
    @Produces({ "application/json", "application/xml" })
    @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.GET_SERVICE_BY_NAME + "\")")
    public RangerService getServiceByName(@PathParam("name") String name) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.getServiceByName(" + name + ")");
        }

        RangerService ret = null;
        RangerPerfTracer perf = null;

        try {
            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "ServiceREST.getService(serviceName=" + name + ")");
            }
            ret = svcStore.getServiceByName(name);
        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("getServiceByName(" + name + ") failed", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        } finally {
            RangerPerfTracer.log(perf);
        }

        if (ret == null) {
            throw restErrorUtil.createRESTException(HttpServletResponse.SC_NOT_FOUND, "Not found", true);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.getServiceByName(" + name + "): " + ret);
        }

        return ret;
    }

    @GET
    @Path("/services")
    @Produces({ "application/json", "application/xml" })
    @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.GET_SERVICES + "\")")
    public RangerServiceList getServices(@Context HttpServletRequest request) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.getServices()");
        }

        RangerServiceList ret = null;
        RangerPerfTracer perf = null;

        PList<RangerService> paginatedSvcs = null;

        SearchFilter filter = searchUtil.getSearchFilter(request, svcService.sortFields);

        try {
            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "ServiceREST.getServices()");
            }
            paginatedSvcs = svcStore.getPaginatedServices(filter);

            if (paginatedSvcs != null) {
                ret = new RangerServiceList();

                ret.setServices(paginatedSvcs.getList());
                ret.setPageSize(paginatedSvcs.getPageSize());
                ret.setResultSize(paginatedSvcs.getResultSize());
                ret.setStartIndex(paginatedSvcs.getStartIndex());
                ret.setTotalCount(paginatedSvcs.getTotalCount());
                ret.setSortBy(paginatedSvcs.getSortBy());
                ret.setSortType(paginatedSvcs.getSortType());
            }
        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("getServices() failed", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        } finally {
            RangerPerfTracer.log(perf);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.getServices(): count=" + (ret == null ? 0 : ret.getListSize()));
        }
        return ret;
    }

    public List<RangerService> getServices(SearchFilter filter) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.getServices():");
        }

        List<RangerService> ret = null;
        RangerPerfTracer perf = null;

        try {
            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "ServiceREST.getServices()");
            }
            ret = svcStore.getServices(filter);
        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("getServices() failed", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        } finally {
            RangerPerfTracer.log(perf);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.getServices(): count=" + (ret == null ? 0 : ret.size()));
        }

        return ret;
    }

    @GET
    @Path("/services/count")
    @Produces({ "application/json", "application/xml" })
    @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.COUNT_SERVICES + "\")")
    public Long countServices(@Context HttpServletRequest request) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.countServices():");
        }

        Long ret = null;
        RangerPerfTracer perf = null;

        try {
            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "ServiceREST.countService()");
            }
            List<RangerService> services = getServices(request).getServices();

            ret = Long.valueOf(services == null ? 0 : services.size());
        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("countServices() failed", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        } finally {
            RangerPerfTracer.log(perf);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.countServices(): " + ret);
        }

        return ret;
    }

    @POST
    @Path("/services/validateConfig")
    @Produces({ "application/json", "application/xml" })
    @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.VALIDATE_CONFIG + "\")")
    public VXResponse validateConfig(RangerService service) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.validateConfig(" + service + ")");
        }

        VXResponse ret = new VXResponse();
        RangerPerfTracer perf = null;

        try {
            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                perf = RangerPerfTracer.getPerfTracer(PERF_LOG,
                        "ServiceREST.validateConfig(serviceName=" + service.getName() + ")");
            }
            ret = serviceMgr.validateConfig(service, svcStore);
        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("validateConfig(" + service + ") failed", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        } finally {
            RangerPerfTracer.log(perf);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.validateConfig(" + service + "): " + ret);
        }

        return ret;
    }

    @POST
    @Path("/services/lookupResource/{serviceName}")
    @Produces({ "application/json", "application/xml" })
    @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.LOOKUP_RESOURCE + "\")")
    public List<String> lookupResource(@PathParam("serviceName") String serviceName,
            ResourceLookupContext context) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.lookupResource(" + serviceName + ")");
        }

        List<String> ret = new ArrayList<String>();
        RangerPerfTracer perf = null;

        try {
            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                perf = RangerPerfTracer.getPerfTracer(PERF_LOG,
                        "ServiceREST.lookupResource(serviceName=" + serviceName + ")");
            }
            ret = serviceMgr.lookupResource(serviceName, context, svcStore);
        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("lookupResource(" + serviceName + ", " + context + ") failed", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        } finally {
            RangerPerfTracer.log(perf);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.lookupResource(" + serviceName + "): " + ret);
        }

        return ret;
    }

    @POST
    @Path("/services/grant/{serviceName}")
    @Produces({ "application/json", "application/xml" })
    public RESTResponse grantAccess(@PathParam("serviceName") String serviceName, GrantRevokeRequest grantRequest,
            @Context HttpServletRequest request) throws Exception {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.grantAccess(" + serviceName + ", " + grantRequest + ")");
        }

        RESTResponse ret = new RESTResponse();
        RangerPerfTracer perf = null;

        if (grantRequest != null) {
            if (serviceUtil.isValidateHttpsAuthentication(serviceName, request)) {

                try {
                    if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                        perf = RangerPerfTracer.getPerfTracer(PERF_LOG,
                                "ServiceREST.grantAccess(serviceName=" + serviceName + ")");
                    }

                    validateGrantRevokeRequest(grantRequest);
                    String userName = grantRequest.getGrantor();
                    Set<String> userGroups = userMgr.getGroupsForUser(userName);
                    RangerAccessResource resource = new RangerAccessResourceImpl(grantRequest.getResource());

                    boolean isAdmin = hasAdminAccess(serviceName, userName, userGroups, resource);

                    if (!isAdmin) {
                        throw restErrorUtil.createGrantRevokeRESTException(
                                "User doesn't have necessary permission to grant access");
                    }

                    RangerPolicy policy = getExactMatchPolicyForResource(serviceName, resource, userName);

                    if (policy != null) {
                        boolean policyUpdated = false;
                        policyUpdated = ServiceRESTUtil.processGrantRequest(policy, grantRequest);

                        if (policyUpdated) {
                            svcStore.updatePolicy(policy);
                        } else {
                            LOG.error("processGrantRequest processing failed");
                            throw new Exception("processGrantRequest processing failed");
                        }
                    } else {
                        policy = new RangerPolicy();
                        policy.setService(serviceName);
                        policy.setName("grant-" + System.currentTimeMillis()); // TODO: better policy name
                        policy.setDescription("created by grant");
                        policy.setIsAuditEnabled(grantRequest.getEnableAudit());
                        policy.setCreatedBy(userName);

                        Map<String, RangerPolicyResource> policyResources = new HashMap<String, RangerPolicyResource>();
                        Set<String> resourceNames = resource.getKeys();

                        if (!CollectionUtils.isEmpty(resourceNames)) {
                            for (String resourceName : resourceNames) {
                                RangerPolicyResource policyResource = new RangerPolicyResource(
                                        resource.getValue(resourceName));
                                policyResource.setIsRecursive(grantRequest.getIsRecursive());

                                policyResources.put(resourceName, policyResource);
                            }
                        }
                        policy.setResources(policyResources);

                        RangerPolicyItem policyItem = new RangerPolicyItem();

                        policyItem.setDelegateAdmin(grantRequest.getDelegateAdmin());
                        policyItem.getUsers().addAll(grantRequest.getUsers());
                        policyItem.getGroups().addAll(grantRequest.getGroups());

                        for (String accessType : grantRequest.getAccessTypes()) {
                            policyItem.getAccesses().add(new RangerPolicyItemAccess(accessType, Boolean.TRUE));
                        }

                        policy.getPolicyItems().add(policyItem);

                        svcStore.createPolicy(policy);
                    }
                } catch (WebApplicationException excp) {
                    throw excp;
                } catch (Throwable excp) {
                    LOG.error("grantAccess(" + serviceName + ", " + grantRequest + ") failed", excp);

                    throw restErrorUtil.createRESTException(excp.getMessage());
                } finally {
                    RangerPerfTracer.log(perf);
                }

                ret.setStatusCode(RESTResponse.STATUS_SUCCESS);
            }
        }
        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.grantAccess(" + serviceName + ", " + grantRequest + "): " + ret);
        }

        return ret;
    }

    @POST
    @Path("/secure/services/grant/{serviceName}")
    @Produces({ "application/json", "application/xml" })
    public RESTResponse secureGrantAccess(@PathParam("serviceName") String serviceName,
            GrantRevokeRequest grantRequest, @Context HttpServletRequest request) throws Exception {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.secureGrantAccess(" + serviceName + ", " + grantRequest + ")");
        }
        RESTResponse ret = new RESTResponse();
        RangerPerfTracer perf = null;
        boolean isAllowed = false;
        boolean isKeyAdmin = bizUtil.isKeyAdmin();
        if (grantRequest != null) {
            if (serviceUtil.isValidService(serviceName, request)) {
                try {
                    if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                        perf = RangerPerfTracer.getPerfTracer(PERF_LOG,
                                "ServiceREST.scureGrantAccess(serviceName=" + serviceName + ")");
                    }

                    validateGrantRevokeRequest(grantRequest);

                    String userName = grantRequest.getGrantor();
                    Set<String> userGroups = userMgr.getGroupsForUser(userName);
                    RangerAccessResource resource = new RangerAccessResourceImpl(grantRequest.getResource());
                    boolean isAdmin = hasAdminAccess(serviceName, userName, userGroups, resource);

                    XXService xService = daoManager.getXXService().findByName(serviceName);
                    XXServiceDef xServiceDef = daoManager.getXXServiceDef().getById(xService.getType());
                    RangerService rangerService = svcStore.getServiceByName(serviceName);

                    if (StringUtils.equals(xServiceDef.getImplclassname(),
                            EmbeddedServiceDefsUtil.KMS_IMPL_CLASS_NAME)) {
                        if (isKeyAdmin) {
                            isAllowed = true;
                        } else {
                            isAllowed = bizUtil.isUserAllowedForGrantRevoke(rangerService,
                                    Allowed_User_List_For_Grant_Revoke, userName);
                        }
                    } else {
                        if (isAdmin) {
                            isAllowed = true;
                        } else {
                            isAllowed = bizUtil.isUserAllowedForGrantRevoke(rangerService,
                                    Allowed_User_List_For_Grant_Revoke, userName);
                        }
                    }

                    if (isAllowed) {
                        RangerPolicy policy = getExactMatchPolicyForResource(serviceName, resource, userName);

                        if (policy != null) {
                            boolean policyUpdated = false;
                            policyUpdated = ServiceRESTUtil.processGrantRequest(policy, grantRequest);

                            if (policyUpdated) {
                                svcStore.updatePolicy(policy);
                            } else {
                                LOG.error("processSecureGrantRequest processing failed");
                                throw new Exception("processSecureGrantRequest processing failed");
                            }
                        } else {
                            policy = new RangerPolicy();
                            policy.setService(serviceName);
                            policy.setName("grant-" + System.currentTimeMillis()); // TODO: better policy name
                            policy.setDescription("created by grant");
                            policy.setIsAuditEnabled(grantRequest.getEnableAudit());
                            policy.setCreatedBy(userName);

                            Map<String, RangerPolicyResource> policyResources = new HashMap<String, RangerPolicyResource>();
                            Set<String> resourceNames = resource.getKeys();

                            if (!CollectionUtils.isEmpty(resourceNames)) {
                                for (String resourceName : resourceNames) {
                                    RangerPolicyResource policyResource = new RangerPolicyResource(
                                            resource.getValue(resourceName));
                                    policyResource.setIsRecursive(grantRequest.getIsRecursive());

                                    policyResources.put(resourceName, policyResource);
                                }
                            }
                            policy.setResources(policyResources);

                            RangerPolicyItem policyItem = new RangerPolicyItem();

                            policyItem.setDelegateAdmin(grantRequest.getDelegateAdmin());
                            policyItem.getUsers().addAll(grantRequest.getUsers());
                            policyItem.getGroups().addAll(grantRequest.getGroups());

                            for (String accessType : grantRequest.getAccessTypes()) {
                                policyItem.getAccesses().add(new RangerPolicyItemAccess(accessType, Boolean.TRUE));
                            }

                            policy.getPolicyItems().add(policyItem);

                            svcStore.createPolicy(policy);
                        }
                    } else {
                        LOG.error("secureGrantAccess(" + serviceName + ", " + grantRequest
                                + ") failed as User doesn't have permission to grant Policy");
                        throw restErrorUtil.createGrantRevokeRESTException(
                                "User doesn't have necessary permission to grant access");
                    }
                } catch (WebApplicationException excp) {
                    throw excp;
                } catch (Throwable excp) {
                    LOG.error("secureGrantAccess(" + serviceName + ", " + grantRequest + ") failed", excp);

                    throw restErrorUtil.createRESTException(excp.getMessage());
                } finally {
                    RangerPerfTracer.log(perf);
                }

                ret.setStatusCode(RESTResponse.STATUS_SUCCESS);
            }
        }
        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.secureGrantAccess(" + serviceName + ", " + grantRequest + "): " + ret);
        }
        return ret;
    }

    @POST
    @Path("/services/revoke/{serviceName}")
    @Produces({ "application/json", "application/xml" })
    public RESTResponse revokeAccess(@PathParam("serviceName") String serviceName, GrantRevokeRequest revokeRequest,
            @Context HttpServletRequest request) throws Exception {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.revokeAccess(" + serviceName + ", " + revokeRequest + ")");
        }

        RESTResponse ret = new RESTResponse();
        RangerPerfTracer perf = null;
        if (revokeRequest != null) {
            if (serviceUtil.isValidateHttpsAuthentication(serviceName, request)) {

                try {
                    if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                        perf = RangerPerfTracer.getPerfTracer(PERF_LOG,
                                "ServiceREST.revokeAccess(serviceName=" + serviceName + ")");
                    }

                    validateGrantRevokeRequest(revokeRequest);

                    String userName = revokeRequest.getGrantor();
                    Set<String> userGroups = userMgr.getGroupsForUser(userName);
                    RangerAccessResource resource = new RangerAccessResourceImpl(revokeRequest.getResource());

                    boolean isAdmin = hasAdminAccess(serviceName, userName, userGroups, resource);

                    if (!isAdmin) {
                        throw restErrorUtil.createGrantRevokeRESTException(
                                "User doesn't have necessary permission to revoke access");
                    }

                    RangerPolicy policy = getExactMatchPolicyForResource(serviceName, resource, userName);

                    if (policy != null) {
                        boolean policyUpdated = false;
                        policyUpdated = ServiceRESTUtil.processRevokeRequest(policy, revokeRequest);

                        if (policyUpdated) {
                            svcStore.updatePolicy(policy);
                        } else {
                            LOG.error("processRevokeRequest processing failed");
                            throw new Exception("processRevokeRequest processing failed");
                        }
                    }
                } catch (WebApplicationException excp) {
                    throw excp;
                } catch (Throwable excp) {
                    LOG.error("revokeAccess(" + serviceName + ", " + revokeRequest + ") failed", excp);

                    throw restErrorUtil.createRESTException(excp.getMessage());
                } finally {
                    RangerPerfTracer.log(perf);
                }

                ret.setStatusCode(RESTResponse.STATUS_SUCCESS);
            }
        }
        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.revokeAccess(" + serviceName + ", " + revokeRequest + "): " + ret);
        }

        return ret;
    }

    @POST
    @Path("/secure/services/revoke/{serviceName}")
    @Produces({ "application/json", "application/xml" })
    public RESTResponse secureRevokeAccess(@PathParam("serviceName") String serviceName,
            GrantRevokeRequest revokeRequest, @Context HttpServletRequest request) throws Exception {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.secureRevokeAccess(" + serviceName + ", " + revokeRequest + ")");
        }
        RESTResponse ret = new RESTResponse();
        RangerPerfTracer perf = null;
        if (revokeRequest != null) {
            if (serviceUtil.isValidService(serviceName, request)) {
                try {
                    if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                        perf = RangerPerfTracer.getPerfTracer(PERF_LOG,
                                "ServiceREST.secureRevokeAccess(serviceName=" + serviceName + ")");
                    }

                    validateGrantRevokeRequest(revokeRequest);

                    String userName = revokeRequest.getGrantor();
                    Set<String> userGroups = userMgr.getGroupsForUser(userName);
                    RangerAccessResource resource = new RangerAccessResourceImpl(revokeRequest.getResource());
                    boolean isAdmin = hasAdminAccess(serviceName, userName, userGroups, resource);
                    boolean isAllowed = false;
                    boolean isKeyAdmin = bizUtil.isKeyAdmin();

                    XXService xService = daoManager.getXXService().findByName(serviceName);
                    XXServiceDef xServiceDef = daoManager.getXXServiceDef().getById(xService.getType());
                    RangerService rangerService = svcStore.getServiceByName(serviceName);

                    if (StringUtils.equals(xServiceDef.getImplclassname(),
                            EmbeddedServiceDefsUtil.KMS_IMPL_CLASS_NAME)) {
                        if (isKeyAdmin) {
                            isAllowed = true;
                        } else {
                            isAllowed = bizUtil.isUserAllowedForGrantRevoke(rangerService,
                                    Allowed_User_List_For_Grant_Revoke, userName);
                        }
                    } else {
                        if (isAdmin) {
                            isAllowed = true;
                        } else {
                            isAllowed = bizUtil.isUserAllowedForGrantRevoke(rangerService,
                                    Allowed_User_List_For_Grant_Revoke, userName);
                        }
                    }

                    if (isAllowed) {
                        RangerPolicy policy = getExactMatchPolicyForResource(serviceName, resource, userName);

                        if (policy != null) {
                            boolean policyUpdated = false;
                            policyUpdated = ServiceRESTUtil.processRevokeRequest(policy, revokeRequest);

                            if (policyUpdated) {
                                svcStore.updatePolicy(policy);
                            } else {
                                LOG.error("processSecureRevokeRequest processing failed");
                                throw new Exception("processSecureRevokeRequest processing failed");
                            }
                        }
                    } else {
                        LOG.error("secureRevokeAccess(" + serviceName + ", " + revokeRequest
                                + ") failed as User doesn't have permission to revoke Policy");
                        throw restErrorUtil.createGrantRevokeRESTException(
                                "User doesn't have necessary permission to revoke access");
                    }
                } catch (WebApplicationException excp) {
                    throw excp;
                } catch (Throwable excp) {
                    LOG.error("secureRevokeAccess(" + serviceName + ", " + revokeRequest + ") failed", excp);

                    throw restErrorUtil.createRESTException(excp.getMessage());
                } finally {
                    RangerPerfTracer.log(perf);
                }

                ret.setStatusCode(RESTResponse.STATUS_SUCCESS);
            }
        }
        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.secureRevokeAccess(" + serviceName + ", " + revokeRequest + "): " + ret);
        }
        return ret;
    }

    @POST
    @Path("/policies")
    @Produces({ "application/json", "application/xml" })
    public RangerPolicy createPolicy(RangerPolicy policy, @Context HttpServletRequest request) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.createPolicy(" + policy + ")");
        }

        RangerPolicy ret = null;
        RangerPerfTracer perf = null;

        try {
            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                perf = RangerPerfTracer.getPerfTracer(PERF_LOG,
                        "ServiceREST.createPolicy(policyName=" + policy.getName() + ")");
            }

            if (request != null) {
                String serviceName = request.getParameter(PARAM_SERVICE_NAME);
                String policyName = request.getParameter(PARAM_POLICY_NAME);
                String updateIfExists = request.getParameter(PARAM_UPDATE_IF_EXISTS);

                if (StringUtils.isNotEmpty(serviceName)) {
                    policy.setService(serviceName);
                }

                if (StringUtils.isNotEmpty(policyName)) {
                    policy.setName(StringUtils.trim(policyName));
                }

                if (Boolean.valueOf(updateIfExists)) {
                    RangerPolicy existingPolicy = null;
                    try {
                        if (StringUtils.isNotEmpty(policy.getGuid())) {
                            existingPolicy = getPolicyByGuid(policy.getGuid());
                        }

                        if (existingPolicy == null && StringUtils.isNotEmpty(serviceName)
                                && StringUtils.isNotEmpty(policyName)) {
                            existingPolicy = getPolicyByName(policy.getService(), policy.getName());
                        }

                        if (existingPolicy != null) {
                            ret = updatePolicy(policy);
                        }
                    } catch (Exception excp) {
                        LOG.info(
                                "ServiceREST.createPolicy(): Failed to find/update exising policy, will attempt to create the policy",
                                excp);
                    }
                }
            }

            if (ret == null) {
                // this needs to happen before validator is called
                // set name of policy if unspecified
                if (StringUtils.isBlank(policy.getName())) { // use of isBlank over isEmpty is deliberate as a blank string does not strike us as a particularly useful policy name!
                    String guid = policy.getGuid();
                    if (StringUtils.isBlank(guid)) { // use of isBlank is deliberate. External parties could send the guid in, perhaps to sync between dev/test/prod instances?
                        guid = guidUtil.genGUID();
                        policy.setGuid(guid);
                        if (LOG.isDebugEnabled()) {
                            LOG.debug("No GUID supplied on the policy!  Ok, setting GUID to [" + guid + "].");
                        }
                    }
                    String name = policy.getService() + "-" + guid;
                    policy.setName(name);
                    if (LOG.isDebugEnabled()) {
                        LOG.debug("Policy did not have its name set!  Ok, setting name to [" + name + "]");
                    }
                }
                RangerPolicyValidator validator = validatorFactory.getPolicyValidator(svcStore);
                validator.validate(policy, Action.CREATE, bizUtil.isAdmin());

                ensureAdminAccess(policy.getService(), policy.getResources());

                ret = svcStore.createPolicy(policy);
            }
        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("createPolicy(" + policy + ") failed", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        } finally {
            RangerPerfTracer.log(perf);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.createPolicy(" + policy + "): " + ret);
        }

        return ret;
    }

    /*
    The verb for applyPolicy is POST as it could be partial update or a create
    */

    @POST
    @Path("/policies/apply")
    @Produces({ "application/json", "application/xml" })
    public RangerPolicy applyPolicy(RangerPolicy policy, @Context HttpServletRequest request) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.applyPolicy(" + policy + ")");
        }

        RangerPolicy ret = null;

        if (policy != null && StringUtils.isNotBlank(policy.getService())) {
            try {
                // Check if applied policy contains any conditions
                if (ServiceRESTUtil.containsRangerCondition(policy)) {
                    LOG.error("Applied policy contains condition(s); not supported:" + policy);
                    throw new Exception("Applied policy contains condition(s); not supported:" + policy);
                }

                String user = request.getRemoteUser();
                RangerPolicy existingPolicy = getExactMatchPolicyForResource(policy.getService(),
                        policy.getResources(), StringUtils.isNotBlank(user) ? user : "admin");

                if (existingPolicy == null) {
                    ret = createPolicy(policy, null);
                } else {
                    ServiceRESTUtil.processApplyPolicy(existingPolicy, policy);

                    ret = updatePolicy(existingPolicy);
                }
            } catch (WebApplicationException excp) {
                throw excp;
            } catch (Exception exception) {
                LOG.error("Failed to apply policy:", exception);
                throw restErrorUtil.createRESTException(exception.getMessage());
            }
        } else {
            throw restErrorUtil.createRESTException("Non-existing service specified:");
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.applyPolicy(" + policy + ") : " + ret);
        }

        return ret;
    }

    @PUT
    @Path("/policies/{id}")
    @Produces({ "application/json", "application/xml" })
    public RangerPolicy updatePolicy(RangerPolicy policy) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.updatePolicy(" + policy + ")");
        }

        RangerPolicy ret = null;
        RangerPerfTracer perf = null;

        try {
            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                perf = RangerPerfTracer.getPerfTracer(PERF_LOG,
                        "ServiceREST.updatePolicy(policyId=" + policy.getId() + ")");
            }
            RangerPolicyValidator validator = validatorFactory.getPolicyValidator(svcStore);
            validator.validate(policy, Action.UPDATE, bizUtil.isAdmin());

            ensureAdminAccess(policy.getService(), policy.getResources());

            ret = svcStore.updatePolicy(policy);
        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("updatePolicy(" + policy + ") failed", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        } finally {
            RangerPerfTracer.log(perf);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.updatePolicy(" + policy + "): " + ret);
        }

        return ret;
    }

    @DELETE
    @Path("/policies/{id}")
    @Produces({ "application/json", "application/xml" })
    public void deletePolicy(@PathParam("id") Long id) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.deletePolicy(" + id + ")");
        }

        RangerPerfTracer perf = null;

        try {
            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "ServiceREST.deletePolicy(policyId=" + id + ")");
            }
            RangerPolicyValidator validator = validatorFactory.getPolicyValidator(svcStore);
            validator.validate(id, Action.DELETE);

            RangerPolicy policy = svcStore.getPolicy(id);

            ensureAdminAccess(policy.getService(), policy.getResources());

            svcStore.deletePolicy(id);
        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("deletePolicy(" + id + ") failed", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        } finally {
            RangerPerfTracer.log(perf);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.deletePolicy(" + id + ")");
        }
    }

    @GET
    @Path("/policies/{id}")
    @Produces({ "application/json", "application/xml" })
    public RangerPolicy getPolicy(@PathParam("id") Long id) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.getPolicy(" + id + ")");
        }

        RangerPolicy ret = null;
        RangerPerfTracer perf = null;

        try {
            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "ServiceREST.getPolicy(policyId=" + id + ")");
            }
            ret = svcStore.getPolicy(id);

            if (ret != null) {
                ensureAdminAccess(ret.getService(), ret.getResources());
            }
        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("getPolicy(" + id + ") failed", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        } finally {
            RangerPerfTracer.log(perf);
        }

        if (ret == null) {
            throw restErrorUtil.createRESTException(HttpServletResponse.SC_NOT_FOUND, "Not found", true);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.getPolicy(" + id + "): " + ret);
        }

        return ret;
    }

    @GET
    @Path("/policies")
    @Produces({ "application/json", "application/xml" })
    public RangerPolicyList getPolicies(@Context HttpServletRequest request) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.getPolicies()");
        }

        RangerPolicyList ret = new RangerPolicyList();
        RangerPerfTracer perf = null;

        SearchFilter filter = searchUtil.getSearchFilter(request, policyService.sortFields);

        try {
            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "ServiceREST.getPolicies()");
            }

            if (isAdminUserWithNoFilterParams(filter)) {
                PList<RangerPolicy> policies = svcStore.getPaginatedPolicies(filter);

                ret = toRangerPolicyList(policies);
            } else {
                // get all policies from the store; pick the page to return after applying filter
                int savedStartIndex = filter == null ? 0 : filter.getStartIndex();
                int savedMaxRows = filter == null ? Integer.MAX_VALUE : filter.getMaxRows();

                if (filter != null) {
                    filter.setStartIndex(0);
                    filter.setMaxRows(Integer.MAX_VALUE);
                }

                List<RangerPolicy> policies = svcStore.getPolicies(filter);

                if (filter != null) {
                    filter.setStartIndex(savedStartIndex);
                    filter.setMaxRows(savedMaxRows);
                }

                policies = applyAdminAccessFilter(policies);

                ret = toRangerPolicyList(policies, filter);
            }

        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("getPolicies() failed", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        } finally {
            RangerPerfTracer.log(perf);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.getPolicies(): count=" + (ret == null ? 0 : ret.getListSize()));
        }
        return ret;
    }

    @GET
    @Path("/policies/downloadExcel")
    @Produces("application/ms-excel")
    public void getPoliciesInExcel(@Context HttpServletRequest request, @Context HttpServletResponse response) {

        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.getPoliciesInExcel()");
        }
        RangerPerfTracer perf = null;

        SearchFilter filter = searchUtil.getSearchFilter(request, policyService.sortFields);

        try {
            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "ServiceREST.getPoliciesInExcel()");
            }
            List<RangerPolicy> policies = new ArrayList<RangerPolicy>();
            if (filter != null) {
                filter.setStartIndex(0);
                filter.setMaxRows(Integer.MAX_VALUE);
                policies = svcStore.getPoliciesForReports(filter);
            }
            svcStore.getPoliciesInExcel(policies, response);

        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("Error while downloading policy report", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        } finally {
            RangerPerfTracer.log(perf);
        }

    }

    @GET
    @Path("/policies/csv")
    @Produces("text/csv")
    public void getPoliciesInCsv(@Context HttpServletRequest request, @Context HttpServletResponse response)
            throws IOException {

        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.getPoliciesInCsv()");
        }
        RangerPerfTracer perf = null;

        SearchFilter filter = searchUtil.getSearchFilter(request, policyService.sortFields);

        try {
            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "ServiceREST.getPoliciesInCsv()");
            }
            List<RangerPolicy> policies = new ArrayList<RangerPolicy>();
            if (filter != null) {
                filter.setStartIndex(0);
                filter.setMaxRows(Integer.MAX_VALUE);
                policies = svcStore.getPoliciesForReports(filter);
            }
            svcStore.getPoliciesInCSV(policies, response);

        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("Error while downloading policy report", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        } finally {
            RangerPerfTracer.log(perf);
        }
    }

    public List<RangerPolicy> getPolicies(SearchFilter filter) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.getPolicies(filter)");
        }

        List<RangerPolicy> ret = null;
        RangerPerfTracer perf = null;

        try {
            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "ServiceREST.getPolicies()");
            }
            ret = svcStore.getPolicies(filter);

            ret = applyAdminAccessFilter(ret);
        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("getPolicies() failed", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        } finally {
            RangerPerfTracer.log(perf);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.getPolicies(filter): count=" + (ret == null ? 0 : ret.size()));
        }

        return ret;
    }

    @GET
    @Path("/policies/count")
    @Produces({ "application/json", "application/xml" })
    public Long countPolicies(@Context HttpServletRequest request) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.countPolicies():");
        }

        Long ret = null;
        RangerPerfTracer perf = null;

        try {
            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "ServiceREST.countPolicies()");
            }
            List<RangerPolicy> policies = getPolicies(request).getPolicies();

            policies = applyAdminAccessFilter(policies);

            ret = Long.valueOf(policies == null ? 0 : policies.size());
        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("countPolicies() failed", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        } finally {
            RangerPerfTracer.log(perf);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.countPolicies(): " + ret);
        }

        return ret;
    }

    @GET
    @Path("/policies/service/{id}")
    @Produces({ "application/json", "application/xml" })
    public RangerPolicyList getServicePolicies(@PathParam("id") Long serviceId,
            @Context HttpServletRequest request) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.getServicePolicies(" + serviceId + ")");
        }

        RangerPolicyList ret = new RangerPolicyList();
        RangerPerfTracer perf = null;

        SearchFilter filter = searchUtil.getSearchFilter(request, policyService.sortFields);

        try {
            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                perf = RangerPerfTracer.getPerfTracer(PERF_LOG,
                        "ServiceREST.getServicePolicies(serviceId=" + serviceId + ")");
            }

            if (isAdminUserWithNoFilterParams(filter)) {
                PList<RangerPolicy> policies = svcStore.getPaginatedServicePolicies(serviceId, filter);

                ret = toRangerPolicyList(policies);
            } else {
                // get all policies from the store; pick the page to return after applying filter
                int savedStartIndex = filter == null ? 0 : filter.getStartIndex();
                int savedMaxRows = filter == null ? Integer.MAX_VALUE : filter.getMaxRows();

                if (filter != null) {
                    filter.setStartIndex(0);
                    filter.setMaxRows(Integer.MAX_VALUE);
                }

                List<RangerPolicy> servicePolicies = svcStore.getServicePolicies(serviceId, filter);

                if (filter != null) {
                    filter.setStartIndex(savedStartIndex);
                    filter.setMaxRows(savedMaxRows);
                }

                servicePolicies = applyAdminAccessFilter(servicePolicies);

                ret = toRangerPolicyList(servicePolicies, filter);
            }
        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("getServicePolicies(" + serviceId + ") failed", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        } finally {
            RangerPerfTracer.log(perf);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.getServicePolicies(" + serviceId + "): count="
                    + (ret == null ? 0 : ret.getListSize()));
        }
        return ret;
    }

    @GET
    @Path("/policies/service/name/{name}")
    @Produces({ "application/json", "application/xml" })
    public RangerPolicyList getServicePoliciesByName(@PathParam("name") String serviceName,
            @Context HttpServletRequest request) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.getServicePolicies(" + serviceName + ")");
        }

        RangerPolicyList ret = new RangerPolicyList();
        RangerPerfTracer perf = null;

        SearchFilter filter = searchUtil.getSearchFilter(request, policyService.sortFields);

        try {
            if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                perf = RangerPerfTracer.getPerfTracer(PERF_LOG,
                        "ServiceREST.getServicePolicies(serviceName=" + serviceName + ")");
            }

            if (isAdminUserWithNoFilterParams(filter)) {
                PList<RangerPolicy> policies = svcStore.getPaginatedServicePolicies(serviceName, filter);

                ret = toRangerPolicyList(policies);
            } else {
                // get all policies from the store; pick the page to return after applying filter
                int savedStartIndex = filter == null ? 0 : filter.getStartIndex();
                int savedMaxRows = filter == null ? Integer.MAX_VALUE : filter.getMaxRows();

                if (filter != null) {
                    filter.setStartIndex(0);
                    filter.setMaxRows(Integer.MAX_VALUE);
                }

                List<RangerPolicy> servicePolicies = svcStore.getServicePolicies(serviceName, filter);

                if (filter != null) {
                    filter.setStartIndex(savedStartIndex);
                    filter.setMaxRows(savedMaxRows);
                }

                servicePolicies = applyAdminAccessFilter(servicePolicies);

                ret = toRangerPolicyList(servicePolicies, filter);
            }
        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("getServicePolicies(" + serviceName + ") failed", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        } finally {
            RangerPerfTracer.log(perf);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.getServicePolicies(" + serviceName + "): count="
                    + (ret == null ? 0 : ret.getListSize()));
        }

        return ret;
    }

    @GET
    @Path("/policies/download/{serviceName}")
    @Produces({ "application/json", "application/xml" })
    public ServicePolicies getServicePoliciesIfUpdated(@PathParam("serviceName") String serviceName,
            @QueryParam("lastKnownVersion") Long lastKnownVersion,
            @DefaultValue("0") @QueryParam("lastActivationTime") Long lastActivationTime,
            @QueryParam("pluginId") String pluginId, @Context HttpServletRequest request) throws Exception {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.getServicePoliciesIfUpdated(" + serviceName + ", " + lastKnownVersion + ", "
                    + lastActivationTime + ")");
        }

        ServicePolicies ret = null;
        int httpCode = HttpServletResponse.SC_OK;
        String logMsg = null;
        RangerPerfTracer perf = null;

        if (serviceUtil.isValidateHttpsAuthentication(serviceName, request)) {
            if (lastKnownVersion == null) {
                lastKnownVersion = Long.valueOf(-1);
            }

            try {
                if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                    perf = RangerPerfTracer.getPerfTracer(PERF_LOG,
                            "ServiceREST.getServicePoliciesIfUpdated(serviceName=" + serviceName
                                    + ",lastKnownVersion=" + lastKnownVersion + ",lastActivationTime="
                                    + lastActivationTime + ")");
                }
                ServicePolicies servicePolicies = svcStore.getServicePoliciesIfUpdated(serviceName,
                        lastKnownVersion);

                Long downloadedVersion;
                if (servicePolicies == null) {
                    downloadedVersion = lastKnownVersion;
                    httpCode = HttpServletResponse.SC_NOT_MODIFIED;
                    logMsg = "No change since last update";
                } else {
                    downloadedVersion = servicePolicies.getPolicyVersion();
                    ret = filterServicePolicies(servicePolicies);
                    httpCode = HttpServletResponse.SC_OK;
                    logMsg = "Returning " + (ret.getPolicies() != null ? ret.getPolicies().size() : 0)
                            + " policies. Policy version=" + ret.getPolicyVersion();
                }
                assetMgr.createPluginInfo(serviceName, pluginId, request, RangerPluginInfo.ENTITY_TYPE_POLICIES,
                        downloadedVersion, lastKnownVersion, lastActivationTime, httpCode);
            } catch (Throwable excp) {
                LOG.error("getServicePoliciesIfUpdated(" + serviceName + ", " + lastKnownVersion + ", "
                        + lastActivationTime + ") failed", excp);

                httpCode = HttpServletResponse.SC_BAD_REQUEST;
                logMsg = excp.getMessage();
            } finally {
                createPolicyDownloadAudit(serviceName, lastKnownVersion, pluginId, httpCode, request);
                RangerPerfTracer.log(perf);
            }

            if (httpCode != HttpServletResponse.SC_OK) {
                boolean logError = httpCode != HttpServletResponse.SC_NOT_MODIFIED;
                throw restErrorUtil.createRESTException(httpCode, logMsg, logError);
            }
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.getServicePoliciesIfUpdated(" + serviceName + ", " + lastKnownVersion + ", "
                    + lastActivationTime + "): count="
                    + ((ret == null || ret.getPolicies() == null) ? 0 : ret.getPolicies().size()));
        }

        return ret;
    }

    @GET
    @Path("/secure/policies/download/{serviceName}")
    @Produces({ "application/json", "application/xml" })
    public ServicePolicies getSecureServicePoliciesIfUpdated(@PathParam("serviceName") String serviceName,
            @QueryParam("lastKnownVersion") Long lastKnownVersion,
            @DefaultValue("0") @QueryParam("lastActivationTime") Long lastActivationTime,
            @QueryParam("pluginId") String pluginId, @Context HttpServletRequest request) throws Exception {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.getSecureServicePoliciesIfUpdated(" + serviceName + ", " + lastKnownVersion
                    + ")");
        }
        ServicePolicies ret = null;
        int httpCode = HttpServletResponse.SC_OK;
        String logMsg = null;
        RangerPerfTracer perf = null;
        boolean isAllowed = false;
        boolean isAdmin = bizUtil.isAdmin();
        boolean isKeyAdmin = bizUtil.isKeyAdmin();
        request.setAttribute("downloadPolicy", "secure");
        if (serviceUtil.isValidService(serviceName, request)) {
            if (lastKnownVersion == null) {
                lastKnownVersion = Long.valueOf(-1);
            }
            try {
                if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
                    perf = RangerPerfTracer.getPerfTracer(PERF_LOG,
                            "ServiceREST.getSecureServicePoliciesIfUpdated(serviceName=" + serviceName
                                    + ",lastKnownVersion=" + lastKnownVersion + ",lastActivationTime="
                                    + lastActivationTime + ")");
                }
                XXService xService = daoManager.getXXService().findByName(serviceName);
                XXServiceDef xServiceDef = daoManager.getXXServiceDef().getById(xService.getType());
                RangerService rangerService = null;

                if (StringUtils.equals(xServiceDef.getImplclassname(),
                        EmbeddedServiceDefsUtil.KMS_IMPL_CLASS_NAME)) {
                    rangerService = svcStore.getServiceByNameForDP(serviceName);
                    if (isKeyAdmin) {
                        isAllowed = true;
                    } else {
                        if (rangerService != null) {
                            isAllowed = bizUtil.isUserAllowed(rangerService, Allowed_User_List_For_Download);
                            if (!isAllowed) {
                                isAllowed = bizUtil.isUserAllowed(rangerService,
                                        Allowed_User_List_For_Grant_Revoke);
                            }
                        }
                    }
                } else {
                    rangerService = svcStore.getServiceByName(serviceName);
                    if (isAdmin) {
                        isAllowed = true;
                    } else {
                        if (rangerService != null) {
                            isAllowed = bizUtil.isUserAllowed(rangerService, Allowed_User_List_For_Download);
                            if (!isAllowed) {
                                isAllowed = bizUtil.isUserAllowed(rangerService,
                                        Allowed_User_List_For_Grant_Revoke);
                            }
                        }
                    }
                }
                if (isAllowed) {
                    ServicePolicies servicePolicies = svcStore.getServicePoliciesIfUpdated(serviceName,
                            lastKnownVersion);
                    Long downloadedVersion;
                    if (servicePolicies == null) {
                        downloadedVersion = lastKnownVersion;
                        httpCode = HttpServletResponse.SC_NOT_MODIFIED;
                        logMsg = "No change since last update";
                    } else {
                        downloadedVersion = servicePolicies.getPolicyVersion();
                        ret = filterServicePolicies(servicePolicies);
                        httpCode = HttpServletResponse.SC_OK;
                        logMsg = "Returning " + (ret.getPolicies() != null ? ret.getPolicies().size() : 0)
                                + " policies. Policy version=" + ret.getPolicyVersion();
                    }

                    assetMgr.createPluginInfo(serviceName, pluginId, request, RangerPluginInfo.ENTITY_TYPE_POLICIES,
                            downloadedVersion, lastKnownVersion, lastActivationTime, httpCode);
                } else {
                    LOG.error("getSecureServicePoliciesIfUpdated(" + serviceName + ", " + lastKnownVersion
                            + ") failed as User doesn't have permission to download Policy");
                    httpCode = HttpServletResponse.SC_UNAUTHORIZED;
                    logMsg = "User doesn't have permission to download policy";
                }
            } catch (Throwable excp) {
                LOG.error("getSecureServicePoliciesIfUpdated(" + serviceName + ", " + lastKnownVersion + ", "
                        + lastActivationTime + ") failed", excp);
                httpCode = HttpServletResponse.SC_BAD_REQUEST;
                logMsg = excp.getMessage();
            } finally {
                createPolicyDownloadAudit(serviceName, lastKnownVersion, pluginId, httpCode, request);
                RangerPerfTracer.log(perf);
            }
            if (httpCode != HttpServletResponse.SC_OK) {
                boolean logError = httpCode != HttpServletResponse.SC_NOT_MODIFIED;
                throw restErrorUtil.createRESTException(httpCode, logMsg, logError);
            }
        }
        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.getSecureServicePoliciesIfUpdated(" + serviceName + ", " + lastKnownVersion
                    + ", " + lastActivationTime + "): count="
                    + ((ret == null || ret.getPolicies() == null) ? 0 : ret.getPolicies().size()));
        }
        return ret;
    }

    private void createPolicyDownloadAudit(String serviceName, Long lastKnownVersion, String pluginId,
            int httpRespCode, HttpServletRequest request) {
        try {
            String ipAddress = request.getHeader("X-FORWARDED-FOR");

            if (ipAddress == null) {
                ipAddress = request.getRemoteAddr();
            }

            XXPolicyExportAudit policyExportAudit = new XXPolicyExportAudit();

            policyExportAudit.setRepositoryName(serviceName);
            policyExportAudit.setAgentId(pluginId);
            policyExportAudit.setClientIP(ipAddress);
            policyExportAudit.setRequestedEpoch(lastKnownVersion);
            policyExportAudit.setHttpRetCode(httpRespCode);

            assetMgr.createPolicyAudit(policyExportAudit);
        } catch (Exception excp) {
            LOG.error("error while creating policy download audit", excp);
        }
    }

    private RangerPolicy getExactMatchPolicyForResource(String serviceName, RangerAccessResource resource,
            String user) throws Exception {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.getExactMatchPolicyForResource(" + resource + ", " + user + ")");
        }

        RangerPolicy ret = null;
        RangerPolicyEngine policyEngine = getPolicyEngine(serviceName);

        Map<String, Object> evalContext = new HashMap<String, Object>();
        RangerAccessRequestUtil.setCurrentUserInContext(evalContext, user);

        List<RangerPolicy> policies = policyEngine != null
                ? policyEngine.getExactMatchPolicies(resource, evalContext)
                : null;

        if (CollectionUtils.isNotEmpty(policies)) {
            // at this point, ret is a policy in policy-engine; the caller might update the policy (for grant/revoke); so get a copy from the store
            ret = svcStore.getPolicy(policies.get(0).getId());
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.getExactMatchPolicyForResource(" + resource + ", " + user + "): " + ret);
        }

        return ret;
    }

    private RangerPolicy getExactMatchPolicyForResource(String serviceName,
            Map<String, RangerPolicyResource> resources, String user) throws Exception {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.getExactMatchPolicyForResource(" + resources + ", " + user + ")");
        }

        RangerPolicy ret = null;
        RangerPolicyEngine policyEngine = getPolicyEngine(serviceName);

        Map<String, Object> evalContext = new HashMap<String, Object>();
        RangerAccessRequestUtil.setCurrentUserInContext(evalContext, user);

        List<RangerPolicy> policies = policyEngine != null
                ? policyEngine.getExactMatchPolicies(resources, evalContext)
                : null;

        if (CollectionUtils.isNotEmpty(policies)) {
            // at this point, ret is a policy in policy-engine; the caller might update the policy (for grant/revoke); so get a copy from the store
            ret = svcStore.getPolicy(policies.get(0).getId());
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.getExactMatchPolicyForResource(" + resources + ", " + user + "): " + ret);
        }

        return ret;
    }

    @GET
    @Path("/policies/eventTime")
    @Produces({ "application/json", "application/xml" })
    @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.GET_POLICY_FROM_EVENT_TIME
            + "\")")
    public RangerPolicy getPolicyFromEventTime(@Context HttpServletRequest request) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.getPolicyFromEventTime()");
        }

        String eventTimeStr = request.getParameter("eventTime");
        String policyIdStr = request.getParameter("policyId");

        if (StringUtils.isEmpty(eventTimeStr) || StringUtils.isEmpty(policyIdStr)) {
            throw restErrorUtil.createRESTException("EventTime or policyId cannot be null or empty string.",
                    MessageEnums.INVALID_INPUT_DATA);
        }

        Long policyId = Long.parseLong(policyIdStr);

        RangerPolicy policy = null;
        try {
            policy = svcStore.getPolicyFromEventTime(eventTimeStr, policyId);
            if (policy != null) {
                ensureAdminAccess(policy.getService(), policy.getResources());
            }
        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("getPolicy(" + policyId + ") failed", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        }

        if (policy == null) {
            throw restErrorUtil.createRESTException(HttpServletResponse.SC_NOT_FOUND, "Not found", true);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.getPolicy(" + policyId + "): " + policy);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.getPolicyFromEventTime()");
        }

        return policy;
    }

    @GET
    @Path("/policy/{policyId}/versionList")
    @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.GET_POLICY_VERSION_LIST
            + "\")")
    public VXString getPolicyVersionList(@PathParam("policyId") Long policyId) {

        VXString policyVersionListStr = svcStore.getPolicyVersionList(policyId);

        return policyVersionListStr;
    }

    @GET
    @Path("/policy/{policyId}/version/{versionNo}")
    @Produces({ "application/json", "application/xml" })
    @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.GET_POLICY_FOR_VERSION_NO
            + "\")")
    public RangerPolicy getPolicyForVersionNumber(@PathParam("policyId") Long policyId,
            @PathParam("versionNo") int versionNo) {
        return svcStore.getPolicyForVersionNumber(policyId, versionNo);
    }

    @GET
    @Path("/plugins/info")
    @Produces({ "application/json", "application/xml" })
    @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.GET_PLUGINS_INFO + "\")")
    public RangerPluginInfoList getPluginsInfo(@Context HttpServletRequest request) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.getPluginsInfo()");
        }

        RangerPluginInfoList ret = null;

        SearchFilter filter = searchUtil.getSearchFilter(request, pluginInfoService.getSortFields());

        try {
            PList<RangerPluginInfo> paginatedPluginsInfo = pluginInfoService.searchRangerPluginInfo(filter);
            if (paginatedPluginsInfo != null) {
                ret = new RangerPluginInfoList();

                ret.setPluginInfoList(paginatedPluginsInfo.getList());
                ret.setPageSize(paginatedPluginsInfo.getPageSize());
                ret.setResultSize(paginatedPluginsInfo.getResultSize());
                ret.setStartIndex(paginatedPluginsInfo.getStartIndex());
                ret.setTotalCount(paginatedPluginsInfo.getTotalCount());
                ret.setSortBy(paginatedPluginsInfo.getSortBy());
                ret.setSortType(paginatedPluginsInfo.getSortType());
            }
        } catch (WebApplicationException excp) {
            throw excp;
        } catch (Throwable excp) {
            LOG.error("getPluginsInfo() failed", excp);

            throw restErrorUtil.createRESTException(excp.getMessage());
        }
        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.getPluginsInfo()");
        }

        return ret;
    }

    private RangerPolicy getPolicyByGuid(String guid) {
        RangerPolicy ret = null;

        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.getPolicyByGuid(" + guid + ")");
        }

        SearchFilter filter = new SearchFilter();
        filter.setParam(SearchFilter.GUID, guid);
        List<RangerPolicy> policies = getPolicies(filter);

        if (CollectionUtils.isNotEmpty(policies)) {
            ret = policies.get(0);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.getPolicyByGuid(" + guid + ")" + ret);
        }
        return ret;
    }

    private RangerPolicy getPolicyByName(String serviceName, String policyName) {
        RangerPolicy ret = null;
        if (LOG.isDebugEnabled()) {
            LOG.debug("==> ServiceREST.getPolicyByName(" + serviceName + "," + policyName + ")");
        }

        SearchFilter filter = new SearchFilter();
        filter.setParam(SearchFilter.SERVICE_NAME, serviceName);
        filter.setParam(SearchFilter.POLICY_NAME, policyName);
        List<RangerPolicy> policies = getPolicies(filter);

        if (CollectionUtils.isNotEmpty(policies)) {
            ret = policies.get(0);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("<== ServiceREST.getPolicyByName(" + serviceName + "," + policyName + ")" + ret);
        }
        return ret;
    }

    private List<RangerPolicy> applyAdminAccessFilter(List<RangerPolicy> policies) {
        List<RangerPolicy> ret = new ArrayList<RangerPolicy>();
        RangerPerfTracer perf = null;

        if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
            perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "ServiceREST.applyAdminAccessFilter(policyCount="
                    + (policies == null ? 0 : policies.size()) + ")");
        }

        if (CollectionUtils.isNotEmpty(policies)) {
            boolean isAdmin = bizUtil.isAdmin();
            boolean isKeyAdmin = bizUtil.isKeyAdmin();
            String userName = bizUtil.getCurrentUserLoginId();
            Set<String> userGroups = null;

            Map<String, List<RangerPolicy>> servicePoliciesMap = new HashMap<String, List<RangerPolicy>>();

            for (int i = 0; i < policies.size(); i++) {
                RangerPolicy policy = policies.get(i);
                String serviceName = policy.getService();
                List<RangerPolicy> policyList = servicePoliciesMap.get(serviceName);

                if (policyList == null) {
                    policyList = new ArrayList<RangerPolicy>();

                    servicePoliciesMap.put(serviceName, policyList);
                }

                policyList.add(policy);
            }

            for (Map.Entry<String, List<RangerPolicy>> entry : servicePoliciesMap.entrySet()) {
                String serviceName = entry.getKey();
                List<RangerPolicy> listToFilter = entry.getValue();

                if (CollectionUtils.isNotEmpty(listToFilter)) {
                    if (isAdmin || isKeyAdmin) {
                        XXService xService = daoManager.getXXService().findByName(serviceName);
                        Long serviceDefId = xService.getType();
                        boolean isKmsService = serviceDefId
                                .equals(EmbeddedServiceDefsUtil.instance().getKmsServiceDefId());

                        if (isAdmin) {
                            if (!isKmsService) {
                                ret.addAll(listToFilter);
                            }
                        } else { // isKeyAdmin
                            if (isKmsService) {
                                ret.addAll(listToFilter);
                            }
                        }

                        continue;
                    }

                    RangerPolicyEngine policyEngine = getDelegatedAdminPolicyEngine(serviceName);

                    if (policyEngine != null) {
                        if (userGroups == null) {
                            userGroups = daoManager.getXXGroupUser().findGroupNamesByUserName(userName);
                        }

                        for (RangerPolicy policy : listToFilter) {
                            if (policyEngine.isAccessAllowed(policy.getResources(), userName, userGroups,
                                    RangerPolicyEngine.ADMIN_ACCESS)) {
                                ret.add(policy);
                            }
                        }
                    }

                }
            }
        }

        RangerPerfTracer.log(perf);

        return ret;
    }

    void ensureAdminAccess(String serviceName, Map<String, RangerPolicyResource> resources) {
        boolean isAdmin = bizUtil.isAdmin();
        boolean isKeyAdmin = bizUtil.isKeyAdmin();
        String userName = bizUtil.getCurrentUserLoginId();

        if (!isAdmin && !isKeyAdmin) {
            boolean isAllowed = false;

            RangerPolicyEngine policyEngine = getDelegatedAdminPolicyEngine(serviceName);

            if (policyEngine != null) {
                Set<String> userGroups = userMgr.getGroupsForUser(userName);

                isAllowed = hasAdminAccess(serviceName, userName, userGroups, resources);
            }

            if (!isAllowed) {
                throw restErrorUtil.createRESTException(HttpServletResponse.SC_UNAUTHORIZED,
                        "User '" + userName + "' does not have delegated-admin privilege on given resources", true);
            }
        } else {

            XXService xService = daoManager.getXXService().findByName(serviceName);
            XXServiceDef xServiceDef = daoManager.getXXServiceDef().getById(xService.getType());

            if (isAdmin) {
                if (xServiceDef.getImplclassname().equals(EmbeddedServiceDefsUtil.KMS_IMPL_CLASS_NAME)) {
                    throw restErrorUtil.createRESTException(
                            "KMS Policies/Services/Service-Defs are not accessible for user '" + userName + "'.",
                            MessageEnums.OPER_NO_PERMISSION);
                }
            } else if (isKeyAdmin) {
                if (!xServiceDef.getImplclassname().equals(EmbeddedServiceDefsUtil.KMS_IMPL_CLASS_NAME)) {
                    throw restErrorUtil.createRESTException(
                            "Only KMS Policies/Services/Service-Defs are accessible for user '" + userName + "'.",
                            MessageEnums.OPER_NO_PERMISSION);
                }
            }
        }
    }

    private boolean hasAdminAccess(String serviceName, String userName, Set<String> userGroups,
            Map<String, RangerPolicyResource> resources) {
        boolean isAllowed = false;

        RangerPolicyEngine policyEngine = getDelegatedAdminPolicyEngine(serviceName);

        if (policyEngine != null) {
            isAllowed = policyEngine.isAccessAllowed(resources, userName, userGroups,
                    RangerPolicyEngine.ADMIN_ACCESS);
        }

        return isAllowed;
    }

    private boolean hasAdminAccess(String serviceName, String userName, Set<String> userGroups,
            RangerAccessResource resource) {
        boolean isAllowed = false;

        RangerPolicyEngine policyEngine = getDelegatedAdminPolicyEngine(serviceName);

        if (policyEngine != null) {
            isAllowed = policyEngine.isAccessAllowed(resource, userName, userGroups,
                    RangerPolicyEngine.ADMIN_ACCESS);
        }

        return isAllowed;
    }

    private RangerPolicyEngine getDelegatedAdminPolicyEngine(String serviceName) {
        if (RangerPolicyEngineCache.getInstance().getPolicyEngineOptions() == null) {
            RangerPolicyEngineOptions options = new RangerPolicyEngineOptions();

            String propertyPrefix = "ranger.admin";

            options.evaluatorType = RangerPolicyEvaluator.EVALUATOR_TYPE_OPTIMIZED;
            options.cacheAuditResults = RangerConfiguration.getInstance()
                    .getBoolean(propertyPrefix + ".policyengine.option.cache.audit.results", false);
            options.disableContextEnrichers = RangerConfiguration.getInstance()
                    .getBoolean(propertyPrefix + ".policyengine.option.disable.context.enrichers", true);
            options.disableCustomConditions = RangerConfiguration.getInstance()
                    .getBoolean(propertyPrefix + ".policyengine.option.disable.custom.conditions", true);
            options.evaluateDelegateAdminOnly = RangerConfiguration.getInstance()
                    .getBoolean(propertyPrefix + ".policyengine.option.evaluate.delegateadmin.only", true);

            RangerPolicyEngineCache.getInstance().setPolicyEngineOptions(options);
        }

        RangerPolicyEngine ret = RangerPolicyEngineCache.getInstance().getPolicyEngine(serviceName, svcStore);

        return ret;
    }

    private RangerPolicyEngine getPolicyEngine(String serviceName) throws Exception {
        RangerPolicyEngineOptions options = new RangerPolicyEngineOptions();

        String propertyPrefix = "ranger.admin";

        options.evaluatorType = RangerPolicyEvaluator.EVALUATOR_TYPE_OPTIMIZED;
        options.cacheAuditResults = RangerConfiguration.getInstance()
                .getBoolean(propertyPrefix + ".policyengine.option.cache.audit.results", false);
        options.disableContextEnrichers = RangerConfiguration.getInstance()
                .getBoolean(propertyPrefix + ".policyengine.option.disable.context.enrichers", true);
        options.disableCustomConditions = RangerConfiguration.getInstance()
                .getBoolean(propertyPrefix + ".policyengine.option.disable.custom.conditions", true);
        options.evaluateDelegateAdminOnly = false;
        options.disableTrieLookupPrefilter = RangerConfiguration.getInstance()
                .getBoolean(propertyPrefix + ".policyengine.option.disable.trie.lookup.prefilter", false);

        ServicePolicies policies = svcStore.getServicePoliciesIfUpdated(serviceName, -1L);

        RangerPolicyEngine ret = new RangerPolicyEngineImpl("ranger-admin", policies, options);

        return ret;
    }

    @GET
    @Path("/checksso")
    @Produces(MediaType.TEXT_PLAIN)
    public String checkSSO() {
        return String.valueOf(bizUtil.isSSOEnabled());
    }

    @GET
    @Path("/csrfconf")
    @Produces({ "application/json" })
    public HashMap<String, Object> getCSRFProperties() {
        return getCSRFPropertiesMap();
    }

    private HashMap<String, Object> getCSRFPropertiesMap() {
        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put(isCSRF_ENABLED, PropertiesUtil.getBooleanProperty(isCSRF_ENABLED, true));
        map.put(CUSTOM_HEADER_PARAM,
                PropertiesUtil.getProperty(CUSTOM_HEADER_PARAM, RangerCSRFPreventionFilter.HEADER_DEFAULT));
        map.put(BROWSER_USER_AGENT_PARAM, PropertiesUtil.getProperty(BROWSER_USER_AGENT_PARAM,
                RangerCSRFPreventionFilter.BROWSER_USER_AGENTS_DEFAULT));
        map.put(CUSTOM_METHODS_TO_IGNORE_PARAM, PropertiesUtil.getProperty(CUSTOM_METHODS_TO_IGNORE_PARAM,
                RangerCSRFPreventionFilter.METHODS_TO_IGNORE_DEFAULT));
        return map;
    }

    boolean isAdminUserWithNoFilterParams(SearchFilter filter) {
        return (filter == null || MapUtils.isEmpty(filter.getParams()))
                && (bizUtil.isAdmin() || bizUtil.isKeyAdmin());
    }

    private RangerPolicyList toRangerPolicyList(PList<RangerPolicy> policyList) {
        RangerPolicyList ret = new RangerPolicyList();

        if (policyList != null) {
            ret.setPolicies(policyList.getList());
            ret.setPageSize(policyList.getPageSize());
            ret.setResultSize(policyList.getResultSize());
            ret.setStartIndex(policyList.getStartIndex());
            ret.setTotalCount(policyList.getTotalCount());
            ret.setSortBy(policyList.getSortBy());
            ret.setSortType(policyList.getSortType());
        }

        return ret;
    }

    private RangerPolicyList toRangerPolicyList(List<RangerPolicy> policyList, SearchFilter filter) {
        RangerPolicyList ret = new RangerPolicyList();

        if (CollectionUtils.isNotEmpty(policyList)) {
            int totalCount = policyList.size();
            int startIndex = filter == null ? 0 : filter.getStartIndex();
            int pageSize = filter == null ? totalCount : filter.getMaxRows();
            int toIndex = Math.min(startIndex + pageSize, totalCount);
            String sortType = filter == null ? null : filter.getSortType();
            String sortBy = filter == null ? null : filter.getSortBy();

            List<RangerPolicy> retList = new ArrayList<RangerPolicy>();
            for (int i = startIndex; i < toIndex; i++) {
                retList.add(policyList.get(i));
            }

            ret.setPolicies(retList);
            ret.setPageSize(pageSize);
            ret.setResultSize(retList.size());
            ret.setStartIndex(startIndex);
            ret.setTotalCount(totalCount);
            ret.setSortBy(sortBy);
            ret.setSortType(sortType);
        }

        return ret;
    }

    private ServicePolicies filterServicePolicies(ServicePolicies servicePolicies) {
        ServicePolicies ret = null;
        boolean containsDisabledResourcePolicies = false;
        boolean containsDisabledTagPolicies = false;

        if (servicePolicies != null) {
            List<RangerPolicy> policies = null;

            policies = servicePolicies.getPolicies();
            if (CollectionUtils.isNotEmpty(policies)) {
                for (RangerPolicy policy : policies) {
                    if (!policy.getIsEnabled()) {
                        containsDisabledResourcePolicies = true;
                        break;
                    }
                }
            }

            if (servicePolicies.getTagPolicies() != null) {
                policies = servicePolicies.getTagPolicies().getPolicies();
                if (CollectionUtils.isNotEmpty(policies)) {
                    for (RangerPolicy policy : policies) {
                        if (!policy.getIsEnabled()) {
                            containsDisabledTagPolicies = true;
                            break;
                        }
                    }
                }
            }

            if (!containsDisabledResourcePolicies && !containsDisabledTagPolicies) {
                ret = servicePolicies;
            } else {
                ret = new ServicePolicies();

                ret.setServiceDef(servicePolicies.getServiceDef());
                ret.setServiceId(servicePolicies.getServiceId());
                ret.setServiceName(servicePolicies.getServiceName());
                ret.setPolicyVersion(servicePolicies.getPolicyVersion());
                ret.setPolicyUpdateTime(servicePolicies.getPolicyUpdateTime());
                ret.setPolicies(servicePolicies.getPolicies());
                ret.setTagPolicies(servicePolicies.getTagPolicies());

                if (containsDisabledResourcePolicies) {
                    List<RangerPolicy> filteredPolicies = new ArrayList<RangerPolicy>();
                    for (RangerPolicy policy : servicePolicies.getPolicies()) {
                        if (policy.getIsEnabled()) {
                            filteredPolicies.add(policy);
                        }
                    }
                    ret.setPolicies(filteredPolicies);
                }

                if (containsDisabledTagPolicies) {
                    ServicePolicies.TagPolicies tagPolicies = new ServicePolicies.TagPolicies();

                    tagPolicies.setServiceDef(servicePolicies.getTagPolicies().getServiceDef());
                    tagPolicies.setServiceId(servicePolicies.getTagPolicies().getServiceId());
                    tagPolicies.setServiceName(servicePolicies.getTagPolicies().getServiceName());
                    tagPolicies.setPolicyVersion(servicePolicies.getTagPolicies().getPolicyVersion());
                    tagPolicies.setPolicyUpdateTime(servicePolicies.getTagPolicies().getPolicyUpdateTime());

                    List<RangerPolicy> filteredPolicies = new ArrayList<RangerPolicy>();
                    for (RangerPolicy policy : servicePolicies.getTagPolicies().getPolicies()) {
                        if (policy.getIsEnabled()) {
                            filteredPolicies.add(policy);
                        }
                    }
                    tagPolicies.setPolicies(filteredPolicies);

                    ret.setTagPolicies(tagPolicies);
                }
            }
        }

        return ret;
    }

    private void validateGrantRevokeRequest(GrantRevokeRequest request) {
        if (request != null) {
            if (CollectionUtils.isEmpty(request.getUsers()) && CollectionUtils.isEmpty(request.getGroups())) {
                throw restErrorUtil.createGrantRevokeRESTException("Grantee users/groups list is empty");
            }
            String grantor = request.getGrantor();
            if (grantor == null || userMgr.getXUserByUserName(grantor) == null) {
                throw restErrorUtil.createGrantRevokeRESTException("Grantor user " + grantor + " doesn't exist");
            }
            for (String userName : request.getUsers()) {
                if (userMgr.getXUserByUserName(userName) == null) {
                    throw restErrorUtil
                            .createGrantRevokeRESTException("Grantee user " + userName + " doesn't exist");
                }
            }
            for (String groupName : request.getGroups()) {
                if (userMgr.getGroupByGroupName(groupName) == null) {
                    throw restErrorUtil
                            .createGrantRevokeRESTException("Grantee group " + groupName + " doesn't exist");
                }
            }
        }
    }
}