Archive for the ‘NIO’ Category

Copying symlinks

Posted: April 15, 2013 in NIO, Symlinks

JDK7 offers a whole new set of methods to work with symbolic links. This was in pre-JDK7 times pretty difficult and often you had to execute barebone copy statements through the runtime. There is one method which I missed in the API. You can open or follow the link, or test whether your file is a link, but you cannot “copy” the link itself. You need to resolve the original link and create a new link as illustrated in the class below.

The class could surely be optimized, but it gives you an idea on how the symbolic links function.

public class LinkFileVisitor extends SimpleFileVisitor<Path> {

    private Path fromPath;

    private Path toPath;

    public LinkFileVisitor(final Path fromPath, final Path toPath) {
        this.fromPath = fromPath;
        this.toPath = toPath;
    }

  public static void copy(final Path from, final Path to)
            throws IOException {

        // make sure it is a directory
        if (!Files.isDirectory(from)) {
            throw new IllegalArgumentException(
                    String.format("%s is not a directory", from.toString()));
        }

        Files.walkFileTree(from, new HashSet(),
                Integer.MAX_VALUE, new LinkFileVisitor(from, to));

    }

    @Override
    public FileVisitResult preVisitDirectory(final Path dir,
            final BasicFileAttributes attrs)
            throws IOException {
        Path targetPath = toPath.resolve(fromPath.relativize(dir));
        if (!Files.exists(targetPath)) {
            Files.createDirectory(targetPath);
        }
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
            throws IOException {
         if (Files.isSymbolicLink(file)) {
            Path link = toPath.resolve(fromPath.relativize(file));
            if (Files.exists(link, LinkOption.NOFOLLOW_LINKS)) {
                Files.delete(link);
            }
            Files.createSymbolicLink(link, Files.readSymbolicLink(file));
        } else {
            Files.copy(file, toPath.resolve(fromPath.relativize(file)),
                    StandardCopyOption.REPLACE_EXISTING);
        }
        return FileVisitResult.CONTINUE;
    }
}
Advertisements