/**
 * 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.hdfs;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.hadoop.conf.Configuration;
import org.apache.sentry.api.common.ApiConstants.PrivilegeScope;
import org.apache.sentry.core.common.exception.SentryInvalidInputException;
import org.apache.sentry.core.common.utils.PubSub;
import org.apache.sentry.core.common.utils.SentryUtils;
import org.apache.sentry.core.common.utils.SigUtils;
import org.apache.sentry.hdfs.ServiceConstants.ServerConfig;
import org.apache.sentry.hdfs.service.thrift.TPrivilegeChanges;
import org.apache.sentry.hdfs.service.thrift.TPrivilegePrincipal;
import org.apache.sentry.hdfs.service.thrift.TPrivilegePrincipalType;
import org.apache.sentry.hdfs.service.thrift.TRoleChanges;
import org.apache.sentry.provider.db.SentryPolicyStorePlugin;
import org.apache.sentry.provider.db.service.persistent.SentryStoreInterface;
import org.apache.sentry.api.common.SentryServiceUtil;
import org.apache.sentry.api.service.thrift.TAlterSentryRoleAddGroupsRequest;
import org.apache.sentry.api.service.thrift.TAlterSentryRoleDeleteGroupsRequest;
import org.apache.sentry.api.service.thrift.TDropPrivilegesRequest;
import org.apache.sentry.api.service.thrift.TDropSentryRoleRequest;
import org.apache.sentry.api.service.thrift.TRenamePrivilegesRequest;
import org.apache.sentry.api.service.thrift.TSentryGroup;
import org.apache.sentry.api.service.thrift.TSentryPrivilege;
import org.apache.sentry.provider.db.service.persistent.HMSFollower;
import com.google.common.base.Preconditions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.apache.sentry.hdfs.ServiceConstants.IMAGE_NUMBER_UPDATE_UNINITIALIZED;
import static org.apache.sentry.hdfs.ServiceConstants.SEQUENCE_NUMBER_UPDATE_UNINITIALIZED;
import static org.apache.sentry.hdfs.ServiceConstants.ServerConfig.SENTRY_HDFS_INTEGRATION_PATH_PREFIXES;
import static org.apache.sentry.hdfs.ServiceConstants.ServerConfig.SENTRY_HDFS_INTEGRATION_PATH_PREFIXES_DEFAULT;
import static org.apache.sentry.hdfs.Updateable.Update;
import static org.apache.sentry.hdfs.service.thrift.sentry_hdfs_serviceConstants.UNUSED_PATH_UPDATE_IMG_NUM;

/**
   * SentryPlugin listens to all sentry permission update events, persists permission
   * changes into database. It also facilitates HDFS synchronization between HMS and NameNode.
   * <p>
   * Synchronization happens via a complete snapshot or partial (incremental) updates.
   * Normally, it is the latter:
   * <ol>
   * <li>
   * Whenever updates happen on HMS, a corresponding notification log is generated,
   * and {@link HMSFollower} will process the notification event and persist it in database.
   * <li>
   * The NameNode periodically asks Sentry for updates. Sentry may return zero
   * or more updates previously received via HMS notification log.
   * </ol>
   * <p>
   * Each individual update is assigned a corresponding sequence number and an image number
   * to synchronize updates between Sentry and NameNode.
   * <p>
   * The image number may be used to identify whether new full updates are persisted and need
   * to be retrieved instead of delta updates.
   * <p>
   * SentryPlugin implements mechanism of triggering full path updates from Sentry to NameNode,
   * to address mission-critical out-of-sync situations that may be encountered in the field.
   * Those out-of-sync situations may not be detectable via the exsiting sequence
   * numbers mechanism (most likely due to the implementation bugs).
   * <p>
   * To trigger full update from Sentry to NameNode, the boolean variable 'fullUpdateNN' is
   * used to ensure that Sentry sends full update to NameNode, and does so only once per
   * triggering event.
   * </ol>
   * The details:
   * <ol>
   * <li>
   * There are two mechanisms to trigger full update: by signal (deprecated) and via WebUI.
   * Both mechanisms are configurable and turned OFF by default.
   * <li>
   * To use signal mechanism, SentryPlugin uses SigUtils to subscribe to specific
   * (configurable) signal that should be delivered to JVM running Sentry server.
   * <li>
   * To use the WebUI mechanism, SentryPlugin uses PubSub which provides publish-subscribe
   * framework. SentryPlugin subscribed to PubSub.Topic.HDFS_SYNC_NN topic.
   * 
   * Upon receiving a signal,  or upon been notified via pub-sub mechanism, fullUpdateNN
   * is set to true.
   * <li>
   * When NameNode calls getAllPathsUpdatesFrom() asking for partial update,
   * Sentry checks if both fullUpdateNN == true. If yes, it sends full update back
   * to NameNode and immediately resets fullUpdateNN to false.
   * </ol>
   */

public class SentryPlugin implements SentryPolicyStorePlugin, SigUtils.SigListener, PubSub.Subscriber {

  private static final Logger LOGGER = LoggerFactory.getLogger(SentryPlugin.class);
  private static final String FULL_UPDATE_TRIGGER = "FULL UPDATE TRIGGER: ";

  private final AtomicBoolean fullUpdateNN = new AtomicBoolean(false);
  public static volatile SentryPlugin instance;

  private DBUpdateForwarder<PathsUpdate> pathsUpdater;
  private DBUpdateForwarder<PermissionsUpdate> permsUpdater;

  @Override
  public void initialize(Configuration conf, SentryStoreInterface sentryStore) throws SentryPluginException {
    // List of paths managed by Sentry
    String[] prefixes =
            conf.getStrings(SENTRY_HDFS_INTEGRATION_PATH_PREFIXES,
                    SENTRY_HDFS_INTEGRATION_PATH_PREFIXES_DEFAULT);
    PermImageRetriever permImageRetriever = new PermImageRetriever(sentryStore);
    PathImageRetriever pathImageRetriever = new PathImageRetriever(sentryStore, prefixes);
    PermDeltaRetriever permDeltaRetriever = new PermDeltaRetriever(sentryStore);
    PathDeltaRetriever pathDeltaRetriever = new PathDeltaRetriever(sentryStore);
    pathsUpdater = new DBUpdateForwarder<>(pathImageRetriever, pathDeltaRetriever);
    permsUpdater = new DBUpdateForwarder<>(permImageRetriever, permDeltaRetriever);

    LOGGER.info("Sentry HDFS plugin initialized !!");
    instance = this;

    // register signal handler(s) if any signal(s) are configured
    String[] sigs = conf.getStrings(ServerConfig.SENTRY_SERVICE_FULL_UPDATE_SIGNAL, null);
    if (sigs != null && sigs.length != 0) {
      for (String sig : sigs) {
        try {
          LOGGER.info("SIGNAL HANDLING: Registering Signal Handler For " + sig);
          SigUtils.registerSigListener(sig, this);
        } catch (Exception e) {
          LOGGER.error("SIGNAL HANDLING: Signal Handle Registration Failure", e);
        }
      }
    }

    // subscribe to full update notification
    if (conf.getBoolean(ServerConfig.SENTRY_SERVICE_FULL_UPDATE_PUBSUB, false)) {
      LOGGER.info(FULL_UPDATE_TRIGGER + "subscribing to topic " + PubSub.Topic.HDFS_SYNC_NN.getName());
      PubSub.getInstance().subscribe(PubSub.Topic.HDFS_SYNC_NN, this);
    }
  }

  /**
   * Request for update from NameNode.
   * Full update to NameNode should happen only after full update from HMS.
   */
  public List<PathsUpdate> getAllPathsUpdatesFrom(long pathSeqNum, long pathImgNum) throws Exception {
    if (!fullUpdateNN.get()) {
      // Most common case - Sentry is NOT handling a full update.
      LOGGER.debug("Received request for PATH update from NameNode for pathSeqNum {} and pathImgNum {}", pathSeqNum, pathImgNum);
      return pathsUpdater.getAllUpdatesFrom(pathSeqNum, pathImgNum);
    }

    /*
     * Sentry is in the middle of signal-triggered full update.
     * It already got a full update from HMS
     */
    LOGGER.info(FULL_UPDATE_TRIGGER + "sending full PATH update to NameNode");
    fullUpdateNN.set(false); // don't do full NN update till the next signal
    List<PathsUpdate> updates =
        pathsUpdater.getAllUpdatesFrom(SEQUENCE_NUMBER_UPDATE_UNINITIALIZED, IMAGE_NUMBER_UPDATE_UNINITIALIZED);
    /*
     * This code branch is only called when Sentry is in the middle of a full update
     * (fullUpdateNN == true) and Sentry has already received full update from HMS
     * (fullUpdateHMSWait == false). It means that the local cache has a full update
     * from HMS.
     *
     * The full update list is expected to contain the last full update as the first
     * element, followed by zero or more subsequent partial updates.
     *
     * Returning NULL, empty, or partial update instead would be unexplainable, so
     * it should be logged.
     */
    if (updates != null) {
      if (!updates.isEmpty()) {
        if (updates.get(0).hasFullImage()) {
          LOGGER.info(FULL_UPDATE_TRIGGER + "Confirmed full PATH update to NameNode for pathSeqNum {} and pathImgNum {}", pathSeqNum, pathImgNum);
        } else {
          LOGGER.warn(FULL_UPDATE_TRIGGER + "Sending partial instead of full PATH update to NameNode  for pathSeqNum {} and pathImgNum {} (???)", pathSeqNum, pathImgNum);
        }
      } else {
        LOGGER.warn(FULL_UPDATE_TRIGGER + "Sending empty instead of full PATH update to NameNode  for pathSeqNum {} and pathImgNum {} (???)", pathSeqNum, pathImgNum);
      }
    } else {
      LOGGER.warn(FULL_UPDATE_TRIGGER + "returned NULL instead of full PATH update to NameNode  for pathSeqNum {} and pathImgNum {} (???)", pathSeqNum, pathImgNum);
    }
    return updates;
  }

  public List<PermissionsUpdate> getAllPermsUpdatesFrom(long permSeqNum) throws Exception {
    LOGGER.debug("Received request for PERM update from NameNode for permSeqNum {}", permSeqNum);
    return permsUpdater.getAllUpdatesFrom(permSeqNum, UNUSED_PATH_UPDATE_IMG_NUM);
  }

  @Override
  public Update onAlterSentryRoleAddGroups(
      TAlterSentryRoleAddGroupsRequest request) throws SentryPluginException {
    Preconditions.checkNotNull(request, "request");
    if (LOGGER.isTraceEnabled()) {
      LOGGER.trace("onAlterSentryRoleAddGroups: {}", request); // request.toString() provides all details
    }
    PermissionsUpdate update = new PermissionsUpdate();
    TRoleChanges rUpdate = update.addRoleUpdate(request.getRoleName());
    for (TSentryGroup group : request.getGroups()) {
      rUpdate.addToAddGroups(group.getGroupName());
    }

    LOGGER.debug(String.format("onAlterSentryRoleAddGroups, Authz Perm preUpdate[ %s ]",
                  request.getRoleName()));
    if (LOGGER.isTraceEnabled()) {
      LOGGER.trace("onAlterSentryRoleAddGroups: {}", update); // update.toString() provides all details
    }
    return update;
  }

  @Override
  public Update onAlterSentryRoleDeleteGroups(
      TAlterSentryRoleDeleteGroupsRequest request)
          throws SentryPluginException {
    Preconditions.checkNotNull(request, "request");
    if (LOGGER.isTraceEnabled()) {
      LOGGER.trace("onAlterSentryRoleDeleteGroups: {}", request); // request.toString() provides all details
    }
    PermissionsUpdate update = new PermissionsUpdate();
    TRoleChanges rUpdate = update.addRoleUpdate(request.getRoleName());
    for (TSentryGroup group : request.getGroups()) {
      rUpdate.addToDelGroups(group.getGroupName());
    }

    LOGGER.debug(String.format("onAlterSentryRoleDeleteGroups, Authz Perm preUpdate [ %s ]",
                  request.getRoleName()));
    if (LOGGER.isTraceEnabled()) {
      LOGGER.trace("onAlterSentryRoleDeleteGroups: {}", update); // update.toString() provides all details
    }
    return update;
  }

  @Override
  public void onAlterSentryRoleGrantPrivilege(String roleName, Set<TSentryPrivilege> privileges,
                                              Map<TSentryPrivilege, Update> privilegesUpdateMap) throws SentryPluginException {
    Preconditions.checkNotNull(roleName, "Role name is NULL");
    Preconditions.checkNotNull(privilegesUpdateMap, "Privilege MAP NULL");
    Preconditions.checkNotNull(privileges, "Privilege Set provided is NULL");

    if (LOGGER.isTraceEnabled()) {
      LOGGER.trace("onAlterSentryRoleGrantPrivilege: {}", roleName, privileges);
    }

    if (privileges.size() > 0) {
      for (TSentryPrivilege privilege : privileges) {
        if(!(PrivilegeScope.COLUMN.name().equalsIgnoreCase(privilege.getPrivilegeScope()))) {
          PermissionsUpdate update = onAlterSentryGrantPrivilegeCore(new TPrivilegePrincipal(TPrivilegePrincipalType.ROLE,
                  roleName), privilege);
          if (update != null && privilegesUpdateMap != null) {
            privilegesUpdateMap.put(privilege, update);
          }
        }
      }
    }
    if (LOGGER.isTraceEnabled()) {
      // TSentryPrivilege.toString() and update.toString() provides all details
      LOGGER.trace("onAlterSentryRoleGrantPrivilege: {}", privilegesUpdateMap);
    }
  }

  @Override
  public void onAlterSentryUserGrantPrivilege(String userName, Set<TSentryPrivilege> privileges,
                Map<TSentryPrivilege, Update> privilegesUpdateMap) throws SentryPluginException {
    Preconditions.checkNotNull(userName, "User name is NULL");
    Preconditions.checkNotNull(privilegesUpdateMap, "Privilege MAP NULL");
    Preconditions.checkNotNull(privileges, "Privilege Set provided is NULL");

    if (LOGGER.isTraceEnabled()) {
      LOGGER.trace("onAlterSentryUserGrantPrivilege: {}", userName, privileges);
    }

    if (privileges.size() > 0) {
      for (TSentryPrivilege privilege : privileges) {
        if(!(PrivilegeScope.COLUMN.name().equalsIgnoreCase(privilege.getPrivilegeScope()))) {
          PermissionsUpdate update = onAlterSentryGrantPrivilegeCore(new TPrivilegePrincipal(TPrivilegePrincipalType.USER,
            userName), privilege);
          if (update != null && privilegesUpdateMap != null) {
            privilegesUpdateMap.put(privilege, update);
          }
        }
      }
    }
    if (LOGGER.isTraceEnabled()) {
      // TSentryPrivilege.toString() and update.toString() provides all details
      LOGGER.trace("onAlterSentryUserGrantPrivilege: {}", privilegesUpdateMap);
    }
  }

  private PermissionsUpdate onAlterSentryGrantPrivilegeCore(TPrivilegePrincipal TPrivilegePrincipal, TSentryPrivilege privilege)
          throws SentryPluginException {
    String authzObj = getAuthzObj(privilege);
    if (authzObj == null) {
      return null;
    }

    PermissionsUpdate update = new PermissionsUpdate();
    update.addPrivilegeUpdate(authzObj).putToAddPrivileges( TPrivilegePrincipal, privilege.getAction().toUpperCase());

    LOGGER.debug(String.format("onAlterSentryRoleGrantPrivilegeCore, Authz Perm preUpdate [ %s ]",
                  authzObj));
    return update;
  }

  @Override
  public Update onRenameSentryPrivilege(TRenamePrivilegesRequest request)
      throws SentryPluginException, SentryInvalidInputException{
    Preconditions.checkNotNull(request, "request");
    if (LOGGER.isTraceEnabled()) {
      LOGGER.trace("onRenameSentryPrivilege: {}", request); // request.toString() provides all details
    }
    String oldAuthz = null;
    String newAuthz = null;
    try {
      oldAuthz = SentryServiceUtil.getAuthzObj(request.getOldAuthorizable());
      newAuthz = SentryServiceUtil.getAuthzObj(request.getNewAuthorizable());
    } catch (SentryInvalidInputException failure) {
      LOGGER.error("onRenameSentryPrivilege, Could not rename sentry privilege ", failure);
      throw failure;
    }
    PermissionsUpdate update = new PermissionsUpdate();
    TPrivilegeChanges privUpdate = update.addPrivilegeUpdate(PermissionsUpdate.RENAME_PRIVS);
    privUpdate.putToAddPrivileges(new TPrivilegePrincipal(TPrivilegePrincipalType.AUTHZ_OBJ, newAuthz), newAuthz);
    privUpdate.putToDelPrivileges(new TPrivilegePrincipal(TPrivilegePrincipalType.AUTHZ_OBJ,oldAuthz), oldAuthz);

    LOGGER.debug("onRenameSentryPrivilege, Authz Perm preUpdate [ {} ]", oldAuthz);
    if (LOGGER.isTraceEnabled()) {
      LOGGER.trace("onRenameSentryPrivilege: {}", update); // update.toString() provides all details
    }
    return update;
  }

  @Override
  public void onAlterSentryRoleRevokePrivilege(String roleName, Set<TSentryPrivilege> privileges,
                                               Map<TSentryPrivilege, Update> privilegesUpdateMap)
          throws SentryPluginException {
    Preconditions.checkNotNull(roleName, "Role name is NULL");
    Preconditions.checkNotNull(privilegesUpdateMap, "Privilege MAP NULL");
    Preconditions.checkNotNull(privileges, "Privilege Set provided is NULL");

    if (LOGGER.isTraceEnabled()) {
      LOGGER.trace("onAlterSentryRoleRevokePrivilege: {}", roleName, privileges);
    }

    if (privileges.size() > 0) {
      for (TSentryPrivilege privilege : privileges) {
        if(!("COLUMN".equalsIgnoreCase(privilege.getPrivilegeScope()))) {
          PermissionsUpdate update = onAlterSentryRevokePrivilegeCore(new TPrivilegePrincipal(TPrivilegePrincipalType.ROLE,
                  roleName), privilege);
          if (update != null && privilegesUpdateMap != null) {
            privilegesUpdateMap.put(privilege, update);
          }
        }
      }
    }
    if (LOGGER.isTraceEnabled()) {
      // TSentryPrivilege.toString() and Update.toString() provides all details
      LOGGER.trace("onAlterSentryRoleRevokePrivilege: {}", privilegesUpdateMap);
    }
  }

  @Override
  public void onAlterSentryUserRevokePrivilege(String userName, Set<TSentryPrivilege> privileges,
                                               Map<TSentryPrivilege, Update> privilegesUpdateMap)
          throws SentryPluginException {
    Preconditions.checkNotNull(userName, "User name is NULL");
    Preconditions.checkNotNull(privilegesUpdateMap, "Privilege MAP NULL");
    Preconditions.checkNotNull(privileges, "Privilege Set provided is NULL");

    if (LOGGER.isTraceEnabled()) {
      LOGGER.trace("onAlterSentryUserRevokePrivilege: {}", userName, privileges);
    }

    if (privileges.size() > 0) {
      for (TSentryPrivilege privilege : privileges) {
        if(!("COLUMN".equalsIgnoreCase(privilege.getPrivilegeScope()))) {
          PermissionsUpdate update = onAlterSentryRevokePrivilegeCore(new TPrivilegePrincipal(TPrivilegePrincipalType.USER,
                  userName), privilege);
          if (update != null && privilegesUpdateMap != null) {
            privilegesUpdateMap.put(privilege, update);
          }
        }
      }
    }
    if (LOGGER.isTraceEnabled()) {
      // TSentryPrivilege.toString() and Update.toString() provides all details
      LOGGER.trace("onAlterSentryUserRevokePrivilege: {}", privilegesUpdateMap);
    }
  }

  private PermissionsUpdate onAlterSentryRevokePrivilegeCore(TPrivilegePrincipal TPrivilegePrincipal, TSentryPrivilege privilege)
      throws SentryPluginException {
    String authzObj = getAuthzObj(privilege);
    if (authzObj == null) {
      return null;
    }

    PermissionsUpdate update = new PermissionsUpdate();
    update.addPrivilegeUpdate(authzObj).putToDelPrivileges(TPrivilegePrincipal, privilege.getAction().toUpperCase());

    LOGGER.debug("onAlterSentryRoleRevokePrivilegeCore, Authz Perm preUpdate [ {} ]", authzObj);
    return update;
  }

  @Override
  public Update onDropSentryRole(TDropSentryRoleRequest request)
      throws SentryPluginException {
    Preconditions.checkNotNull(request, "request");
    if (LOGGER.isTraceEnabled()) {
      LOGGER.trace("onDropSentryRole: {}", request); // request.toString() provides all details
    }
    PermissionsUpdate update = new PermissionsUpdate();
    update.addPrivilegeUpdate(PermissionsUpdate.ALL_AUTHZ_OBJ).putToDelPrivileges(
            new TPrivilegePrincipal(TPrivilegePrincipalType.ROLE, request.getRoleName()),
            PermissionsUpdate.ALL_AUTHZ_OBJ);
    update.addRoleUpdate(request.getRoleName()).addToDelGroups(PermissionsUpdate.ALL_GROUPS);

    LOGGER.debug("onDropSentryRole, Authz Perm preUpdate [ {} ]", request.getRoleName());
    if (LOGGER.isTraceEnabled()) {
      LOGGER.trace("onDropSentryRole: {}", update); // update.toString() provides all details
    }
    return update;
  }

  @Override
  public Update onDropSentryPrivilege(TDropPrivilegesRequest request)
      throws SentryPluginException {
    Preconditions.checkNotNull(request, "request");
    if (LOGGER.isTraceEnabled()) {
      LOGGER.trace("onDropSentryPrivilege: {}", request); // request.toString() provides all details
    }

    PermissionsUpdate update = new PermissionsUpdate();
    String authzObj = null;
    try {
       authzObj = SentryServiceUtil.getAuthzObj(request.getAuthorizable());
    } catch (SentryInvalidInputException failure) {
      LOGGER.error("onDropSentryPrivilege, Could not drop sentry privilege "
        + failure.toString(), failure);
      throw new SentryPluginException(failure.getMessage(), failure);
    }

    // The value of TPrivilegePrincipal being PermissionsUpdate.ALL_PRIVS indicates that all privileges
    // associated with this authorizable should be deleted, including both role and user, i.e.,
    // the key value of TPrivilegePrincipalType.ROLE is ignored.
    update.addPrivilegeUpdate(authzObj).putToDelPrivileges(
            new TPrivilegePrincipal(TPrivilegePrincipalType.ROLE,PermissionsUpdate.ALL_PRIVS),
            PermissionsUpdate.ALL_PRIVS);

    LOGGER.debug("onDropSentryPrivilege, Authz Perm preUpdate [ {} ]", authzObj);
    if (LOGGER.isTraceEnabled()) {
      LOGGER.trace("onDropSentryPrivilege: {}", update); // update.toString() provides all details
    }
    return update;
  }

  /**
   * SigUtils.SigListener callback API
   */
  @Override
  public void onSignal(final String sigName) {
    LOGGER.info("SIGNAL HANDLING: Received signal " + sigName + ", triggering full update");
    fullUpdateNN.set(true);
  }

  /**
   * PubSub.Subscriber callback API
   */
  @Override
  public void onMessage(PubSub.Topic topic, String message) {
    Preconditions.checkArgument(topic == PubSub.Topic.HDFS_SYNC_NN, "Unexpected topic %s instead of %s", topic, PubSub.Topic.HDFS_SYNC_NN);
    LOGGER.info(FULL_UPDATE_TRIGGER + "Received [{}, {}] notification", topic, message);
    fullUpdateNN.set(true);
  }

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