/**
 * 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.sentry.provider.db.service.thrift;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.hadoop.hive.metastore.HiveMetaStoreClient;
import org.apache.hadoop.hive.metastore.api.Database;
import org.apache.hadoop.hive.metastore.api.Partition;
import org.apache.hadoop.hive.metastore.api.Table;
import org.apache.sentry.SentryUserException;
import org.apache.sentry.core.model.db.AccessConstants;
import org.apache.sentry.hdfs.ExtendedMetastoreClient;
import org.apache.sentry.hdfs.HMSPaths;
import org.apache.sentry.hdfs.MetastoreClient;
import org.apache.sentry.hdfs.PathsUpdate;
import org.apache.sentry.hdfs.PermissionsUpdate;
import org.apache.sentry.hdfs.UpdateableAuthzPaths;
import org.apache.sentry.provider.common.GroupMappingService;
import org.apache.sentry.provider.db.SentryAccessDeniedException;
import org.apache.sentry.provider.db.SentryAlreadyExistsException;
import org.apache.sentry.provider.db.SentryInvalidInputException;
import org.apache.sentry.provider.db.SentryNoSuchObjectException;
import org.apache.sentry.provider.db.log.entity.JsonLogEntityFactory;
import org.apache.sentry.provider.db.log.util.Constants;
import org.apache.sentry.provider.db.service.UpdateForwarder;
import org.apache.sentry.provider.db.service.UpdateForwarder.ExternalImageRetriever;
import org.apache.sentry.provider.db.service.UpdateablePermissions;
import org.apache.sentry.provider.db.service.persistent.CommitContext;
import org.apache.sentry.provider.db.service.persistent.SentryStore;
import org.apache.sentry.provider.db.service.thrift.PolicyStoreConstants.PolicyStoreServerConfig;
import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig;
import org.apache.sentry.service.thrift.Status;
import org.apache.sentry.service.thrift.TSentryResponseStatus;
import org.apache.thrift.TException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

@SuppressWarnings("unused")
public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface {
  private static final Logger LOGGER = LoggerFactory.getLogger(SentryPolicyStoreProcessor.class);
  private static final Logger AUDIT_LOGGER = LoggerFactory.getLogger(Constants.AUDIT_LOGGER_NAME);

  public static final String SENTRY_POLICY_SERVICE_NAME = "SentryPolicyService";

  private final String name;
  private final Configuration conf;
  private final SentryStore sentryStore;
  private final NotificationHandlerInvoker notificationHandlerInvoker;
  private final ImmutableSet<String> adminGroups;
  private boolean isReady;

  private final UpdateForwarder<PathsUpdate> pathsUpdater;
  private final UpdateForwarder<PermissionsUpdate> permsUpdater;
  
  // Initialized to some value > 1 so that the first update notification
  // will trigger a full Image fetch
  private final AtomicLong permSeqNum = new AtomicLong(5);

  public SentryPolicyStoreProcessor(String name, Configuration conf) throws Exception {
    super();
    this.name = name;
    this.conf = conf;
    this.notificationHandlerInvoker = new NotificationHandlerInvoker(conf,
        createHandlers(conf));
    isReady = false;
    sentryStore = new SentryStore(conf);
    isReady = true;
    adminGroups = ImmutableSet.copyOf(toTrimedLower(Sets.newHashSet(conf.getStrings(
        ServerConfig.ADMIN_GROUPS, new String[]{}))));
    HiveConf hiveConf = new HiveConf(conf, Configuration.class);
    if (conf.getBoolean(ServerConfig.SENTRY_HDFS_INTEGRATION_ENABLE, true)) {
      final MetastoreClient hmsClient = new ExtendedMetastoreClient(hiveConf);
      final String[] pathPrefixes = conf
          .getStrings(ServerConfig.SENTRY_HDFS_INTEGRATION_PATH_PREFIXES, new String[]{"/"});
      pathsUpdater = new UpdateForwarder<PathsUpdate>(new UpdateableAuthzPaths(
          pathPrefixes), createHMSImageRetriever(pathPrefixes, hmsClient), 100);
      permsUpdater = new UpdateForwarder<PermissionsUpdate>(
          new UpdateablePermissions(sentryStore), sentryStore, 100);
    } else {
      pathsUpdater = null;
      permsUpdater = null;
    }
  }

  private ExternalImageRetriever<PathsUpdate> createHMSImageRetriever(
      final String[] pathPrefixes, final MetastoreClient hmsClient) {
    return new ExternalImageRetriever<PathsUpdate>() {
      @Override
      public PathsUpdate retrieveFullImage(long currSeqNum) {
        PathsUpdate tempUpdate = new PathsUpdate(currSeqNum, false);
        List<Database> allDatabases = hmsClient.getAllDatabases();
        for (Database db : allDatabases) {
          tempUpdate.newPathChange(db.getName()).addToAddPaths(
              PathsUpdate.cleanPath(db.getLocationUri()));
          List<Table> allTables = hmsClient.getAllTablesOfDatabase(db);
          for (Table tbl : allTables) {
            TPathChanges tblPathChange = tempUpdate.newPathChange(tbl
                .getDbName() + "." + tbl.getTableName());
            List<Partition> tblParts = hmsClient.listAllPartitions(db, tbl);
            tblPathChange.addToAddPaths(PathsUpdate.cleanPath(tbl.getSd()
                    .getLocation() == null ? db.getLocationUri() : tbl
                    .getSd().getLocation()));
            for (Partition part : tblParts) {
              tblPathChange.addToAddPaths(PathsUpdate.cleanPath(part.getSd()
                  .getLocation()));
            }
          }
        }
        UpdateableAuthzPaths tmpAuthzPaths = new UpdateableAuthzPaths(
            pathPrefixes);
        tmpAuthzPaths.updatePartial(Lists.newArrayList(tempUpdate),
            new ReentrantReadWriteLock());
        PathsUpdate retUpdate = new PathsUpdate(currSeqNum, true);
        retUpdate.getThriftObject().setPathsDump(
            tmpAuthzPaths.getPathsDump().createPathsDump());
        return retUpdate;
      }
    };
  }

  public void stop() {
    if (isReady) {
      sentryStore.stop();
    }
  }

  @VisibleForTesting
  static List<NotificationHandler> createHandlers(Configuration conf)
  throws SentryConfigurationException {
    List<NotificationHandler> handlers = Lists.newArrayList();
    Iterable<String> notificationHandlers = Splitter.onPattern("[\\s,]").trimResults()
                                            .omitEmptyStrings().split(conf.get(PolicyStoreServerConfig.NOTIFICATION_HANDLERS, ""));
    for (String notificationHandler : notificationHandlers) {
      Class<?> clazz = null;
      try {
        clazz = Class.forName(notificationHandler);
        if (!NotificationHandler.class.isAssignableFrom(clazz)) {
          throw new SentryConfigurationException("Class " + notificationHandler + " is not a " +
                                                 NotificationHandler.class.getName());
        }
      } catch (ClassNotFoundException e) {
        throw new SentryConfigurationException("Value " + notificationHandler +
                                               " is not a class", e);
      }
      Preconditions.checkNotNull(clazz, "Error class cannot be null");
      try {
        Constructor<?> constructor = clazz.getConstructor(Configuration.class);
        handlers.add((NotificationHandler)constructor.newInstance(conf));
      } catch (Exception e) {
        throw new SentryConfigurationException("Error attempting to create " + notificationHandler, e);
      }
    }
    return handlers;
  }

  @VisibleForTesting
  public Configuration getSentryStoreConf() {
    return conf;
  }

  private static Set<String> toTrimedLower(Set<String> s) {
    Set<String> result = Sets.newHashSet();
    for (String v : s) {
      result.add(v.trim().toLowerCase());
    }
    return result;
  }

  private boolean inAdminGroups(Set<String> requestorGroups) {
    requestorGroups = toTrimedLower(requestorGroups);
    if (Sets.intersection(adminGroups, requestorGroups).isEmpty()) {
      return false;
    } else return true;
  }
  private void authorize(String requestorUser, Set<String> requestorGroups)
  throws SentryAccessDeniedException {
    if (!inAdminGroups(requestorGroups)) {
      String msg = "User: " + requestorUser + " is part of " + requestorGroups +
          " which does not, intersect admin groups " + adminGroups;
      LOGGER.warn(msg);
      throw new SentryAccessDeniedException("Access denied to " + requestorUser);
    }
  }

  @Override
  public TCreateSentryRoleResponse create_sentry_role(
    TCreateSentryRoleRequest request) throws TException {
    TCreateSentryRoleResponse response = new TCreateSentryRoleResponse();
    try {
      authorize(request.getRequestorUserName(),
          getRequestorGroups(request.getRequestorUserName()));
      CommitContext commitContext = sentryStore.createSentryRole(request.getRoleName(),
          request.getRequestorUserName());
      response.setStatus(Status.OK());
      notificationHandlerInvoker.create_sentry_role(commitContext,
          request, response);
    } catch (SentryAlreadyExistsException e) {
      String msg = "Role: " + request + " already exists.";
      LOGGER.error(msg, e);
      response.setStatus(Status.AlreadyExists(msg, e));
    } catch (SentryAccessDeniedException e) {
      LOGGER.error(e.getMessage(), e);
      response.setStatus(Status.AccessDenied(e.getMessage(), e));
    } catch (Exception e) {
      String msg = "Unknown error for request: " + request + ", message: " + e.getMessage();
      LOGGER.error(msg, e);
      response.setStatus(Status.RuntimeError(msg, e));
    }

    AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance().createJsonLogEntity(
    		request, response, conf).toJsonFormatLog());
    return response;
  }

  @Override
  public TAlterSentryRoleGrantPrivilegeResponse alter_sentry_role_grant_privilege
  (TAlterSentryRoleGrantPrivilegeRequest request) throws TException {

    TAlterSentryRoleGrantPrivilegeResponse response = new TAlterSentryRoleGrantPrivilegeResponse();
    try {
      CommitContext commitContext = sentryStore.alterSentryRoleGrantPrivilege(request.getRoleName(),
                                    request.getPrivilege());
      response.setStatus(Status.OK());
      notificationHandlerInvoker.alter_sentry_role_grant_privilege(commitContext,
          request, response);
      String authzObj = getAuthzObj(request.getPrivilege());
      if (authzObj != null) {
        PermissionsUpdate update = new PermissionsUpdate(permSeqNum.incrementAndGet(), false);
        update.addPrivilegeUpdate(authzObj).putToAddPrivileges(
            request.getRoleName(),
            SentryStore.ACTION_MAPPING.get(request.getPrivilege().getAction().toUpperCase())
                .SYMBOL);
        permsUpdater.handleUpdateNotification(update);
        LOGGER.info("Authz Perm preUpdate [" + update.getSeqNum() + "]..");
      }
    } catch (SentryNoSuchObjectException e) {
      String msg = "Role: " + request.getRoleName() + " doesn't exist.";
      LOGGER.error(msg, e);
      response.setStatus(Status.NoSuchObject(msg, e));
    } catch (SentryInvalidInputException e) {
      String msg = "Invalid input privilege object";
      LOGGER.error(msg, e);
      response.setStatus(Status.InvalidInput(msg, e));
    } catch (SentryAccessDeniedException e) {
      LOGGER.error(e.getMessage(), e);
      response.setStatus(Status.AccessDenied(e.getMessage(), e));
    } catch (Exception e) {
      String msg = "Unknown error for request: " + request + ", message: " + e.getMessage();
      LOGGER.error(msg, e);
      response.setStatus(Status.RuntimeError(msg, e));
    }

    AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance().createJsonLogEntity(
    		request, response, conf).toJsonFormatLog());
    return response;
  }

  @Override
  public TAlterSentryRoleRevokePrivilegeResponse alter_sentry_role_revoke_privilege
  (TAlterSentryRoleRevokePrivilegeRequest request) throws TException {
    TAlterSentryRoleRevokePrivilegeResponse response = new TAlterSentryRoleRevokePrivilegeResponse();
    try {
      CommitContext commitContext = sentryStore.alterSentryRoleRevokePrivilege(request.getRoleName(),
                                    request.getPrivilege());
      response.setStatus(Status.OK());
      notificationHandlerInvoker.alter_sentry_role_revoke_privilege(commitContext,
          request, response);
      String authzObj = getAuthzObj(request.getPrivilege());
      if (authzObj != null) {
        PermissionsUpdate update = new PermissionsUpdate(permSeqNum.incrementAndGet(), false);
        update.addPrivilegeUpdate(authzObj).putToDelPrivileges(
            request.getRoleName(),
            SentryStore.ACTION_MAPPING.get(request.getPrivilege().getAction().toUpperCase())
                .SYMBOL);
        permsUpdater.handleUpdateNotification(update);
        LOGGER.info("Authz Perm preUpdate [" + update.getSeqNum() + ", " + authzObj + "]..");
      }
    } catch (SentryNoSuchObjectException e) {
      String msg = "Privilege: [server=" + request.getPrivilege().getServerName() +
    		  ",db=" + request.getPrivilege().getDbName() +
    		  ",table=" + request.getPrivilege().getTableName() +
    		  ",URI=" + request.getPrivilege().getURI() +
    		  ",action=" + request.getPrivilege().getAction() + "] doesn't exist.";
      LOGGER.error(msg, e);
      response.setStatus(Status.NoSuchObject(msg, e));
    } catch (SentryInvalidInputException e) {
      String msg = "Invalid input privilege object";
      LOGGER.error(msg, e);
      response.setStatus(Status.InvalidInput(msg, e));
    } catch (SentryAccessDeniedException e) {
      LOGGER.error(e.getMessage(), e);
      response.setStatus(Status.AccessDenied(e.getMessage(), e));
    } catch (Exception e) {
      String msg = "Unknown error for request: " + request + ", message: " + e.getMessage();
      LOGGER.error(msg, e);
      response.setStatus(Status.RuntimeError(msg, e));
    }

    AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance().createJsonLogEntity(
    		request, response, conf).toJsonFormatLog());
    return response;
  }

  @Override
  public TDropSentryRoleResponse drop_sentry_role(
    TDropSentryRoleRequest request)  throws TException {
    TDropSentryRoleResponse response = new TDropSentryRoleResponse();
    TSentryResponseStatus status;
    try {
      authorize(request.getRequestorUserName(),
          getRequestorGroups(request.getRequestorUserName()));
      CommitContext commitContext = sentryStore.dropSentryRole(request.getRoleName());
      response.setStatus(Status.OK());
      notificationHandlerInvoker.drop_sentry_role(commitContext,
          request, response);
      PermissionsUpdate update = new PermissionsUpdate(permSeqNum.incrementAndGet(), false);
      update.addPrivilegeUpdate(PermissionsUpdate.ALL_AUTHZ_OBJ).putToDelPrivileges(
          request.getRoleName(), PermissionsUpdate.ALL_AUTHZ_OBJ);
      update.addRoleUpdate(request.getRoleName()).addToDelGroups(PermissionsUpdate.ALL_GROUPS);
      permsUpdater.handleUpdateNotification(update);
      LOGGER.info("Authz Perm preUpdate [" + update.getSeqNum() + ", " + request.getRoleName() + "]..");
    } catch (SentryNoSuchObjectException e) {
      String msg = "Role :" + request + " does not exist.";
      LOGGER.error(msg, e);
      response.setStatus(Status.NoSuchObject(msg, e));
    } catch (SentryAccessDeniedException e) {
      LOGGER.error(e.getMessage(), e);
      response.setStatus(Status.AccessDenied(e.getMessage(), e));
    } catch (Exception e) {
      String msg = "Unknown error for request: " + request + ", message: " + e.getMessage();
      LOGGER.error(msg, e);
      response.setStatus(Status.RuntimeError(msg, e));
    }

    AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance().createJsonLogEntity(
    		request, response, conf).toJsonFormatLog());
    return response;
  }

  @Override
  public TAlterSentryRoleAddGroupsResponse alter_sentry_role_add_groups(
    TAlterSentryRoleAddGroupsRequest request) throws TException {
    TAlterSentryRoleAddGroupsResponse response = new TAlterSentryRoleAddGroupsResponse();
    try {
      authorize(request.getRequestorUserName(),
          getRequestorGroups(request.getRequestorUserName()));
      CommitContext commitContext = sentryStore.alterSentryRoleAddGroups(request.getRequestorUserName(),
                                    request.getRoleName(), request.getGroups());
      response.setStatus(Status.OK());
      notificationHandlerInvoker.alter_sentry_role_add_groups(commitContext,
          request, response);
      PermissionsUpdate update = new PermissionsUpdate(permSeqNum.incrementAndGet(), false);
      TRoleChanges rUpdate = update.addRoleUpdate(request.getRoleName());
      for (TSentryGroup group : request.getGroups()) {
        rUpdate.addToAddGroups(group.getGroupName());
      }
      permsUpdater.handleUpdateNotification(update);
      LOGGER.info("Authz Perm preUpdate [" + update.getSeqNum() + ", " + request.getRoleName() + "]..");
    } catch (SentryNoSuchObjectException e) {
      String msg = "Role: " + request + " does not exist.";
      LOGGER.error(msg, e);
      response.setStatus(Status.NoSuchObject(msg, e));
    } catch (SentryAccessDeniedException e) {
      LOGGER.error(e.getMessage(), e);
      response.setStatus(Status.AccessDenied(e.getMessage(), e));
    } catch (Exception e) {
      String msg = "Unknown error for request: " + request + ", message: " + e.getMessage();
      LOGGER.error(msg, e);
      response.setStatus(Status.RuntimeError(msg, e));
    }

    AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance().createJsonLogEntity(
    		request, response, conf).toJsonFormatLog());
    return response;
  }

  @Override
  public TAlterSentryRoleDeleteGroupsResponse alter_sentry_role_delete_groups(
    TAlterSentryRoleDeleteGroupsRequest request) throws TException {
    TAlterSentryRoleDeleteGroupsResponse response = new TAlterSentryRoleDeleteGroupsResponse();
    try {
      authorize(request.getRequestorUserName(),
          getRequestorGroups(request.getRequestorUserName()));
      CommitContext commitContext = sentryStore.alterSentryRoleDeleteGroups(request.getRoleName(),
          request.getGroups());
      response.setStatus(Status.OK());
      notificationHandlerInvoker.alter_sentry_role_delete_groups(commitContext,
          request, response);
      PermissionsUpdate update = new PermissionsUpdate(permSeqNum.incrementAndGet(), false);
      TRoleChanges rUpdate = update.addRoleUpdate(request.getRoleName());
      for (TSentryGroup group : request.getGroups()) {
        rUpdate.addToDelGroups(group.getGroupName());
      }
      permsUpdater.handleUpdateNotification(update);
      LOGGER.info("Authz Perm preUpdate [" + update.getSeqNum() + ", " + request.getRoleName() + "]..");
    } catch (SentryNoSuchObjectException e) {
      String msg = "Role: " + request + " does not exist.";
      LOGGER.error(msg, e);
      response.setStatus(Status.NoSuchObject(msg, e));
    } catch (SentryAccessDeniedException e) {
      LOGGER.error(e.getMessage(), e);
      response.setStatus(Status.AccessDenied(e.getMessage(), e));
    } catch (Exception e) {
      String msg = "Unknown error adding groups to role: " + request;
      LOGGER.error(msg, e);
      response.setStatus(Status.RuntimeError(msg, e));
    }

    AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance().createJsonLogEntity(
    		request, response, conf).toJsonFormatLog());
    return response;
  }

  @Override
  public TListSentryRolesResponse list_sentry_roles_by_group(
    TListSentryRolesRequest request) throws TException {
    TListSentryRolesResponse response = new TListSentryRolesResponse();
    TSentryResponseStatus status;
    Set<TSentryRole> roleSet = new HashSet<TSentryRole>();
    Set<String> groups = new HashSet<String>();
    boolean checkAllGroups = false;
    try {
      // Don't check admin permissions for listing requestor's own roles
      if (AccessConstants.ALL.equalsIgnoreCase(request.getGroupName())) {
        groups = getRequestorGroups(request.getRequestorUserName());
        checkAllGroups = true;
      } else {
        authorize(request.getRequestorUserName(),
          getRequestorGroups(request.getRequestorUserName()));
        groups.add(request.getGroupName());
      }
      roleSet = sentryStore.getTSentryRolesByGroupName(groups, checkAllGroups);
      response.setRoles(roleSet);
      response.setStatus(Status.OK());
    } catch (SentryNoSuchObjectException e) {
      response.setRoles(roleSet);
      String msg = "Role: " + request + " couldn't be retrieved.";
      LOGGER.error(msg, e);
      response.setStatus(Status.NoSuchObject(msg, e));
    } catch (SentryAccessDeniedException e) {
      LOGGER.error(e.getMessage(), e);
      response.setStatus(Status.AccessDenied(e.getMessage(), e));
    } catch (Exception e) {
      String msg = "Unknown error for request: " + request + ", message: " + e.getMessage();
      LOGGER.error(msg, e);
      response.setStatus(Status.RuntimeError(msg, e));
    }
    return response;
  }

  @Override
  public TListSentryPrivilegesResponse list_sentry_privileges_by_role(
      TListSentryPrivilegesRequest request) throws TException {
    TListSentryPrivilegesResponse response = new TListSentryPrivilegesResponse();
    TSentryResponseStatus status;
    Set<TSentryPrivilege> privilegeSet = new HashSet<TSentryPrivilege>();
    String subject = request.getRequestorUserName();
    try {
      Set<String> groups = getRequestorGroups(subject);
      Boolean admin = inAdminGroups(groups);
      if(!admin) {
        Set<String> roleNamesForGroups = toTrimedLower(sentryStore.getRoleNamesForGroups(groups));
        if(!roleNamesForGroups.contains(request.getRoleName().trim().toLowerCase())) {
          throw new SentryAccessDeniedException("Access denied to " + subject);
        }
      }
      if (request.isSetAuthorizableHierarchy()) {
        TSentryAuthorizable authorizableHierarchy = request.getAuthorizableHierarchy();
        privilegeSet = sentryStore.getTSentryPrivileges(Sets.newHashSet(request.getRoleName()), authorizableHierarchy);
      } else {
        privilegeSet = sentryStore.getAllTSentryPrivilegesByRoleName(request.getRoleName());
      }
      response.setPrivileges(privilegeSet);
      response.setStatus(Status.OK());
    } catch (SentryNoSuchObjectException e) {
      response.setPrivileges(privilegeSet);
      String msg = "Privilege: " + request + " couldn't be retrieved.";
      LOGGER.error(msg, e);
      response.setStatus(Status.NoSuchObject(msg, e));
    } catch (SentryAccessDeniedException e) {
      LOGGER.error(e.getMessage(), e);
      response.setStatus(Status.AccessDenied(e.getMessage(), e));
    } catch (Exception e) {
      String msg = "Unknown error for request: " + request + ", message: " + e.getMessage();
      LOGGER.error(msg, e);
      response.setStatus(Status.RuntimeError(msg, e));
    }
    return response;
  }

  /**
   * This method was created specifically for ProviderBackend.getPrivileges() and is not meant
   * to be used for general privilege retrieval. More details in the .thrift file.
   */
  @Override
  public TListSentryPrivilegesForProviderResponse list_sentry_privileges_for_provider(
      TListSentryPrivilegesForProviderRequest request) throws TException {
    TListSentryPrivilegesForProviderResponse response = new TListSentryPrivilegesForProviderResponse();
    response.setPrivileges(new HashSet<String>());
    try {
      Set<String> privilegesForProvider = sentryStore.listSentryPrivilegesForProvider(
          request.getGroups(), request.getRoleSet(), request.getAuthorizableHierarchy());
      response.setPrivileges(privilegesForProvider);
      if (((privilegesForProvider == null)||(privilegesForProvider.size() == 0))&&(request.getAuthorizableHierarchy() != null)) {
        if (sentryStore.hasAnyServerPrivileges(
            request.getGroups(), request.getRoleSet(), request.getAuthorizableHierarchy().getServer())) {

          // REQUIRED for ensuring 'default' Db is accessible by any user
          // with privileges to atleast 1 object with the specific server as root

          // Need some way to specify that even though user has no privilege
          // For the specific AuthorizableHierarchy.. he has privilege on
          // atleast 1 object in the server hierarchy
          HashSet<String> serverPriv = Sets.newHashSet("server=+");
          response.setPrivileges(serverPriv);
        }
      }
      response.setStatus(Status.OK());
    } catch (Exception e) {
      String msg = "Unknown error for request: " + request + ", message: " + e.getMessage();
      LOGGER.error(msg, e);
      response.setStatus(Status.RuntimeError(msg, e));
    }
    return response;
  }

  // retrieve the group mapping for the given user name
  private Set<String> getRequestorGroups(String userName)
      throws SentryUserException {
    return getGroupsFromUserName(this.conf, userName);
  }

  public static Set<String> getGroupsFromUserName(Configuration conf,
      String userName) throws SentryUserException {
    String groupMapping = conf.get(ServerConfig.SENTRY_STORE_GROUP_MAPPING,
        ServerConfig.SENTRY_STORE_GROUP_MAPPING_DEFAULT);
    String authResoruce = conf
        .get(ServerConfig.SENTRY_STORE_GROUP_MAPPING_RESOURCE);

    // load the group mapping provider class
    GroupMappingService groupMappingService;
    try {
      Constructor<?> constrctor = Class.forName(groupMapping)
          .getDeclaredConstructor(Configuration.class, String.class);
      constrctor.setAccessible(true);
      groupMappingService = (GroupMappingService) constrctor
          .newInstance(new Object[] { conf, authResoruce });
    } catch (NoSuchMethodException e) {
      throw new SentryUserException("Unable to instantiate group mapping", e);
    } catch (SecurityException e) {
      throw new SentryUserException("Unable to instantiate group mapping", e);
    } catch (ClassNotFoundException e) {
      throw new SentryUserException("Unable to instantiate group mapping", e);
    } catch (InstantiationException e) {
      throw new SentryUserException("Unable to instantiate group mapping", e);
    } catch (IllegalAccessException e) {
      throw new SentryUserException("Unable to instantiate group mapping", e);
    } catch (IllegalArgumentException e) {
      throw new SentryUserException("Unable to instantiate group mapping", e);
    } catch (InvocationTargetException e) {
      throw new SentryUserException("Unable to instantiate group mapping", e);
    }
    return groupMappingService.getGroups(userName);
  }

  @Override
  public TDropPrivilegesResponse drop_sentry_privilege(
      TDropPrivilegesRequest request) throws TException {
    TDropPrivilegesResponse response = new TDropPrivilegesResponse();
    try {
      authorize(request.getRequestorUserName(), adminGroups);
      sentryStore.dropPrivilege(request.getAuthorizable());
      response.setStatus(Status.OK());
      // TODO : Sentry - HDFS : Have to handle this 
    } catch (SentryAccessDeniedException e) {
      LOGGER.error(e.getMessage(), e);
      response.setStatus(Status.AccessDenied(e.getMessage(), e));
    } catch (Exception e) {
      String msg = "Unknown error for request: " + request + ", message: "
          + e.getMessage();
      LOGGER.error(msg, e);
      response.setStatus(Status.RuntimeError(msg, e));
    }
    return response;
  }

  @Override
  public TRenamePrivilegesResponse rename_sentry_privilege(
      TRenamePrivilegesRequest request) throws TException {
    TRenamePrivilegesResponse response = new TRenamePrivilegesResponse();
    try {
      authorize(request.getRequestorUserName(), adminGroups);
      sentryStore.renamePrivilege(request.getOldAuthorizable(),
          request.getNewAuthorizable(), request.getRequestorUserName());
      response.setStatus(Status.OK());
      // TODO : Sentry - HDFS : Have to handle this
    } catch (SentryAccessDeniedException e) {
      LOGGER.error(e.getMessage(), e);
      response.setStatus(Status.AccessDenied(e.getMessage(), e));
    } catch (Exception e) {
      String msg = "Unknown error for request: " + request + ", message: "
          + e.getMessage();
      LOGGER.error(msg, e);
      response.setStatus(Status.RuntimeError(msg, e));
    }
    return response;
  }

  @Override
  public void handle_hms_notification(TPathsUpdate update) throws TException {
    if (pathsUpdater == null) {
      throw new TException("HiveMetastore Path Cache not enabled !!");
    }
    try {
      PathsUpdate hmsUpdate = new PathsUpdate(update);
      pathsUpdater.handleUpdateNotification(hmsUpdate);
      LOGGER.info("Authz Path preUpdate [" + hmsUpdate.getSeqNum() + "]..");
    } catch (Exception e) {
      LOGGER.error("Error handling notification from HMS", e);
      throw new TException(e);
    }
  }

  @Override
  public TAuthzUpdateResponse get_all_authz_updates_from(long permSeqNum, long pathSeqNum) throws TException {
    if (pathsUpdater == null) {
      throw new TException("HiveMetastore Path Cache not enabled !!");
    }
    List<PathsUpdate> pathUpdates = pathsUpdater.getAllUpdatesFrom(pathSeqNum);
    List<PermissionsUpdate> permUpdates = permsUpdater.getAllUpdatesFrom(permSeqNum);
    TAuthzUpdateResponse retVal = new TAuthzUpdateResponse();
    retVal.setAuthzPathUpdate(new LinkedList<TPathsUpdate>());
    retVal.setAuthzPermUpdate(new LinkedList<TPermissionsUpdate>());
    try {
      for (PathsUpdate update : pathUpdates) {
        if (LOGGER.isDebugEnabled()) {
          LOGGER.debug("### Sending PATH preUpdate seq [" + update.getSeqNum() + "] ###");
          LOGGER.debug("### Sending PATH preUpdate [" + update.getThriftObject() + "] ###");
        }
        retVal.getAuthzPathUpdate().add(update.getThriftObject());
      }
      for (PermissionsUpdate update : permUpdates) {
        if (LOGGER.isDebugEnabled()) {
          LOGGER.debug("### Sending PERM preUpdate seq [" + update.getSeqNum() + "] ###");
          LOGGER.debug("### Sending PERM preUpdate [" + update.getThriftObject() + "] ###");
        }
        retVal.getAuthzPermUpdate().add(update.getThriftObject());
      }
    } catch (Exception e) {
      LOGGER.error("Error Sending updates to downstream Cache", e);
      throw new TException(e);
    }
    return retVal;
  }

  @Override
  public Map<String, List<String>> get_all_related_paths(String path,
      boolean exactMatch) throws TException {
    if (pathsUpdater == null) {
      throw new TException("HiveMetastore Path Cache not enabled !!");
    }
//    Map<String, LinkedList<String>> relatedPaths = hmsPathCache
//        .getAllRelatedPaths(path, exactMatch);
    return new HashMap<String, List<String>>();
  }

  private String getAuthzObj(TSentryPrivilege privilege) {
    String authzObj = null;
    if (!SentryStore.isNULL(privilege.getDbName())) {
      String dbName = privilege.getDbName();
      String tblName = privilege.getTableName();
      if (tblName == null) {
        authzObj = dbName;
      } else {
        authzObj = dbName + "." + tblName;
      }
    }
    return authzObj;
  }

}
