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

com.ovea.tadjin.util.fs.FrequencyFileSystemWatcher Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (C) 2011 Ovea 
 *
 * 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.ovea.tadjin.util.fs;

import java.io.File;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @author Mathieu Carbou ([email protected])
 */
public final class FrequencyFileSystemWatcher implements FileSystemWatcher {

    private static final Logger LOGGER = Logger.getLogger(FrequencyFileSystemWatcher.class.getName());

    private final List listeners = new CopyOnWriteArrayList();
    private volatile ScheduledExecutorService executor;

    @Override
    public void addListener(FileListener listener) {
        listeners.add(listener);
    }

    @Override
    public void start() {
        if (executor == null) {
            executor = new ScheduledThreadPoolExecutor(Runtime.getRuntime().availableProcessors() * 2, new ThreadPoolExecutor.CallerRunsPolicy());
        }
    }

    @Override
    public void stop() {
        if (executor != null) {
            ScheduledExecutorService e = executor;
            executor = null;
            e.shutdown();
        }
    }

    @Override
    public void watchDirectory(final long sleepDelay, final TimeUnit unit, final File directory, String... includes) {
        if (executor != null) {
            final AntFileScanner scanner = AntFileScanner.create(true, includes, new String[0]);
            executor.scheduleWithFixedDelay(new Runnable() {
                Map states = null;

                @Override
                public void run() {
                    try {
                        Map oldStates = getStates();
                        states = scan();
                        for (Map.Entry entry : getStates().entrySet()) {
                            FileState old = oldStates.remove(entry.getKey());
                            if (old == null) {
                                for (FileListener listener : listeners) {
                                    listener.onAddition(entry.getKey());
                                }
                            } else if (old.time != entry.getValue().time) {
                                for (FileListener listener : listeners) {
                                    listener.onChange(entry.getKey());
                                }
                            }
                        }
                        for (File file : oldStates.keySet()) {
                            for (FileListener listener : listeners) {
                                listener.onRemoval(file);
                            }
                        }
                    } catch (Exception e) {
                        if (!Thread.currentThread().isInterrupted()) {
                            LOGGER.log(Level.SEVERE, "FileSystem watching job error: " + e.getMessage(), e);
                        }
                    }
                }

                Map getStates() {
                    if (states == null) {
                        states = scan();
                        for (File file : states.keySet()) {
                            for (FileListener listener : listeners) {
                                listener.onAddition(file);
                            }
                        }
                    }
                    return states;
                }

                Map scan() {
                    Map states = new LinkedHashMap();
                    if (directory.exists() && directory.canRead())
                        for (File f : scanner.scan(directory))
                            states.put(f, new FileState(f));
                    return states;
                }
            }, 0, sleepDelay, unit);
        }
    }

    private final ConcurrentHashMap> files = new ConcurrentHashMap>();

    @Override
    public void watchFile(long sleepDelay, TimeUnit unit, final File file) {
        if (files.containsKey(file)) return;
        files.put(file, Void.TYPE);
        executor.scheduleWithFixedDelay(new Runnable() {
            FileState state = new FileState(file);

            @Override
            public void run() {
                FileState old = state;
                state = new FileState(file);
                if (old.exist && !state.exist) {
                    for (FileListener listener : listeners) {
                        listener.onRemoval(file);
                    }
                } else if (!old.exist && state.exist) {
                    for (FileListener listener : listeners) {
                        listener.onAddition(file);
                    }
                } else if (old.exist && state.exist && old.time != state.time) {
                    for (FileListener listener : listeners) {
                        listener.onChange(file);
                    }
                }
            }
        }, 0, sleepDelay, unit);
    }

    private static final class FileState {
        final boolean exist;
        final long time;

        FileState(File file) {
            this.exist = file.exists();
            this.time = file.lastModified();
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy