/**
   * Takes a collection of StorageFiles and performs the replace functionality described in {@link
   * #replaceOriginal()}. However, all files that are part of the same {@link ShpFiles} are done
   * within a lock so all of the updates for all the Files of a Shapefile can be updated within a
   * single lock.
   *
   * @param storageFiles files to execute the replace functionality.
   * @throws IOException
   */
  static void replaceOriginals(final StorageFile... storageFiles) throws IOException {
    SortedSet<StorageFile> files = new TreeSet<StorageFile>(Arrays.asList(storageFiles));

    ShpFiles currentShpFiles = null;
    for (StorageFile storageFile : files) {
      if (currentShpFiles != storageFile.shpFiles) {
        // there's a new set of files so unlock old and lock new.
        currentShpFiles = storageFile.shpFiles;
      }

      final File storage = storageFile.getFile();

      final URL url = storageFile.getSrcURLForWrite();
      try {
        File dest = toFile(url);

        if (storage.equals(dest)) return;

        if (dest.exists()) {
          if (!dest.delete()) {
            LOGGER.severe(
                "Unable to delete the file: "
                    + dest
                    + " when attempting to replace with temporary copy.");
          }
        }

        if (storage.exists() && !storage.renameTo(dest)) {
          LOGGER.finer(
              "Unable to rename temporary file to the file: "
                  + dest
                  + " when attempting to replace with temporary copy");

          copyFile(storage, url, dest);
          if (!storage.delete()) {
            storage.deleteOnExit();
          }
        }
      } finally {
        if (storage.exists()) {
          storage.delete();
        }
      }
    }
  }