/* * Copyright (C) 2008 Clam <clamisgood@gmail.com> * Copyright (C) 2009 Quadduc <quadduc@gmail.com> * * This file is part of LateralGM. * LateralGM is free software and comes with ABSOLUTELY NO WARRANTY. * See LICENSE for details. */ package org.lateralgm.file; import java.io.File; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import org.lateralgm.main.UpdateSource; import org.lateralgm.main.UpdateSource.UpdateEvent; import org.lateralgm.main.UpdateSource.UpdateTrigger; public class FileChangeMonitor implements Runnable { private static final int POLL_INTERVAL = 1000; public enum Flag { CHANGED,DELETED } private static ScheduledExecutorService monitorService = Executors.newSingleThreadScheduledExecutor(); public final File file; public final Executor executor; private final UpdateRunnable changedRunnable, deletedRunnable; private final ScheduledFuture<?> future; private final UpdateTrigger trigger = new UpdateTrigger(); public final UpdateSource updateSource = new UpdateSource(this,trigger); public FileChangeMonitor(File f, Executor e) { if (!f.exists()) throw new IllegalArgumentException(); file = f; executor = e; changedRunnable = new UpdateRunnable(new FileUpdateEvent(updateSource,Flag.CHANGED)); deletedRunnable = new UpdateRunnable(new FileUpdateEvent(updateSource,Flag.DELETED)); lastModified = file.lastModified(); length = file.length(); future = monitorService.scheduleWithFixedDelay(this,POLL_INTERVAL,POLL_INTERVAL, TimeUnit.MILLISECONDS); } public FileChangeMonitor(String f, Executor e) { this(new File(f),e); } public void stop() { future.cancel(false); } private long lastModified, length; private boolean changed; public void run() { if (!file.exists()) { executor.execute(deletedRunnable); future.cancel(false); return; } long m = file.lastModified(); long l = file.length(); if (m != lastModified || l != length) { changed = true; lastModified = m; length = l; } else if (changed) { executor.execute(changedRunnable); changed = false; } } public class FileUpdateEvent extends UpdateEvent { public final Flag flag; public FileUpdateEvent(UpdateSource s, Flag f) { super(s); flag = f; } } private class UpdateRunnable implements Runnable { public final FileUpdateEvent event; public UpdateRunnable(FileUpdateEvent e) { event = e; } public void run() { trigger.fire(event); } } }