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

com.mypurecloud.sdk.v2.guest.FileWatcher Maven / Gradle / Ivy

The newest version!
package com.mypurecloud.sdk.v2.guest;

import java.util.EventListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.WatchService;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.ClosedWatchServiceException;
import java.util.EventObject;
import java.util.List;
import java.util.Collections;
import java.util.Arrays;
import static java.nio.file.StandardWatchEventKinds.*;

public class FileWatcher implements Runnable {
    protected List listeners = new ArrayList<>();
    protected static final List watchServices = new ArrayList<>();
    protected final File parentFolder;
    protected Path fileName;
    
    public FileWatcher(File parentFolder, Path fileName) {
        this.parentFolder = parentFolder;
        this.fileName = fileName;
    }
    
    public void watch() {
        if (parentFolder.exists()) {
            Thread thread = new Thread(this);
            thread.setDaemon(true);
            thread.start();
        }
    }
    
    @Override
    public void run() {
        try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
            Path path = Paths.get(parentFolder.getAbsolutePath());
            path.register(watchService, ENTRY_CREATE, ENTRY_MODIFY);
            watchServices.add(watchService);
            boolean poll = true;
            while (poll) {
                poll = pollEvents(watchService);
            }
        } catch (IOException | InterruptedException | ClosedWatchServiceException e) {
            Thread.currentThread().interrupt();
        }
    }
    
    protected boolean pollEvents(WatchService watchService) throws InterruptedException {
        WatchKey key = watchService.take();
        Path path = (Path) key.watchable();
        for (WatchEvent event : key.pollEvents()) {
            final Path changed = (Path) event.context();
            if (changed.endsWith(fileName) || fullPathEndsWith(changed, watchService)) {
                notifyListeners(event.kind(), path.resolve(changed).toFile());
            }
        }
        return key.reset();
    }

    // method for checking the changed path's ending when the config file's parent directory did not exist at init
    protected boolean fullPathEndsWith(Path changed, WatchService watchService) {
        boolean nullOrEmpty = changed == null
                || changed.toString().isEmpty()
                || fileName == null
                || fileName.toString().isEmpty();
        if (nullOrEmpty)
            return false;
        File parentDirectory = new File(parentFolder.getAbsolutePath());
        StringBuilder filePath = new StringBuilder();
        if (fileName.toString().indexOf('\\') != -1) {
            filePath = new StringBuilder(fileName.toString().replace('\\', '/'));
        } else {
            filePath = new StringBuilder(fileName.toString());
        }
        if (filePath.charAt(0) == '/')
            filePath = new StringBuilder(filePath.substring(1, filePath.length()));
        String[] pathPoints = filePath.toString().split("/");
        return searchFiles(parentDirectory, parentDirectory.listFiles(), pathPoints, watchService);
    }

    // recursively searches for the config file in subdirectories of the config file path
    protected boolean searchFiles(File parent, File[] files, String[] pathPoints, WatchService watchService) {
        if (files != null && files.length > 0) {
            for (File file : files) {
                if (file.getName().equals(pathPoints[0])) {
                    if (file.isFile()
                            && file.exists()
                            && file.getAbsolutePath().endsWith(fileName.toString())) {
                        return true;
                    }
                    Path path = Paths.get(file.getAbsolutePath());
                    try {
                        path.register(watchService, ENTRY_CREATE, ENTRY_MODIFY);
                    } catch (IOException e) {
                        // no-op
                    }
                    return searchFiles(file, file.listFiles(), Arrays.copyOfRange(pathPoints, 1, pathPoints.length), watchService);
                }
            }
        }
        return false;
    }
    
    protected void notifyListeners(WatchEvent.Kind kind, File file) {
        FileEvent event = new FileEvent(file);
        if (kind == ENTRY_CREATE) {
            List removeList = new ArrayList<>();
            for (FileListener listener : listeners) {
                boolean shouldRemove = listener.onCreated(event);
                if (shouldRemove) {
                    removeList.add(listener);
                }
            }
            for (FileListener listener : removeList) {
                removeListener(listener);
            }
        }
        else if (kind == ENTRY_MODIFY) {
            List removeList = new ArrayList<>();
            for (FileListener listener : listeners) {
                boolean shouldRemove = listener.onModified(event);
                if (shouldRemove) {
                    removeList.add(listener);
                }
            }
            for (FileListener listener : removeList) {
                removeListener(listener);
            }
        }
    }
    
    public FileWatcher addListener(FileListener listener) {
        listeners.add(listener);
        return this;
    }
    
    public FileWatcher removeListener(FileListener listener) {
        listeners.remove(listener);
        return this;
    }
    
    public List getListeners() {
        return listeners;
    }
    
    public FileWatcher setListeners(List listeners) {
        this.listeners = listeners;
        return this;
    }
    
    public static List getWatchServices() {
        return Collections.unmodifiableList(watchServices);
    }
    
    public static class FileEvent extends EventObject{
        public FileEvent(File file) {
            super(file);
        }
        public File getFile() {
            return (File) getSource();
        }
    }
    
    public interface FileListener extends EventListener {
        public boolean onCreated(FileEvent event);
        public boolean onModified(FileEvent event);
    }
    
    public static abstract class FileAdapter implements FileListener {
        @Override
        public boolean onCreated(FileEvent event) {
            return false;
        }
        @Override
        public boolean onModified(FileEvent event) {
            return false;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy