Java tutorial
/* 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; } }