package javaforce.utils;
/**
* Monitor Dir (Linux : inotify)
*
* Uses JNA
*
* @author pquiring
*
* Created : Nov 3, 2013
*/
import java.util.*;
import javaforce.*;
import javaforce.jni.*;
public class monitordir {
public static interface Listener {
public void folderChangeEvent(String event, String path);
}
/** Loads native library. Only need to call once per process. */
private static int fd;
public static boolean init() {
try {
fd = LnxNative.inotify_init();
if (fd == -1) throw new Exception("inotify_init failed");
new Worker().start();
return true;
} catch (Exception e) {
JFLog.log(e);
return false;
}
}
/** Stops all watches. */
public static void uninit() {
active = false;
LnxNative.inotify_close(fd);
}
/** Start watching a folder. */
public static int add(String path) {
int wd = LnxNative.inotify_add_watch(fd, path, IN_ALL);
// JFLog.log("wd=" + wd);
return wd;
}
/** Stops watching a folder. */
public static void remove(int wd) {
LnxNative.inotify_rm_watch(fd, wd);
map.remove(wd);
}
private static boolean active = true;
private static HashMap<Integer, Listener> map = new HashMap<Integer, Listener>();
public static void setListener(int wd, Listener listener) {
map.put(wd, listener);
}
public static void main(String args[]) {
if (args.length == 0) {
System.out.println("Usage:jf-monitor-dir folder");
return;
}
if (!init()) return;
add(args[0]);
try { new Object().wait(); } catch (Exception e) {} //wait forever
}
public static class Worker extends Thread {
public void run() {
// JFLog.log("worker start");
while (active) {
byte data[] = LnxNative.inotify_read(fd);
int pos = 0;
int siz = data.length;
while (siz > 12) {
int _wd = LE.getuint32(data, pos);
pos += 4;
int _mask = LE.getuint32(data, pos);
pos += 4;
//cookie
pos += 4;
int _len = LE.getuint32(data, pos);
pos += 4;
String _name = _len > 0 ? LE.getString(data, pos, _len) : null;
siz -= 16 + _len;
String _event = null;
switch (_mask & IN_ALL) {
case IN_CREATE: _event = "CREATED"; break;
case IN_DELETE: _event = "DELETED"; break;
case IN_MOVED_FROM: _event = "MOVED_FROM"; break;
case IN_MOVED_TO: _event = "MOVED_TO"; break;
case IN_DELETE_SELF: _event = "DELETE_SELF"; break;
case IN_MOVED_SELF: _event = "MOVED_SELF"; break;
}
if (_event == null) continue;
Listener listener = map.get(_wd);
if (listener != null) {
listener.folderChangeEvent(_event, _name);
} else {
JFLog.log(_event + ":" + _name);
}
}
}
// JFLog.log("worker end");
}
}
private static final int IN_MOVED_FROM = 0x040;
private static final int IN_MOVED_TO = 0x080;
private static final int IN_CREATE = 0x100;
private static final int IN_DELETE = 0x200;
private static final int IN_DELETE_SELF = 0x0400;
private static final int IN_MOVED_SELF = 0x0800;
private static final int IN_ALL = 0xfc0;
/*
public class inotify_event extends Structure {
public int wd; // Watch descriptor
public int mask; // Mask of events
public int cookie; // Unique cookie associating related
// events (for rename(2))
public int len; // Size of name field
public char name[]; // Optional null-terminated name
};
*/
}