All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.carlspring.commons.io.RecursiveMover Maven / Gradle / Ivy

package org.carlspring.commons.io;

import java.io.IOException;
import java.nio.file.CopyOption;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.FileSystemLoopException;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Arrays;
import java.util.EnumSet;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static java.nio.file.FileVisitResult.CONTINUE;
import static java.nio.file.FileVisitResult.SKIP_SIBLINGS;
import static java.nio.file.StandardCopyOption.COPY_ATTRIBUTES;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;

/**
 * @author mtodorov
 */
public class RecursiveMover
        implements FileVisitor
{

    private static final Logger logger = LoggerFactory.getLogger(RecursiveMover.class);

    private final Path source;

    private final Path target;


    public RecursiveMover(Path source,
                          Path target)
    {
        this.source = source;
        this.target = target;
    }

    public FileVisitResult preVisitDirectory(Path sourcePath,
                                             BasicFileAttributes attrs)
            throws IOException
    {
        Path relativePath = relativizeTargetPath(sourcePath);
        Path targetPath = target.resolve(relativePath);

        if (Files.exists(sourcePath) && Files.exists(targetPath))
        {
            // 1) If its a file, delete it
            if (Files.isRegularFile(sourcePath))
            {
                Files.deleteIfExists(sourcePath);
            }
            // 2) If its a directory, iterate and check
            else
            {
                // Carry out a directory move
                String[] paths = sourcePath.toFile().list();
                if (paths != null)
                {
                    Arrays.sort(paths);

                    for (String path : paths)
                    {
                        Path srcPath = sourcePath.resolve(path);
                        Path destPath = targetPath.resolve(path);

                        if (Files.isDirectory(srcPath))
                        {
                            if (Files.notExists(targetPath))
                            {
                                // Make sure we've created the destination directory:

                                move(sourcePath, targetPath, true);
                            }
                            else
                            {
                                EnumSet opts = EnumSet.of(FileVisitOption.FOLLOW_LINKS);
                                RecursiveMover recursiveMover = new RecursiveMover(srcPath, destPath.getParent());
                                Files.walkFileTree(srcPath, opts, Integer.MAX_VALUE, recursiveMover);
                            }
                        }
                        else
                        {
                            Files.move(srcPath, destPath, REPLACE_EXISTING);
                        }
                    }

                    if (paths.length == 0)
                    {
                        // Make sure the source directory has been removed, if its empty.
                        // This is for cases where the destination contains the directory or part of the resources.
                        Files.deleteIfExists(sourcePath);
                    }
                }

                return SKIP_SIBLINGS;
            }
        }

        return CONTINUE;
    }

    private Path relativizeTargetPath(Path dir)
    {
        return Paths.get(source.toFile().getName() + "/" + source.relativize(dir.toAbsolutePath()));
    }

    public FileVisitResult visitFile(Path sourcePath,
                                     BasicFileAttributes attrs)
    {
        Path relativePath = relativizeTargetPath(sourcePath);
        Path targetPath = target.resolve(relativePath);

        if (Files.notExists(targetPath.getParent()))
        {
            move(sourcePath.getParent(), targetPath.getParent(), false);

            return SKIP_SIBLINGS;
        }
        else
        {
            move(sourcePath, targetPath, false);

            return CONTINUE;
        }
    }

    public FileVisitResult postVisitDirectory(Path dir,
                                              IOException exc)
    {
        return CONTINUE;
    }

    public FileVisitResult visitFileFailed(Path file,
                                           IOException e)
    {
        if (e instanceof FileSystemLoopException)
        {
            logger.error("Cycle detected: {}", file);
        }
        else
        {
            logger.error("Unable to move: {}", file, e);
        }

        return CONTINUE;
    }

    public void move(Path source,
                     Path target,
                     boolean preserve)
    {
        CopyOption[] options = (preserve) ?
                               new CopyOption[]{ COPY_ATTRIBUTES,
                                                 REPLACE_EXISTING } :
                               new CopyOption[]{ REPLACE_EXISTING };

        try
        {
            Files.move(source, target, options);
        }
        catch (FileAlreadyExistsException e)
        {
            // Ignore
            logger.error("File already exists", e);
        }
        catch (IOException e)
        {
            logger.error("ERROR: Unable to move {} to {}!",
                         source.toAbsolutePath(),
                         target.toAbsolutePath(), e);
        }
    }

}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy