protected static void safeMoveOrCopy()

in taverna-robundle/src/main/java/org/apache/taverna/robundle/Bundles.java [246:312]


	protected static void safeMoveOrCopy(Path source, Path destination,
			boolean move) throws IOException {
		// First just try to do an atomic move with overwrite
		try {
			if (move
					&& source.getFileSystem().provider()
							.equals(destination.getFileSystem().provider())) {
				move(source, destination, ATOMIC_MOVE, REPLACE_EXISTING);
				return;
			}
		} catch (AtomicMoveNotSupportedException ex) {
			// Do the fallback by temporary files below
		}

		destination = destination.toAbsolutePath();

		String tmpName = destination.getFileName().toString();
		Path tmpDestination = createTempFile(destination.getParent(), tmpName,
				".tmp");
		Path backup = null;
		try {
			if (move) {
				/*
				 * This might do a copy if filestores differ .. hence to avoid
				 * an incomplete (and partially overwritten) destination, we do
				 * it first to a temporary file
				 */
				move(source, tmpDestination, REPLACE_EXISTING);
			} else {
				copy(source, tmpDestination, REPLACE_EXISTING);
			}

			if (exists(destination)) {
				if (isDirectory(destination))
					// ensure it is empty
					try (DirectoryStream<Path> ds = newDirectoryStream(destination)) {
						if (ds.iterator().hasNext())
							throw new DirectoryNotEmptyException(
									destination.toString());
					}
				// Keep the files for roll-back in case it goes bad
				backup = createTempFile(destination.getParent(), tmpName,
						".orig");
				move(destination, backup, REPLACE_EXISTING);
			}
			// OK ; let's swap over
			try {
				// prefer ATOMIC_MOVE
				move(tmpDestination, destination, REPLACE_EXISTING, ATOMIC_MOVE);
			} catch (AtomicMoveNotSupportedException ex) {
				/*
				 * possibly a network file system as src/dest should be in same
				 * folder
				 */
				move(tmpDestination, destination, REPLACE_EXISTING);
			} finally {
				if (!exists(destination) && backup != null)
					// Restore the backup
					move(backup, destination);
			}
			// It went well, tidy up
			if (backup != null)
				deleteIfExists(backup);
		} finally {
			deleteIfExists(tmpDestination);
		}
	}