alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (UnixCopyFile.java)

This example Java source code file (UnixCopyFile.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

cancellable, copyoption, directorynotemptyexception, eexist, enotempty, flags, ioexception, o_rdonly, override, security, securitymanager, threading, threads, unixcopyfile, unixexception, unixfileattributes, unixpath

The UnixCopyFile.java Java example source code

/*
 * Copyright (c) 2008, 2013, 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 sun.nio.fs;

import java.nio.file.*;
import java.io.IOException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import com.sun.nio.file.ExtendedCopyOption;

import static sun.nio.fs.UnixNativeDispatcher.*;
import static sun.nio.fs.UnixConstants.*;


/**
 * Unix implementation of Path#copyTo and Path#moveTo methods.
 */

class UnixCopyFile {
    private UnixCopyFile() {  }

    // The flags that control how a file is copied or moved
    private static class Flags {
        boolean replaceExisting;
        boolean atomicMove;
        boolean followLinks;
        boolean interruptible;

        // the attributes to copy
        boolean copyBasicAttributes;
        boolean copyPosixAttributes;
        boolean copyNonPosixAttributes;

        // flags that indicate if we should fail if attributes cannot be copied
        boolean failIfUnableToCopyBasic;
        boolean failIfUnableToCopyPosix;
        boolean failIfUnableToCopyNonPosix;

        static Flags fromCopyOptions(CopyOption... options) {
            Flags flags = new Flags();
            flags.followLinks = true;
            for (CopyOption option: options) {
                if (option == StandardCopyOption.REPLACE_EXISTING) {
                    flags.replaceExisting = true;
                    continue;
                }
                if (option == LinkOption.NOFOLLOW_LINKS) {
                    flags.followLinks = false;
                    continue;
                }
                if (option == StandardCopyOption.COPY_ATTRIBUTES) {
                    // copy all attributes but only fail if basic attributes
                    // cannot be copied
                    flags.copyBasicAttributes = true;
                    flags.copyPosixAttributes = true;
                    flags.copyNonPosixAttributes = true;
                    flags.failIfUnableToCopyBasic = true;
                    continue;
                }
                if (option == ExtendedCopyOption.INTERRUPTIBLE) {
                    flags.interruptible = true;
                    continue;
                }
                if (option == null)
                    throw new NullPointerException();
                throw new UnsupportedOperationException("Unsupported copy option");
            }
            return flags;
        }

        static Flags fromMoveOptions(CopyOption... options) {
            Flags flags = new Flags();
            for (CopyOption option: options) {
                if (option == StandardCopyOption.ATOMIC_MOVE) {
                    flags.atomicMove = true;
                    continue;
                }
                if (option == StandardCopyOption.REPLACE_EXISTING) {
                    flags.replaceExisting = true;
                    continue;
                }
                if (option == LinkOption.NOFOLLOW_LINKS) {
                    // ignore
                    continue;
                }
                if (option == null)
                    throw new NullPointerException();
                throw new UnsupportedOperationException("Unsupported copy option");
            }

            // a move requires that all attributes be copied but only fail if
            // the basic attributes cannot be copied
            flags.copyBasicAttributes = true;
            flags.copyPosixAttributes = true;
            flags.copyNonPosixAttributes = true;
            flags.failIfUnableToCopyBasic = true;
            return flags;
        }
    }

    // copy directory from source to target
    private static void copyDirectory(UnixPath source,
                                      UnixFileAttributes attrs,
                                      UnixPath target,
                                      Flags flags)
        throws IOException
    {
        try {
            mkdir(target, attrs.mode());
        } catch (UnixException x) {
            x.rethrowAsIOException(target);
        }

        // no attributes to copy
        if (!flags.copyBasicAttributes &&
            !flags.copyPosixAttributes &&
            !flags.copyNonPosixAttributes) return;

        // open target directory if possible (this can fail when copying a
        // directory for which we don't have read access).
        int dfd = -1;
        try {
            dfd = open(target, O_RDONLY, 0);
        } catch (UnixException x) {
            // access to target directory required to copy named attributes
            if (flags.copyNonPosixAttributes && flags.failIfUnableToCopyNonPosix) {
                try { rmdir(target); } catch (UnixException ignore) { }
                x.rethrowAsIOException(target);
            }
        }

        boolean done = false;
        try {
            // copy owner/group/permissions
            if (flags.copyPosixAttributes){
                try {
                    if (dfd >= 0) {
                        fchown(dfd, attrs.uid(), attrs.gid());
                        fchmod(dfd, attrs.mode());
                    } else {
                        chown(target, attrs.uid(), attrs.gid());
                        chmod(target, attrs.mode());
                    }
                } catch (UnixException x) {
                    // unable to set owner/group
                    if (flags.failIfUnableToCopyPosix)
                        x.rethrowAsIOException(target);
                }
            }
            // copy other attributes
            if (flags.copyNonPosixAttributes && (dfd >= 0)) {
                int sfd = -1;
                try {
                    sfd = open(source, O_RDONLY, 0);
                } catch (UnixException x) {
                    if (flags.failIfUnableToCopyNonPosix)
                        x.rethrowAsIOException(source);
                }
                if (sfd >= 0) {
                    source.getFileSystem().copyNonPosixAttributes(sfd, dfd);
                    close(sfd);
                }
            }
            // copy time stamps last
            if (flags.copyBasicAttributes) {
                try {
                    if (dfd >= 0 && futimesSupported()) {
                        futimes(dfd,
                                attrs.lastAccessTime().to(TimeUnit.MICROSECONDS),
                                attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS));
                    } else {
                        utimes(target,
                               attrs.lastAccessTime().to(TimeUnit.MICROSECONDS),
                               attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS));
                    }
                } catch (UnixException x) {
                    // unable to set times
                    if (flags.failIfUnableToCopyBasic)
                        x.rethrowAsIOException(target);
                }
            }
            done = true;
        } finally {
            if (dfd >= 0)
                close(dfd);
            if (!done) {
                // rollback
                try { rmdir(target); } catch (UnixException ignore) { }
            }
        }
    }

    // copy regular file from source to target
    private static void copyFile(UnixPath source,
                                 UnixFileAttributes attrs,
                                 UnixPath  target,
                                 Flags flags,
                                 long addressToPollForCancel)
        throws IOException
    {
        int fi = -1;
        try {
            fi = open(source, O_RDONLY, 0);
        } catch (UnixException x) {
            x.rethrowAsIOException(source);
        }

        try {
            // open new file
            int fo = -1;
            try {
                fo = open(target,
                           (O_WRONLY |
                            O_CREAT |
                            O_EXCL),
                           attrs.mode());
            } catch (UnixException x) {
                x.rethrowAsIOException(target);
            }

            // set to true when file and attributes copied
            boolean complete = false;
            try {
                // transfer bytes to target file
                try {
                    transfer(fo, fi, addressToPollForCancel);
                } catch (UnixException x) {
                    x.rethrowAsIOException(source, target);
                }
                // copy owner/permissions
                if (flags.copyPosixAttributes) {
                    try {
                        fchown(fo, attrs.uid(), attrs.gid());
                        fchmod(fo, attrs.mode());
                    } catch (UnixException x) {
                        if (flags.failIfUnableToCopyPosix)
                            x.rethrowAsIOException(target);
                    }
                }
                // copy non POSIX attributes (depends on file system)
                if (flags.copyNonPosixAttributes) {
                    source.getFileSystem().copyNonPosixAttributes(fi, fo);
                }
                // copy time attributes
                if (flags.copyBasicAttributes) {
                    try {
                        if (futimesSupported()) {
                            futimes(fo,
                                    attrs.lastAccessTime().to(TimeUnit.MICROSECONDS),
                                    attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS));
                        } else {
                            utimes(target,
                                   attrs.lastAccessTime().to(TimeUnit.MICROSECONDS),
                                   attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS));
                        }
                    } catch (UnixException x) {
                        if (flags.failIfUnableToCopyBasic)
                            x.rethrowAsIOException(target);
                    }
                }
                complete = true;
            } finally {
                close(fo);

                // copy of file or attributes failed so rollback
                if (!complete) {
                    try {
                        unlink(target);
                    } catch (UnixException ignore) { }
                }
            }
        } finally {
            close(fi);
        }
    }

    // copy symbolic link from source to target
    private static void copyLink(UnixPath source,
                                 UnixFileAttributes attrs,
                                 UnixPath  target,
                                 Flags flags)
        throws IOException
    {
        byte[] linktarget = null;
        try {
            linktarget = readlink(source);
        } catch (UnixException x) {
            x.rethrowAsIOException(source);
        }
        try {
            symlink(linktarget, target);

            if (flags.copyPosixAttributes) {
                try {
                    lchown(target, attrs.uid(), attrs.gid());
                } catch (UnixException x) {
                    // ignore since link attributes not required to be copied
                }
            }
        } catch (UnixException x) {
            x.rethrowAsIOException(target);
        }
    }

    // copy special file from source to target
    private static void copySpecial(UnixPath source,
                                    UnixFileAttributes attrs,
                                    UnixPath  target,
                                    Flags flags)
        throws IOException
    {
        try {
            mknod(target, attrs.mode(), attrs.rdev());
        } catch (UnixException x) {
            x.rethrowAsIOException(target);
        }
        boolean done = false;
        try {
            if (flags.copyPosixAttributes) {
                try {
                    chown(target, attrs.uid(), attrs.gid());
                    chmod(target, attrs.mode());
                } catch (UnixException x) {
                    if (flags.failIfUnableToCopyPosix)
                        x.rethrowAsIOException(target);
                }
            }
            if (flags.copyBasicAttributes) {
                try {
                    utimes(target,
                           attrs.lastAccessTime().to(TimeUnit.MICROSECONDS),
                           attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS));
                } catch (UnixException x) {
                    if (flags.failIfUnableToCopyBasic)
                        x.rethrowAsIOException(target);
                }
            }
            done = true;
        } finally {
            if (!done) {
                try { unlink(target); } catch (UnixException ignore) { }
            }
        }
    }

    // move file from source to target
    static void move(UnixPath source, UnixPath target, CopyOption... options)
        throws IOException
    {
        // permission check
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            source.checkWrite();
            target.checkWrite();
        }

        // translate options into flags
        Flags flags = Flags.fromMoveOptions(options);

        // handle atomic rename case
        if (flags.atomicMove) {
            try {
                rename(source, target);
            } catch (UnixException x) {
                if (x.errno() == EXDEV) {
                    throw new AtomicMoveNotSupportedException(
                        source.getPathForExceptionMessage(),
                        target.getPathForExceptionMessage(),
                        x.errorString());
                }
                x.rethrowAsIOException(source, target);
            }
            return;
        }

        // move using rename or copy+delete
        UnixFileAttributes sourceAttrs = null;
        UnixFileAttributes targetAttrs = null;

        // get attributes of source file (don't follow links)
        try {
            sourceAttrs = UnixFileAttributes.get(source, false);
        } catch (UnixException x) {
            x.rethrowAsIOException(source);
        }

        // get attributes of target file (don't follow links)
        try {
            targetAttrs = UnixFileAttributes.get(target, false);
        } catch (UnixException x) {
            // ignore
        }
        boolean targetExists = (targetAttrs != null);

        // if the target exists:
        // 1. check if source and target are the same file
        // 2. throw exception if REPLACE_EXISTING option is not set
        // 3. delete target if REPLACE_EXISTING option set
        if (targetExists) {
            if (sourceAttrs.isSameFile(targetAttrs))
                return;  // nothing to do as files are identical
            if (!flags.replaceExisting) {
                throw new FileAlreadyExistsException(
                    target.getPathForExceptionMessage());
            }

            // attempt to delete target
            try {
                if (targetAttrs.isDirectory()) {
                    rmdir(target);
                } else {
                    unlink(target);
                }
            } catch (UnixException x) {
                // target is non-empty directory that can't be replaced.
                if (targetAttrs.isDirectory() &&
                   (x.errno() == EEXIST || x.errno() == ENOTEMPTY))
                {
                    throw new DirectoryNotEmptyException(
                        target.getPathForExceptionMessage());
                }
                x.rethrowAsIOException(target);
            }
        }

        // first try rename
        try {
            rename(source, target);
            return;
        } catch (UnixException x) {
            if (x.errno() != EXDEV && x.errno() != EISDIR) {
                x.rethrowAsIOException(source, target);
            }
        }

        // copy source to target
        if (sourceAttrs.isDirectory()) {
            copyDirectory(source, sourceAttrs, target, flags);
        } else {
            if (sourceAttrs.isSymbolicLink()) {
                copyLink(source, sourceAttrs, target, flags);
            } else {
                if (sourceAttrs.isDevice()) {
                    copySpecial(source, sourceAttrs, target, flags);
                } else {
                    copyFile(source, sourceAttrs, target, flags, 0L);
                }
            }
        }

        // delete source
        try {
            if (sourceAttrs.isDirectory()) {
                rmdir(source);
            } else {
                unlink(source);
            }
        } catch (UnixException x) {
            // file was copied but unable to unlink the source file so attempt
            // to remove the target and throw a reasonable exception
            try {
                if (sourceAttrs.isDirectory()) {
                    rmdir(target);
                } else {
                    unlink(target);
                }
            } catch (UnixException ignore) { }

            if (sourceAttrs.isDirectory() &&
                (x.errno() == EEXIST || x.errno() == ENOTEMPTY))
            {
                throw new DirectoryNotEmptyException(
                    source.getPathForExceptionMessage());
            }
            x.rethrowAsIOException(source);
        }
    }

    // copy file from source to target
    static void copy(final UnixPath source,
                     final UnixPath target,
                     CopyOption... options) throws IOException
    {
        // permission checks
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            source.checkRead();
            target.checkWrite();
        }

        // translate options into flags
        final Flags flags = Flags.fromCopyOptions(options);

        UnixFileAttributes sourceAttrs = null;
        UnixFileAttributes targetAttrs = null;

        // get attributes of source file
        try {
            sourceAttrs = UnixFileAttributes.get(source, flags.followLinks);
        } catch (UnixException x) {
            x.rethrowAsIOException(source);
        }

        // if source file is symbolic link then we must check LinkPermission
        if (sm != null && sourceAttrs.isSymbolicLink()) {
            sm.checkPermission(new LinkPermission("symbolic"));
        }

        // get attributes of target file (don't follow links)
        try {
            targetAttrs = UnixFileAttributes.get(target, false);
        } catch (UnixException x) {
            // ignore
        }
        boolean targetExists = (targetAttrs != null);

        // if the target exists:
        // 1. check if source and target are the same file
        // 2. throw exception if REPLACE_EXISTING option is not set
        // 3. try to unlink the target
        if (targetExists) {
            if (sourceAttrs.isSameFile(targetAttrs))
                return;  // nothing to do as files are identical
            if (!flags.replaceExisting)
                throw new FileAlreadyExistsException(
                    target.getPathForExceptionMessage());
            try {
                if (targetAttrs.isDirectory()) {
                    rmdir(target);
                } else {
                    unlink(target);
                }
            } catch (UnixException x) {
                // target is non-empty directory that can't be replaced.
                if (targetAttrs.isDirectory() &&
                   (x.errno() == EEXIST || x.errno() == ENOTEMPTY))
                {
                    throw new DirectoryNotEmptyException(
                        target.getPathForExceptionMessage());
                }
                x.rethrowAsIOException(target);
            }
        }

        // do the copy
        if (sourceAttrs.isDirectory()) {
            copyDirectory(source, sourceAttrs, target, flags);
            return;
        }
        if (sourceAttrs.isSymbolicLink()) {
            copyLink(source, sourceAttrs, target, flags);
            return;
        }
        if (!flags.interruptible) {
            // non-interruptible file copy
            copyFile(source, sourceAttrs, target, flags, 0L);
            return;
        }

        // interruptible file copy
        final UnixFileAttributes attrsToCopy = sourceAttrs;
        Cancellable copyTask = new Cancellable() {
            @Override public void implRun() throws IOException {
                copyFile(source, attrsToCopy, target, flags,
                    addressToPollForCancel());
            }
        };
        try {
            Cancellable.runInterruptibly(copyTask);
        } catch (ExecutionException e) {
            Throwable t = e.getCause();
            if (t instanceof IOException)
                throw (IOException)t;
            throw new IOException(t);
        }
    }

    // -- native methods --

    static native void transfer(int dst, int src, long addressToPollForCancel)
        throws UnixException;

    static {
        AccessController.doPrivileged(new PrivilegedAction<Void>() {
            @Override
            public Void run() {
                System.loadLibrary("nio");
                return null;
            }});
    }

}

Other Java examples (source code examples)

Here is a short list of links related to this Java UnixCopyFile.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.