org.pgptool.gui.decryptedlist.impl.MonitoringDecryptedFilesServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.pgptool.gui.decryptedlist.impl.MonitoringDecryptedFilesServiceImpl.java

Source

/*******************************************************************************
 * PGPTool is a desktop application for pgp encryption/decryption
 * Copyright (C) 2017 Sergey Karpushin
 *
 * 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 org.pgptool.gui.decryptedlist.impl;

import java.io.File;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent.Kind;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import org.apache.log4j.Logger;
import org.pgptool.gui.configpairs.api.ConfigPairs;
import org.pgptool.gui.decryptedlist.api.DecryptedFile;
import org.pgptool.gui.decryptedlist.api.MonitoringDecryptedFilesService;
import org.pgptool.gui.tools.fileswatcher.FilesWatcherHandler;
import org.pgptool.gui.tools.fileswatcher.MultipleFilesWatcher;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;

import com.google.common.base.Preconditions;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;

public class MonitoringDecryptedFilesServiceImpl
        implements MonitoringDecryptedFilesService, InitializingBean, DisposableBean {
    private static Logger log = Logger.getLogger(MonitoringDecryptedFilesServiceImpl.class);

    protected static final long TIME_TO_ENSURE_FILE_WAS_DELETED_MS = 2000;

    public static final String PREFIX = "decrhist:";

    @Autowired
    private ConfigPairs monitoredDecrypted;

    private MultipleFilesWatcher multipleFilesWatcher;

    private Cache<String, DecryptedFile> recentlyRemoved = CacheBuilder.newBuilder()
            .expireAfterWrite(TIME_TO_ENSURE_FILE_WAS_DELETED_MS, TimeUnit.MILLISECONDS).build();

    @Override
    public void afterPropertiesSet() throws Exception {
        setupFileWatcher();
    }

    private void setupFileWatcher() {
        // TODO: Fix. Smells like DI violation
        multipleFilesWatcher = new MultipleFilesWatcher(dirWatcherHandler, "MonitoringDecryptedFilesService");
        List<DecryptedFile> entries = getDecryptedFiles();
        for (DecryptedFile entry : entries) {
            String decryptedFile = entry.getDecryptedFile();
            if (!new File(decryptedFile).exists()) {
                log.debug("Previously registered file is no longer exists, remove =ing it from the tracking "
                        + decryptedFile);
                remove(decryptedFile);
                continue;
            }
            multipleFilesWatcher.watchForFileChanges(decryptedFile);
        }
    }

    @Override
    public void destroy() throws Exception {
        multipleFilesWatcher.stopWatcher();
    }

    private FilesWatcherHandler dirWatcherHandler = new FilesWatcherHandler() {
        @Override
        public void handleFileChanged(Kind<?> operation, String fileAbsolutePathname) {
            if (StandardWatchEventKinds.ENTRY_CREATE.equals(operation)) {
                DecryptedFile recentlyRemovedEntry = recentlyRemoved.getIfPresent(fileAbsolutePathname);
                if (recentlyRemovedEntry != null) {
                    addOrUpdate(recentlyRemovedEntry);
                }
                return;
            }

            if (StandardWatchEventKinds.ENTRY_DELETE.equals(operation)) {
                remove(fileAbsolutePathname);
                return;
            }

            // Other cases not supported -- not needed
        }
    };

    @Override
    public synchronized void addOrUpdate(DecryptedFile decryptedFile) {
        try {
            Preconditions.checkArgument(decryptedFile != null, "decryptedFile is NULL");
            Preconditions.checkArgument(decryptedFile.getDecryptedFile() != null,
                    "decryptedFile.DecryptedFile is NULL");
            Preconditions.checkArgument(decryptedFile.getEncryptedFile() != null,
                    "decryptedFile.EncryptedFile is NULL");

            String key = buildKey(decryptedFile.getDecryptedFile());
            monitoredDecrypted.put(key, decryptedFile);
            multipleFilesWatcher.watchForFileChanges(decryptedFile.getDecryptedFile());
        } catch (Throwable t) {
            throw new RuntimeException("Failed to update decrypted file for monitoring", t);
        }
    }

    @Override
    public synchronized void remove(String depcryptedFilePathname) {
        try {
            Preconditions.checkArgument(depcryptedFilePathname != null, "depcryptedFilePathname is NULL");

            String key = buildKey(depcryptedFilePathname);
            DecryptedFile existing = monitoredDecrypted.find(key, null);
            if (existing == null) {
                // if it's not there -- nothing to delete
                return;
            }

            // Remember this file in case it will appear right away
            recentlyRemoved.put(depcryptedFilePathname, existing);

            monitoredDecrypted.put(key, null);

            multipleFilesWatcher.stopWatchingFile(depcryptedFilePathname);
        } catch (Throwable t) {
            throw new RuntimeException("Failed to unregister decrypted file from monitoring", t);
        }
    }

    private String buildKey(String decryptedFile) {
        return decryptedFile;
    }

    @Override
    public synchronized List<DecryptedFile> getDecryptedFiles() {
        return new ArrayList<>(monitoredDecrypted.getAll().stream().map(x -> (DecryptedFile) x.getValue())
                .collect(Collectors.toList()));
    }

    @Override
    public DecryptedFile findByDecryptedFile(String decryptedFile) {
        return getDecryptedFiles().stream().filter(x -> x.getDecryptedFile().equals(decryptedFile)).findFirst()
                .orElse(null);
    }

    @Override
    public DecryptedFile findByEncryptedFile(String encryptedFile, Predicate<DecryptedFile> filter) {
        return getDecryptedFiles().stream()
                .filter(x -> x.getEncryptedFile().equals(encryptedFile) && filter.test(x)).findFirst().orElse(null);
    }
}