--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/nio/file/CopyMoveHelper.java Fri Jan 28 09:28:43 2011 +0000
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+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() { }
+
+ /**
+ * Parses the arguments for a file copy operation.
+ */
+ 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;
+ }
+ }
+
+ /**
+ * Converts the given array of options for moving a file to options suitable
+ * for copying the file when a move is implemented as copy + delete.
+ */
+ 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;
+ }
+
+ /**
+ * Simple copy for use when source and target are associated with different
+ * providers
+ */
+ 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 };
+
+ // attributes of source file
+ BasicFileAttributes attrs = Files.readAttributes(source,
+ BasicFileAttributes.class,
+ linkOptions);
+ if (attrs.isSymbolicLink())
+ throw new IOException("Copying of symbolic links not supported");
+
+ // delete target if it exists and REPLACE_EXISTING is specified
+ if (opts.replaceExisting) {
+ Files.deleteIfExists(target);
+ } else if (Files.exists(target))
+ throw new FileAlreadyExistsException(target.toString());
+
+ // create directory or copy file
+ if (attrs.isDirectory()) {
+ Files.createDirectory(target);
+ } else {
+ try (InputStream in = Files.newInputStream(source)) {
+ Files.copy(in, target);
+ }
+ }
+
+ // copy basic attributes to target
+ if (opts.copyAttributes) {
+ BasicFileAttributeView view =
+ Files.getFileAttributeView(target, BasicFileAttributeView.class, linkOptions);
+ try {
+ view.setTimes(attrs.lastModifiedTime(),
+ attrs.lastAccessTime(),
+ attrs.creationTime());
+ } catch (IOException x) {
+ // rollback
+ try {
+ Files.delete(target);
+ } catch (IOException ignore) { }
+ throw x;
+ }
+ }
+ }
+
+ /**
+ * Simple move implements as copy+delete for use when source and target are
+ * associated with different providers
+ */
+ static void moveToForeignTarget(Path source, Path target,
+ CopyOption... options) throws IOException
+ {
+ copyToForeignTarget(source, target, convertMoveToCopyOptions(options));
+ Files.delete(source);
+ }
+}