diff options
Diffstat (limited to 'bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/p2/directorywatcher/DirectoryWatcher.java')
-rw-r--r-- | bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/p2/directorywatcher/DirectoryWatcher.java | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/p2/directorywatcher/DirectoryWatcher.java b/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/p2/directorywatcher/DirectoryWatcher.java new file mode 100644 index 000000000..14a398949 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/p2/directorywatcher/DirectoryWatcher.java @@ -0,0 +1,197 @@ +/******************************************************************************* + * Copyright (c) 2007 aQute, IBM Corporation and others. 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: + * aQute - initial implementation and ideas + * IBM Corporation - initial adaptation to Equinox provisioning use + ******************************************************************************/ +package org.eclipse.equinox.p2.directorywatcher; + +import java.io.File; +import java.io.IOException; +import java.util.*; +import org.osgi.framework.BundleContext; + +public class DirectoryWatcher extends Thread { + public final static String POLL = "eclipse.p2.directory.watcher.poll"; + public final static String DIR = "eclipse.p2.directory.watcher.dir"; + public final static String DEBUG = "eclipse.p2.directory.watcher.debug"; + private static long debug; + + public static void log(String string, Throwable e) { + System.err.println(string + ": " + e); + if (debug > 0) + e.printStackTrace(); + } + + File targetDirectory; + boolean done = false; + long poll = 2000; + Map processedBundles = new HashMap(); + Map processedConfigs = new HashMap(); + private Set listeners = new HashSet(); + private HashSet scannedFiles = new HashSet(); + private HashSet removals; + private Set pendingDeletions; + + public DirectoryWatcher(Dictionary properties, BundleContext context) { + super("Directory Watcher"); + poll = getLong(context.getProperty(POLL), poll); + debug = getLong(context.getProperty(DEBUG), -1); + + String dir = (String) properties.get(DIR); + if (dir == null) + dir = "./load"; + + try { + targetDirectory = new File(dir).getCanonicalFile(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + targetDirectory.mkdirs(); + } + + public void addListener(IDirectoryChangeListener listener) { + listeners.add(listener); + } + + public void close() { + done = true; + interrupt(); + try { + join(10000); + } catch (InterruptedException ie) { + // Ignore + } + } + + private long getLong(String value, long defaultValue) { + if (value != null) + try { + return Long.parseLong(value); + } catch (Exception e) { + System.out.println(value + " is not a long"); + } + return defaultValue; + } + + public File getTargetDirectory() { + return targetDirectory; + } + + private boolean isInterested(IDirectoryChangeListener listener, File file) { + String[] extensions = listener.getExtensions(); + for (int i = 0; i < extensions.length; i++) + if (file.getPath().endsWith(extensions[i])) + return true; + return false; + } + + /** + * Notify the listeners of the files that have been deleted or marked for deletion. + */ + private void notifyRemovals() { + Set removed = removals; + for (Iterator i = listeners.iterator(); i.hasNext();) { + IDirectoryChangeListener listener = (IDirectoryChangeListener) i.next(); + for (Iterator j = removed.iterator(); j.hasNext();) { + File file = (File) j.next(); + if (isInterested(listener, file)) + listener.removed(file); + } + } + } + + private void processFile(File file, IDirectoryChangeListener listener) { + try { + Long oldTimestamp = listener.getSeenFile(file); + if (oldTimestamp == null) { + // The file is new + listener.added(file); + } else { + // The file is not new but may have changed + long lastModified = file.lastModified(); + if (oldTimestamp.longValue() != lastModified) + listener.changed(file); + } + } catch (Exception e) { + log("Processing : " + listener, e); + } + } + + /** + * Try to remove the files that have been marked for deletion. + */ + private void processPendingDeletions() { + for (Iterator iterator = pendingDeletions.iterator(); iterator.hasNext();) { + File file = (File) iterator.next(); + if (!file.exists() || file.delete()) + iterator.remove(); + new File(file.getPath() + ".del").delete(); + } + } + + public void run() { + if (debug > 0) { + System.out.println(POLL + "(ms) " + poll); + System.out.println(DIR + " " + targetDirectory.getAbsolutePath()); + System.out.println(DEBUG + " " + debug); + } + while (!done) + try { + startPoll(); + scanDirectory(); + stopPoll(); + Thread.sleep(poll); + } catch (InterruptedException e) { + // ignore + } catch (Throwable e) { + log("In main loop, we have serious trouble", e); + } + } + + private void scanDirectory() { + File list[] = targetDirectory.listFiles(); + if (list == null) + return; + for (int i = 0; i < list.length; i++) { + File file = list[i]; + // if this is a deletion marker then add to the list of pending deletions. + if (list[i].getPath().endsWith(".del")) { + File target = new File(file.getPath().substring(0, file.getPath().length() - 4)); + removals.add(target); + pendingDeletions.add(target); + } else { + // else remember that we saw the file and remove it from this list of files to be + // removed at the end. Then notify all the listeners as needed. + scannedFiles.add(file); + removals.remove(file); + for (Iterator iterator = listeners.iterator(); iterator.hasNext();) { + IDirectoryChangeListener listener = (IDirectoryChangeListener) iterator.next(); + if (isInterested(listener, file)) + processFile(file, listener); + } + } + } + } + + private void startPoll() { + removals = scannedFiles; + scannedFiles = new HashSet(); + pendingDeletions = new HashSet(); + for (Iterator i = listeners.iterator(); i.hasNext();) + ((IDirectoryChangeListener) i.next()).startPoll(); + } + + private void stopPoll() { + notifyRemovals(); + removals = scannedFiles; + for (Iterator i = listeners.iterator(); i.hasNext();) + ((IDirectoryChangeListener) i.next()).stopPoll(); + processPendingDeletions(); + } +} |