code: public List<URI> listFileNames(FileInfo fileInfo, boolean recursive)
        throws IOException {
  
      Preconditions.checkNotNull(fileInfo);
      URI path = fileInfo.getPath();
      logger.atFine().log("listFileNames(%s)", path);
      List<URI> paths = new ArrayList<>();
      List<String> childNames;
  
      // If it is a directory, obtain info about its children.
      if (fileInfo.isDirectory()) {
        if (fileInfo.exists()) {
          if (fileInfo.isGlobalRoot()) {
            childNames = gcs.listBucketNames();
  
            // Obtain path for each child.
            for (String childName : childNames) {
              URI childPath = pathCodec.getPath(childName, null, true);
              paths.add(childPath);
              logger.atFine().log("listFileNames: added: %s", childPath);
            }
          } else {
            // A null delimiter asks GCS to return all objects with a given prefix,
            // regardless of their 'directory depth' relative to the prefix;
            // that is what we want for a recursive list. On the other hand,
            // when a delimiter is specified, only items with relative depth
            // of 1 are returned.
            String delimiter = recursive ? null : PATH_DELIMITER;
  
            GoogleCloudStorageItemInfo itemInfo = fileInfo.getItemInfo();
            // Obtain paths of children.
            childNames =
                gcs.listObjectNames(itemInfo.getBucketName(), itemInfo.getObjectName(), delimiter);
  
            // Obtain path for each child.
            for (String childName : childNames) {
              URI childPath = pathCodec.getPath(itemInfo.getBucketName(), childName, false);
              paths.add(childPath);
              logger.atFine().log("listFileNames: added: %s", childPath);
            }
          }
        }
      } else {
        paths.add(path);
        logger.atFine().log(
            "listFileNames: added single original path since !isDirectory(): %s", path);
      }
  
      return paths;
    }
docs: If the given item is a directory then the paths of its
  children are returned, otherwise the path of the given item is returned.
  
  @param fileInfo FileInfo of an item.
  @param recursive If true, path of all children are returned;
  else, only immediate children are returned.
  @return Paths of children (if directory) or self path.
  @throws IOException