de.joinout.criztovyl.tools.directory.DirectorySync.java Source code

Java tutorial

Introduction

Here is the source code for de.joinout.criztovyl.tools.directory.DirectorySync.java

Source

/**
This is a part of my tool collection.
Copyright (C) 2014 Christoph "criztovyl" Schulz
    
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
    
This program 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 for more details.
    
You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package de.joinout.criztovyl.tools.directory;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;

import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import de.joinout.criztovyl.tools.CloneUtils;
import de.joinout.criztovyl.tools.file.Path;

/**
 * Synchronises files of two directories.
 * 
 * @author criztovyl
 * 
 */
public class DirectorySync extends DirectoryChanges {

    private final Logger logger;

    /**
     * Creates a new directory sync. <code>base</code> and <code>branch</code> are set.
     * 
     * @param base
     *            the directory the data is taken from
     * @param branch
     *            the directory the files are stored in
     * @throws IOException If an I/O error occurs
     */
    public DirectorySync(Path base, Path branch) throws IOException {
        this(base, branch, "");
    }

    /**
     * Creates a new directory sync. <code>base</code>, <code>branch</code> and regular expression for ignoring files are set.
     * @param base the base directory
     * @param branch the branch directory
     * @param ignoreRegex the regular expression for ignoring files
     * @throws IOException If an I/O error occurs in {@link DirectoryChanges#DirectoryChanges(Path, Path, String)}
     */
    public DirectorySync(Path base, Path branch, String ignoreRegex) throws IOException {
        super(base, branch, ignoreRegex);

        logger = LogManager.getLogger();

        if (getCurrentList().isEmpty())
            logger.warn(
                    "Base diretory is empty, will delete _complete_ branch directory if you run DiretorySync#removeDeletedFiles(true)!");
    }

    /**
     * Copies the new files from the source to the target.
     */
    public void copyNewFiles() {

        int file = 1;

        // Iterate over new files
        for (final Path path : getNewFiles(false)) {

            // Calculate source directory
            final Path srcD = getCurrentList().getDirectory().append(path).getFile().exists()
                    ? getCurrentList().getDirectory()
                    : getPreviousList().getDirectory();
            final Path targetD = srcD.equals(getCurrentList().getDirectory()) ? getPreviousList().getDirectory()
                    : getCurrentList().getDirectory();
            Path src = srcD.append(path);
            Path target = targetD.append(path);

            try {

                if (logger.isInfoEnabled())
                    logger.info("Copying file {} of {} from {} to {}", file, getNewFiles(false).size(), src,
                            target);

                // Clone if is file 
                if (src.getFile().isFile())
                    CloneUtils.cloneFile(src, target);

                //Create directory if is one.
                if (src.getFile().isDirectory())
                    target.getFile().mkdir();

                if (logger.isInfoEnabled())
                    logger.info("Copied.");

            } catch (final IOException e) {

                if (logger.isWarnEnabled())
                    logger.warn("Caught IOException while copying file {} with source {} and target {}.", path,
                            srcD, targetD);
                if (logger.isDebugEnabled())
                    logger.debug("IOException.", e);
            }

            //Increment file
            file++;
        }
    }

    /**
     * Runs {@link #removeDeletedFiles(boolean)} with boolean false.
     * @see #removeDeletedFiles(boolean)
     */
    public void removeDeletedFiles() {
        removeDeletedFiles(false);
    }

    /**
     * Removes all deleted files.
     * @param force whether files should be deleted if base directory is empty.
     */
    public void removeDeletedFiles(boolean force) {

        if (getCurrentList().isEmpty() && !force) {
            logger.warn("Not removing any files, base diretory is empty.");
            return;
        }

        //Iterate over files
        for (Path path : getDeletedFiles(false)) {

            //Make absolute
            path = getPreviousList().getDirectory().append(path);

            //Check if path needed to delete is a directory
            if (path.getFile().isDirectory())

                try { //Try to delete directory recursively.

                    if (logger.isInfoEnabled())
                        logger.info("Deleting {}", path);

                    FileUtils.deleteDirectory(path.getFile());

                    if (logger.isInfoEnabled())
                        logger.info("Deleted.");
                } catch (IOException e) { //Catch general IOException.

                    if (logger.isWarnEnabled())
                        logger.warn("There was an IOException while deleting the disappeared directory {}: {}",
                                path, e.toString());

                    if (logger.isDebugEnabled())
                        logger.debug("IOException.", e);
                }
            else
                try { //Try to delete file, using NIO to get an exception whether something went wrong.

                    if (logger.isInfoEnabled())
                        logger.info("Deleting {}", path);

                    Files.delete(path.getNIOPath());

                    if (logger.isInfoEnabled())
                        logger.info("Deleted.");
                } catch (NoSuchFileException e) { //Catch NoSuchFileException (NIO FileNotFoundException), file may has been deleted by an earlier
                    if (logger.isDebugEnabled())
                        logger.debug("File {} not found, may be already deleted?", path);
                } catch (IOException e) {

                    if (logger.isWarnEnabled())
                        logger.warn("There was an IOException while deleting the disappeared directory {}: {}",
                                path, e.toString());

                    if (logger.isDebugEnabled())
                        logger.debug("IOException.", e);
                }
        }

    }

    /**
     * Copies new files, updates changed files and remove deleted files.
     * @see #copyNewFiles()
     * @see #updateChangedFiles()
     * @see #removeDeletedFiles()
     */
    public void sync() {

        if (logger.isInfoEnabled())
            logger.info("Copying {} new files...", getNewFiles(false).size());

        copyNewFiles();

        if (logger.isInfoEnabled())
            logger.info("Update {} changed files...", getChangedFiles(false).size());

        updateChangedFiles();

        if (logger.isInfoEnabled())
            logger.info("Remove {} deleted files...", getDeletedFiles(false).size());

        removeDeletedFiles();
    }

    /**
     * Updates the changed files.
     */
    public void updateChangedFiles() {

        int file = 1;

        // Iterate of changed files
        for (final Path path : getChangedFiles(false))
            try {

                if (logger.isInfoEnabled())
                    logger.info("Copying file {} of {} from {} to {}", file, getChangedFiles(false), path,
                            getComplementPath(path));

                // Clone file
                CloneUtils.cloneFile(path, getComplementPath(path));

                if (logger.isInfoEnabled())
                    logger.info("Copied.");

            } catch (final IOException e) {

                if (logger.isWarnEnabled())
                    logger.warn("Caught IOException while copying file {}: {}", path, e.toString());
                if (logger.isDebugEnabled())
                    logger.debug("IOException.", e);
            }
    }

}