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);
}
}