com.itmanwuiso.checksums.FileDuplicateChecker.java Source code

Java tutorial

Introduction

Here is the source code for com.itmanwuiso.checksums.FileDuplicateChecker.java

Source

/*
  Copyright 2014 Wassim Akachi - itmanwuiso.com
    
   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at
    
   http://www.apache.org/licenses/LICENSE-2.0
    
   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
    
 */
package com.itmanwuiso.checksums;

import java.io.File;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;
import java.util.concurrent.TimeUnit;

import org.apache.commons.cli.BasicParser;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.MissingArgumentException;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.itmanwuiso.checksums.dao.ResultJSONWriter;
import com.itmanwuiso.checksums.dao.ResultWriter;
import com.itmanwuiso.checksums.dao.SaveResultDAO;
import com.itmanwuiso.checksums.dao.SaveResultDAOFile;
import com.itmanwuiso.checksums.workers.ChecksumWorkerPool;
import com.itmanwuiso.checksums.workers.ChecksumWorkerPoolImpl;

public class FileDuplicateChecker {
    private static Logger logger = LoggerFactory.getLogger(FileDuplicateChecker.class);
    private static ChecksumWorkerPool checksumPool;
    private static SaveResultDAO storage;
    private static String rootPath;
    private static String storageFile;
    private static Stack<File> folderStack;
    private static Object sync;
    private static long tasks;
    private static boolean recursive;
    private static List<ResultWriter> writers;
    private static String[] hashers;
    private static CommandLineParser parser = new BasicParser();
    private static HelpFormatter lvFormater = new HelpFormatter();
    private static CommandLine cmd = null;
    public static boolean quite;

    public static void main(String[] args) {

        sync = new Object();
        tasks = 0L;

        if (!setSettings(args)) {
            System.exit(-1);
        }

        int cores = Runtime.getRuntime().availableProcessors();
        cores = cores + 1;

        prepare(cores, storageFile);

        run();
    }

    private static void prepare(int cores, String storageFile) {
        checksumPool = new ChecksumWorkerPoolImpl(cores * 2 + 5);
        storage = new SaveResultDAOFile(writers);
        folderStack = recursive ? new Stack<File>() : null;
        writers = new LinkedList<ResultWriter>();
        // System.out = new QuitePrinter(System.out);
    }

    private static void createTaske(File file) {
        try {
            if (file.isFile()) {
                HashTask task = new HashTask(file, hashers, storage);
                FileDuplicateChecker.increment();
                checksumPool.execute(task);
            }
        } catch (Exception e) {
            logger.error(file.toString(), e);
        }
    }

    private static void run() {

        if (null != folderStack)
            createTaskes(rootPath, folderStack);
        else
            createTaskes(rootPath);

        checksumPool.shutdown();
        try {
            while (!checksumPool.awaitTermination(2, TimeUnit.SECONDS))
                ;
        } catch (InterruptedException e) {
            logger.error(null, e);
        }

        storage.writeAndClose();
    }

    private static void createTaskes(String pathname, Stack<File> fStack) {
        if (null == fStack) {
            fStack = new Stack<File>();
        }

        File f = new File(pathname);
        fStack.push(f);

        while (!fStack.isEmpty()) {

            File currentFile = fStack.pop();
            File[] listOfFiles = null;

            // if is the current file a dir
            if (currentFile.isDirectory()) {
                listOfFiles = currentFile.listFiles();
            } else if (currentFile.isFile()) {
                createTaske(currentFile);
                continue;
            }

            // if the currentFile isn't a dir
            // or if the dir is empty
            if (listOfFiles == null || listOfFiles.length == 0) {
                continue;
            }

            for (int i = 0; i < listOfFiles.length; i++) {
                File cFile = listOfFiles[i];

                if (cFile.isFile()) {
                    createTaske(cFile);
                } else if (recursive && cFile.isDirectory()) {
                    fStack.push(cFile);
                }
            }
        }
    }

    public static void increment() {
        long tmp;
        synchronized (sync) {
            tmp = ++tasks;
        }
        logger.info(String.format("Tasks \t %20d", tmp));
    }

    public static void decrement() {
        long tmp;
        synchronized (sync) {
            tmp = --tasks;
        }
        logger.info(String.format("Tasks \t %20d", tmp));
    }

    private static void createTaskes(String pathname) {

        File f = new File(pathname);

        if (f.isFile()) {
            createTaske(f);
        } else if (f.isDirectory()) {

            File[] listfiles = f.listFiles();
            for (int i = 0; i < listfiles.length; i++) {
                if (recursive && listfiles[i].isDirectory()) {
                    createTaskes(listfiles[i].getAbsolutePath());
                } else {
                    createTaske(listfiles[i]);
                }
            }
        }

    }

    private static Options options() {
        Options options = new Options();
        options.addOption("h", "help", true, "print this Help.");
        options.addOption("fj", "fjson", true, "Save the result in JSON Format");
        options.addOption("fx", "fxml", true, "Save the result in XML Format");
        options.addOption("p", "path", true, "Path of the File or a Folder");
        options.addOption("r", "recursive", false, "Create Hashes for all files in Folder recursively");
        // Hashes
        options.addOption("md5", "MD5", false, "Create a MD5 Hash");
        options.addOption("sha1", "SHA1", false, "Create a SHA-1 Hash");
        options.addOption("sha256", "SHA256", false, "Create a SHA-256 Hash");
        options.addOption("sha512", "SHA512", false, "Create a SHA-512 Hash");
        options.addOption("as", "all-hashes", false, "Create all Hashes");
        // options.addOption("v", "--verbose", false, "Verbose");
        return options;
    }

    private static boolean setSettings(String[] args) {
        Options opt = options();
        List<String> hashes = new LinkedList<String>();
        if (null == writers) {
            writers = new LinkedList<ResultWriter>();
        }

        try {
            cmd = parser.parse(opt, args);

            if (cmd.hasOption("h") || cmd.hasOption("help")) {
                lvFormater.printHelp(FileDuplicateChecker.class.toString(), opt);
                return false;
            }
            // Verbose
            quite = !cmd.hasOption("v");

            // START Hashes
            if (cmd.hasOption("as")) {
                hashes.add(HashComputer.HASH_MD5);
                hashes.add(HashComputer.HASH_SHA1);
                hashes.add(HashComputer.HASH_SHA256);
                hashes.add(HashComputer.HASH_SHA512);
            } else {
                if (cmd.hasOption("md5")) {
                    hashes.add(HashComputer.HASH_MD5);
                }
                if (cmd.hasOption("sha1")) {
                    hashes.add(HashComputer.HASH_SHA1);
                }
                if (cmd.hasOption("sha256")) {
                    hashes.add(HashComputer.HASH_SHA256);
                }
                if (cmd.hasOption("sha512")) {
                    hashes.add(HashComputer.HASH_SHA512);
                }
            }

            if (hashes.isEmpty()) {
                throw new ParseException("at least one hash must be given.");
            } else {
                FileDuplicateChecker.hashers = new String[hashes.size()];
                int i = 0;
                for (String hash : hashes) {
                    FileDuplicateChecker.hashers[i++] = hash;
                }
            }
            // END Hashes

            // START Path
            if (cmd.hasOption("p")) {
                rootPath = cmd.getOptionValue("p");
                recursive = cmd.hasOption('r');
            } else {
                throw new ParseException("Path is missing.");
            }
            // END Path

            // Start Format
            if (cmd.hasOption("fj")) {
                String fileName = cmd.getOptionValue("fj");
                logger.error(fileName);
                File f = new File(fileName);

                writers.add(new ResultJSONWriter(f));

            } else if (cmd.hasOption("fx")) {
                throw new ParseException(null);
            } else {
                throw new ParseException(null);
            }
            // END Format

        } catch (MissingArgumentException e) {
            if (null != e.getMessage()) {
                System.out.println(e.getMessage());
            }
            lvFormater.printHelp(FileDuplicateChecker.class.toString(), opt);
            return false;
        } catch (ParseException pvException) {
            if (null != pvException.getMessage()) {
                System.out.println(pvException.getMessage());
            }
            lvFormater.printHelp(FileDuplicateChecker.class.toString(), opt);
            return false;
        }
        return true;
    }
}