code: public static UserGroupInformation getHadoopAndHiveTokensForProxyUser(final State state, Optional<File> tokenFile,
        UserGroupInformation ugi, IMetaStoreClient client, String targetUser) throws IOException, InterruptedException {
      final Credentials cred = new Credentials();
      ugi.doAs(new PrivilegedExceptionAction<Void>() {
        @Override
        public Void run() throws Exception {
          getHadoopTokens(state, Optional.absent(), cred);
          return null;
        }
      });
  
      ugi.getCredentials().addAll(cred);
      // Will add hive tokens into ugi in this method.
      getHiveToken(state, client, cred, targetUser, ugi);
  
      if (tokenFile.isPresent()) {
        persistTokens(cred, tokenFile.get());
      }
      // at this point, tokens in ugi can be more than that in Credential object,
      // since hive token is not put in Credential object.
      return ugi;
    }
docs: Get Hadoop tokens (tokens for job history server, job tracker, hive and HDFS) using Kerberos keytab,
  on behalf on a proxy user, embed tokens into a {@link UserGroupInformation} as returned result, persist in-memory
  credentials if tokenFile specified
  
  Note that when a super-user is fetching tokens for other users,
  {@link #fetchHcatToken(String, HiveConf, String, IMetaStoreClient)} getDelegationToken} explicitly
  contains a string parameter indicating proxy user, while other hadoop services require impersonation first.
  
  @param state A {@link State} object that should contain properties.
  @param tokenFile If present, the file will store materialized credentials.
  @param ugi The {@link UserGroupInformation} that used to impersonate into the proxy user by a "doAs block".
  @param targetUser The user to be impersonated as, for fetching hadoop tokens.
  @return A {@link UserGroupInformation} containing negotiated credentials.