/** * 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. * * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. */ package org.sintef.thingml; import java.awt.*; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.util.Vector; /** * A very simple file monitor, that will monitor a directory tree and trigger * actions, when it detects changes. Only directory trees, that actually * contain files matching a filter criteria are included. */ public class FileMonitor implements Runnable { private File root; private SimpleFileManager simpleFileManager; private Vector<Runnable> clients = new Vector<Runnable>(); /** * Construct a new monitor, monitoring a specific directory tree * @param root root of the directory tree to monitor * @param smf the <code>SimpleFileManager</code> to notify */ public FileMonitor(File root, SimpleFileManager smf) { this.root = root; simpleFileManager = smf; } /** * Descend recursively into a directory tree and return the most recent * modifaction date. * @param dir the directory to descend into * @returnThe most recent timestamp found. */ private long descend(File dir, int depth) { File[] lst = dir.listFiles(); long lastMod = dir.lastModified(); long test = lastMod; for (int i = 0; i < lst.length; i++) { if (depth > 0 && lst[i].canRead()) { if (lst[i].isDirectory()) { test = descend(lst[i], depth - 1); } else { test = lst[i].lastModified(); } } if (test > lastMod) lastMod = test; } return lastMod; } /** * Add a client to the notification list * @param r a Runnable, that will be submitted to * <code>EventQueue.invokeAndWait()</code> once a change in the * directory tree is detected. */ public synchronized void addClient(Runnable r) { clients.add(r); } // Interface implementation: Runnable /** {inheritdoc} */ public void run() { long lastMod = 0; while (true) { try { long tmp = descend(root, SimpleFileManager.MAXDEPTH); if (tmp > lastMod) { simpleFileManager.refresh(); Runnable[] r = clients.toArray(new Runnable[0]); for (int i = 0; i < r.length; i++) { EventQueue.invokeAndWait(r[i]); } lastMod = tmp; } Thread.sleep(1000); } catch (InterruptedException e) { // Goodbye return; } catch (InvocationTargetException e) { //?! return; } } } }