/* The MIT License (MIT) * Copyright (c) 2014 Nicholas Wright * http://opensource.org/licenses/MIT */ package com.github.dozedoff.commonj.hash; import java.io.File; import java.io.FileNotFoundException; import java.io.FilenameFilter; import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Path; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.LinkedList; import java.util.concurrent.LinkedBlockingQueue; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.github.dozedoff.commonj.file.BinaryFileReader; import com.github.dozedoff.commonj.file.FileInfo; /** * Class for hashing files in a directory. */ public class DirectoryHasher { LinkedBlockingQueue<FileInfo> outputQueue = null; final static Logger logger = LoggerFactory.getLogger(DirectoryHasher.class); private HashWorker hashWorker; private FilenameFilter filter = null; public DirectoryHasher(LinkedBlockingQueue<FileInfo> outputQueue) { this.filter = new AcceptAllFilter(); this.outputQueue = outputQueue; hashWorker = new HashWorker(); hashWorker.setDaemon(true); hashWorker.start(); } public void setFilter(FilenameFilter filter) { this.filter = filter; } public void hashDirectory(String directory) throws IOException { File dir = new File(directory); // check if the directory exists if (!dir.exists()) { throw new FileNotFoundException("Directory " + dir + " does not exist"); } logger.info("Starting to walk {}", dir); java.nio.file.Files.walkFileTree(dir.toPath(), new DirectoryVisitor(filter)); } class AcceptAllFilter implements FilenameFilter { @Override public boolean accept(File dir, String name) { return true; } } class DirectoryVisitor extends SimpleFileVisitor<Path> { FilenameFilter filter; public DirectoryVisitor(FilenameFilter filter) { this.filter = filter; } @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { if (file == null) { return FileVisitResult.CONTINUE; } Path dir = file.getParent(); if(dir == null) { return FileVisitResult.CONTINUE; } Path filename = file.getFileName(); if (filename == null) { return FileVisitResult.CONTINUE; } if (filter.accept(dir.toFile(), filename.toString())) { FileInfo fi = new FileInfo(file.toFile(), null); hashWorker.addFile(fi); } return super.visitFile(file, attrs); } } /** * This Tread hashes files and adds them to a queue. */ class HashWorker extends Thread { LinkedBlockingQueue<FileInfo> inputQueue = new LinkedBlockingQueue<>(); LinkedList<FileInfo> workingList = new LinkedList<>(); HashMaker hash = new HashMaker(); BinaryFileReader bfr = new BinaryFileReader(); public void addFile(FileInfo file) { inputQueue.add(file); } @Override public void run() { while (!isInterrupted()) { // grab some work inputQueue.drainTo(workingList); // process items for (FileInfo f : workingList) { try { f.setHash(hash.hash(bfr.get(f.getFile()))); outputQueue.add(f); } catch (IOException e) { logger.warn("Could not hash file: " + e.getMessage()); } } workingList.clear(); } } } }