/******************************************************************************* * Copyright (c) 2010- Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.databoard.accessor.impl; import java.io.File; import java.io.FileFilter; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.CopyOnWriteArrayList; /** * DirectoryWatch monitors a directory for file additions / removals. *

* DirectoryWatch is used in the long wait for WatchService. * * @author Toni Kalajainen */ public class DirectoryWatch { public static final long POLL_INTERVAL = 10000; // seconds Timer timer; FileFilter filter; File directory; List knownFiles; CopyOnWriteArrayList listeners = new CopyOnWriteArrayList(); TimerTask task = new TimerTask() { public void run() { poll(); } }; public DirectoryWatch(File directory, FileFilter filter) { this.directory = directory; this.filter = filter; knownFiles = readFiles(); timer = new Timer(directory.toString()+" watcher", true); timer.schedule(task, 1, POLL_INTERVAL); } /** * Close the timer. * This method does one last poll. */ public void close() { timer.cancel(); poll(); } public static class DirectoryEvent { public Set filesAdded = new HashSet(); public Set filesRemoved = new HashSet(); } public interface DirectoryListener { void onWatchEvent(DirectoryEvent e); } public void addListener(DirectoryListener listener) { listeners.add(listener); } public void removeListener(DirectoryListener listener) { listeners.remove(listener); } /** * Get a snapshot of currently known files * * @return a snapshot of files */ public List files() { return knownFiles; } /** * Reload the directory */ public void refresh() { poll(); } /** * Add file to the known list without reading the disk. * The modification is void after next timer refresh. * * @param f */ public synchronized void add(File f) { ArrayList newList = new ArrayList( knownFiles ); newList.add(f); knownFiles = newList; } /** * Remove file from the known list without reading the disk. * The modification is void after next timer refresh. * * @param f */ public synchronized void remove(File f) { ArrayList newList = new ArrayList( knownFiles ); newList.remove(f); knownFiles = newList; } /** * Read files * @return a list of absolute files */ private List readFiles() { File[] files = directory.listFiles(filter); List newFiles = new ArrayList( files.length ); for (File f : files) { // System.out.println(f); // f = f.getAbsoluteFile(); // System.out.println(f); newFiles.add(f); } return newFiles; } /** * Read files and spawn events */ private synchronized void poll() { DirectoryEvent e = read(); if (e.filesAdded.isEmpty() && e.filesRemoved.isEmpty()) return; // Spawn an event for (DirectoryListener l : listeners) l.onWatchEvent(e); } private DirectoryEvent read() { List oldFiles = knownFiles; List newFiles = readFiles(); knownFiles = newFiles; DirectoryEvent result = new DirectoryEvent(); result.filesAdded.addAll(newFiles); result.filesAdded.removeAll(oldFiles); result.filesRemoved.addAll(oldFiles); result.filesRemoved.removeAll(newFiles); return result; } }