/**
   * Delete the entire tree. This is an internal one with slightly different behavior: if an entry
   * is missing, a {@link FileNotFoundException} is raised. This lets the caller distinguish a file
   * not found with other reasons for failure, so handles race conditions in recursive directory
   * deletes better.
   *
   * <p>The problem being addressed is: caller A requests a recursive directory of directory /dir ;
   * caller B requests a delete of a file /dir/file, between caller A enumerating the files
   * contents, and requesting a delete of /dir/file. We want to recognise the special case "directed
   * file is no longer there" and not convert that into a failure
   *
   * @param path the path to delete.
   * @param recursive if path is a directory and set to true, the directory is deleted else throws
   *     an exception if the directory is not empty case of a file the recursive can be set to
   *     either true or false.
   * @return true if the object was deleted
   * @throws IOException IO problems
   * @throws FileNotFoundException if a file/dir being deleted is not there - this includes entries
   *     below the specified path, (if the path is a dir and recursive is true)
   */
  private boolean innerDelete(Path path, boolean recursive) throws IOException {
    Path target = makeAbsolute(path);
    final FileStatus fileStatus;
    fileStatus = getFileStatus(path);
    if (LOG.isDebugEnabled()) {
      LOG.debug("Deleting path '" + path + "'");
    }
    if (!SwiftUtils.isDirectory(fileStatus)) {
      // simple file: delete it
      if (LOG.isDebugEnabled()) {
        LOG.debug("Deleting simple file '" + path + "'");
      }
      store.deleteObject(target);
    } else {
      // it's a directory
      if (LOG.isDebugEnabled()) {
        LOG.debug("Deleting directory '" + path + "'");
      }

      // get all entries
      List<FileStatus> children = store.listDirectory(target, true, true);

      // look to see if there are now any children
      if (!children.isEmpty() && !recursive) {
        // if there are children, unless this is a recursive operation, fail immediately
        throw new SwiftOperationFailedException("Directory " + path + " is not empty.");
      }

      // delete the children
      for (FileStatus child : children) {
        Path childPath = child.getPath();
        try {
          store.deleteObject(childPath);
        } catch (FileNotFoundException e) {
          // the path went away -race conditions.
          // do not fail, as the outcome is still OK.
          LOG.info("Path " + childPath + " is no longer present");
        }
      }
      // here any children that existed have been deleted
      // so rm the directory (which is a no-op for /)
      store.rmdir(target);
    }

    return true;
  }
  /**
   * Delete the entire tree. This is an internal one with slightly different behavior: if an entry
   * is missing, a {@link FileNotFoundException} is raised. This lets the caller distinguish a file
   * not found with other reasons for failure, so handles race conditions in recursive directory
   * deletes better.
   *
   * <p>The problem being addressed is: caller A requests a recursive directory of directory /dir ;
   * caller B requests a delete of a file /dir/file, between caller A enumerating the files
   * contents, and requesting a delete of /dir/file. We want to recognise the special case "directed
   * file is no longer there" and not convert that into a failure
   *
   * @param path the path to delete.
   * @param recursive if path is a directory and set to true, the directory is deleted else throws
   *     an exception if the directory is not empty case of a file the recursive can be set to
   *     either true or false.
   * @return true if the object was deleted
   * @throws IOException IO problems
   * @throws FileNotFoundException if a file/dir being deleted is not there - this includes entries
   *     below the specified path, (if the path is a dir and recursive is true)
   */
  private boolean innerDelete(Path path, boolean recursive) throws IOException {
    Path absolutePath = makeAbsolute(path);
    final FileStatus fileStatus;
    fileStatus = getFileStatus(path);
    if (LOG.isDebugEnabled()) {
      LOG.debug("Deleting path '" + path + "'");
    }
    if (!SwiftUtils.isDirectory(fileStatus)) {
      // simple file: delete it
      if (LOG.isDebugEnabled()) {
        LOG.debug("Deleting simple file '" + path + "'");
      }
      store.deleteObject(absolutePath);
    } else {
      // it's a directory
      if (LOG.isDebugEnabled()) {
        LOG.debug("Deleting directory '" + path + "'");
      }
      FileStatus[] contents = listStatus(absolutePath);
      if (contents == null) {
        // the directory went away during the non-atomic stages of the operation.
        // Return false as it was not this thread doing the deletion.
        if (LOG.isDebugEnabled()) {
          LOG.debug("Path '" + path + "' has no status -it has 'gone away'");
        }
        return false;
      }
      // now build a list without ourselves in it
      Path dirPath = fileStatus.getPath();
      if (LOG.isDebugEnabled()) {
        LOG.debug("Found " + contents.length + " child entries under " + dirPath);
      }
      ArrayList<FileStatus> children = new ArrayList<FileStatus>(contents.length);
      for (FileStatus child : contents) {
        if (!(child.getPath().equals(dirPath))) {
          if (LOG.isDebugEnabled()) {
            LOG.debug(child.toString());
          }
          children.add(child);
        } else {
          if (LOG.isDebugEnabled()) {
            LOG.debug("skipping own entry");
          }
        }
      }

      // look to see if there are now any children
      if (!children.isEmpty() && !recursive) {
        // if there are unless this is a recursive operation, fail immediately
        throw new SwiftException("Directory " + path + " is not empty.");
      }
      // delete the children
      for (FileStatus child : children) {
        Path childPath = child.getPath();
        try {
          if (!innerDelete(childPath, true)) {
            if (LOG.isDebugEnabled()) {
              LOG.debug("Failed to  recursively delete '" + childPath + "'");
            }
            return false;
          }
        } catch (FileNotFoundException e) {
          // the path went away -race conditions.
          // do not fail, as the outcome is still OK.
          LOG.info("Path " + childPath + " is no longer present");
        }
      }
      // here any children that existed have been deleted
      // so rm the directory
      store.rmdir(absolutePath);
    }

    return true;
  }