private void createAndRestoreTable(Connection conn, TableName tableName, TableName newTableName,
    Path tableBackupPath, boolean truncateIfExists, boolean isKeepOriginalSplits,
    String lastIncrBackupId) throws IOException {
    if (newTableName == null) {
      newTableName = tableName;
    }
    FileSystem fileSys = tableBackupPath.getFileSystem(this.conf);

    // get table descriptor first
    TableDescriptor tableDescriptor = getTableDescriptor(fileSys, tableName, lastIncrBackupId);
    if (tableDescriptor != null) {
      LOG.debug("Retrieved descriptor: " + tableDescriptor + " thru " + lastIncrBackupId);
    }

    if (tableDescriptor == null) {
      Path tableSnapshotPath = getTableSnapshotPath(backupRootPath, tableName, backupId);
      if (fileSys.exists(tableSnapshotPath)) {
        // snapshot path exist means the backup path is in HDFS
        // check whether snapshot dir already recorded for target table
        if (snapshotMap.get(tableName) != null) {
          SnapshotDescription desc =
            SnapshotDescriptionUtils.readSnapshotInfo(fileSys, tableSnapshotPath);
          SnapshotManifest manifest = SnapshotManifest.open(conf, fileSys, tableSnapshotPath, desc);
          tableDescriptor = manifest.getTableDescriptor();
        } else {
          tableDescriptor = getTableDesc(tableName);
          snapshotMap.put(tableName, getTableInfoPath(tableName));
        }
        if (tableDescriptor == null) {
          LOG.debug("Found no table descriptor in the snapshot dir, previous schema would be lost");
        }
      } else {
        throw new IOException(
          "Table snapshot directory: " + tableSnapshotPath + " does not exist.");
      }
    }

    Path tableArchivePath = getTableArchivePath(tableName);
    if (tableArchivePath == null) {
      if (tableDescriptor != null) {
        // find table descriptor but no archive dir means the table is empty, create table and exit
        if (LOG.isDebugEnabled()) {
          LOG.debug("find table descriptor but no archive dir for table " + tableName
            + ", will only create table");
        }
        tableDescriptor = TableDescriptorBuilder.copy(newTableName, tableDescriptor);
        checkAndCreateTable(conn, newTableName, null, tableDescriptor, truncateIfExists);
        return;
      } else {
        throw new IllegalStateException(
          "Cannot restore hbase table because directory '" + " tableArchivePath is null.");
      }
    }

    if (tableDescriptor == null) {
      tableDescriptor = TableDescriptorBuilder.newBuilder(newTableName).build();
    } else {
      tableDescriptor = TableDescriptorBuilder.copy(newTableName, tableDescriptor);
    }

    // record all region dirs:
    // load all files in dir
    try {
      ArrayList<Path> regionPathList = getRegionList(tableName);

      // should only try to create the table with all region informations, so we could pre-split
      // the regions in fine grain
      checkAndCreateTable(conn, newTableName, regionPathList, tableDescriptor, truncateIfExists);
      configureForRestoreJob(isKeepOriginalSplits);
      RestoreJob restoreService = BackupRestoreFactory.getRestoreJob(conf);
      Path[] paths = new Path[regionPathList.size()];
      regionPathList.toArray(paths);
      restoreService.run(paths, new TableName[] { tableName }, restoreRootDir,
        new TableName[] { newTableName }, true);

    } catch (Exception e) {
      LOG.error(e.toString(), e);
      throw new IllegalStateException("Cannot restore hbase table", e);
    }
  }
Get table descriptor
@param tableName is the table backed up
@return {@link TableDescriptor} saved in backup image of the table
hbase-backup/src/main/java/org/apache/hadoop/hbase/backup/util/RestoreTool.java