|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package java.nio.file; |
|
|
|
import java.nio.file.attribute.*; |
|
import java.io.InputStream; |
|
import java.io.IOException; |
|
|
|
/** |
|
* Helper class to support copying or moving files when the source and target |
|
* are associated with different providers. |
|
*/ |
|
|
|
class CopyMoveHelper { |
|
private CopyMoveHelper() { } |
|
|
|
|
|
|
|
*/ |
|
private static class CopyOptions { |
|
boolean replaceExisting = false; |
|
boolean copyAttributes = false; |
|
boolean followLinks = true; |
|
|
|
private CopyOptions() { } |
|
|
|
static CopyOptions parse(CopyOption... options) { |
|
CopyOptions result = new CopyOptions(); |
|
for (CopyOption option: options) { |
|
if (option == StandardCopyOption.REPLACE_EXISTING) { |
|
result.replaceExisting = true; |
|
continue; |
|
} |
|
if (option == LinkOption.NOFOLLOW_LINKS) { |
|
result.followLinks = false; |
|
continue; |
|
} |
|
if (option == StandardCopyOption.COPY_ATTRIBUTES) { |
|
result.copyAttributes = true; |
|
continue; |
|
} |
|
if (option == null) |
|
throw new NullPointerException(); |
|
throw new UnsupportedOperationException("'" + option + |
|
"' is not a recognized copy option"); |
|
} |
|
return result; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
private static CopyOption[] convertMoveToCopyOptions(CopyOption... options) |
|
throws AtomicMoveNotSupportedException |
|
{ |
|
int len = options.length; |
|
CopyOption[] newOptions = new CopyOption[len+2]; |
|
for (int i=0; i<len; i++) { |
|
CopyOption option = options[i]; |
|
if (option == StandardCopyOption.ATOMIC_MOVE) { |
|
throw new AtomicMoveNotSupportedException(null, null, |
|
"Atomic move between providers is not supported"); |
|
} |
|
newOptions[i] = option; |
|
} |
|
newOptions[len] = LinkOption.NOFOLLOW_LINKS; |
|
newOptions[len+1] = StandardCopyOption.COPY_ATTRIBUTES; |
|
return newOptions; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
static void copyToForeignTarget(Path source, Path target, |
|
CopyOption... options) |
|
throws IOException |
|
{ |
|
CopyOptions opts = CopyOptions.parse(options); |
|
LinkOption[] linkOptions = (opts.followLinks) ? new LinkOption[0] : |
|
new LinkOption[] { LinkOption.NOFOLLOW_LINKS }; |
|
|
|
|
|
BasicFileAttributes attrs = Files.readAttributes(source, |
|
BasicFileAttributes.class, |
|
linkOptions); |
|
if (attrs.isSymbolicLink()) |
|
throw new IOException("Copying of symbolic links not supported"); |
|
|
|
|
|
if (opts.replaceExisting) { |
|
Files.deleteIfExists(target); |
|
} else if (Files.exists(target)) |
|
throw new FileAlreadyExistsException(target.toString()); |
|
|
|
|
|
if (attrs.isDirectory()) { |
|
Files.createDirectory(target); |
|
} else { |
|
try (InputStream in = Files.newInputStream(source)) { |
|
Files.copy(in, target); |
|
} |
|
} |
|
|
|
|
|
if (opts.copyAttributes) { |
|
BasicFileAttributeView view = |
|
Files.getFileAttributeView(target, BasicFileAttributeView.class); |
|
try { |
|
view.setTimes(attrs.lastModifiedTime(), |
|
attrs.lastAccessTime(), |
|
attrs.creationTime()); |
|
} catch (Throwable x) { |
|
|
|
try { |
|
Files.delete(target); |
|
} catch (Throwable suppressed) { |
|
x.addSuppressed(suppressed); |
|
} |
|
throw x; |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
static void moveToForeignTarget(Path source, Path target, |
|
CopyOption... options) throws IOException |
|
{ |
|
copyToForeignTarget(source, target, convertMoveToCopyOptions(options)); |
|
Files.delete(source); |
|
} |
|
} |