/******************************************************************************* * JNotify - Allow java applications to register to File system events. * * Copyright (C) 2005 - Content Objects * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * ****************************************************************************** * * You may also redistribute and/or modify this library under the terms of the * Eclipse Public License. See epl.html. * ****************************************************************************** * * Content Objects, Inc., hereby disclaims all copyright interest in the * library `JNotify' (a Java library for file system events). * * Yahali Sherman, 21 November 2005 * Content Objects, VP R&D. * ****************************************************************************** * Author : Omry Yadan ******************************************************************************/ package net.contentobjects.jnotify.linux; import net.contentobjects.jnotify.JNotifyException; import de.dal33t.powerfolder.util.os.OSUtil; public class JNotify_linux { static final boolean DEBUG = false; public static boolean WARN = true; static { OSUtil.loadLibrary(JNotify_linux.class, "jnotify"); //System.loadLibrary("jnotify"); int res = nativeInit(); if (res != 0) { throw new RuntimeException("Error initializing fshook_inotify library. linux error code #" + res + ", man errno for more info"); } init(); } /* the following are legal, implemented events that user-space can watch for */ public final static int IN_ACCESS = 0x00000001; /* File was accessed */ public final static int IN_MODIFY = 0x00000002; /* File was modified */ public final static int IN_ATTRIB = 0x00000004; /* Metadata changed */ public final static int IN_CLOSE_WRITE = 0x00000008; /* Writtable file was closed */ public final static int IN_CLOSE_NOWRITE = 0x00000010; /* Unwrittable file closed */ public final static int IN_OPEN = 0x00000020; /* File was opened */ public final static int IN_MOVED_FROM = 0x00000040; /* File was moved from X */ public final static int IN_MOVED_TO = 0x00000080; /* File was moved to Y */ public final static int IN_CREATE = 0x00000100; /* Subfile was created */ public final static int IN_DELETE = 0x00000200; /* Subfile was deleted */ public final static int IN_DELETE_SELF = 0x00000400; /* Self was deleted */ public final static int IN_MOVE_SELF = 0x00000800; /* Self was moved */ /* the following are legal events. they are sent as needed to any watch */ public final static int IN_UNMOUNT = 0x00002000; /* Backing fs was unmounted */ public final static int IN_Q_OVERFLOW = 0x00004000; /* Event queued overflowed */ public final static int IN_IGNORED = 0x00008000; /* File was ignored */ /* helper events */ public final static int IN_CLOSE = (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE); /* close */ public final static int IN_MOVE = (IN_MOVED_FROM | IN_MOVED_TO); /* moves */ /* special flags */ public final static int IN_ISDIR = 0x40000000; /* * event occurred against * dir */ public final static int IN_ONESHOT = 0x80000000; /* only send event once */ /* * All of the events - we build the list by hand so that we can add flags in * the future and not break backward compatibility. Apps will get only the * events that they originally wanted. Be sure to add new events here! */ public final static int IN_ALL_EVENT = (IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE | IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM | IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF); private static INotifyListener _notifyListener; private static native int nativeInit(); private static native int nativeAddWatch(String path, int mask); private static native int nativeRemoveWatch(int wd); private native static int nativeNotifyLoop(); private static native String getErrorDesc(long errorCode); public static int addWatch(String path, int mask) throws JNotifyException { int wd = nativeAddWatch(path, mask); if (wd < 0) { throw new JNotifyException_linux("Error watching " + path + " : " + getErrorDesc(-wd), -wd); } debug(wd + " = JNotify_linux.addWatch("+ path + "," + getMaskDesc(mask)+ ")"); return wd; } public static void removeWatch(int wd) throws JNotifyException { int ret = nativeRemoveWatch(wd); debug(ret + " = JNotify_linux.removeWatch("+ wd + ")"); if (ret != 0) { throw new JNotifyException_linux("Error removing watch " + wd, ret); } } private static void init() { Thread thread = new Thread("INotify thread") { public void run() { nativeNotifyLoop(); } }; thread.setDaemon(true); thread.start(); } static void callbackProcessEvent(String name, int wd, int mask, int cookie) { debug("JNotify.event(name=" + name + ", wd="+ wd+", " + getMaskDesc(mask)+ (cookie != 0 ? ", cookie=" +cookie : "" )+ ")"); if (_notifyListener != null) { _notifyListener.notify(name, wd, mask, cookie); } } public static void setNotifyListener(INotifyListener notifyListener) { if (_notifyListener == null) { _notifyListener = notifyListener; } else { throw new RuntimeException("Notify listener is already set. multiple notify listeners are not supported."); } } private static String getMaskDesc(int linuxMask) { boolean lIN_ACCESS = (linuxMask & JNotify_linux.IN_ACCESS) != 0; boolean lIN_MODIFY = (linuxMask & JNotify_linux.IN_MODIFY) != 0; boolean lIN_ATTRIB = (linuxMask & JNotify_linux.IN_ATTRIB) != 0; boolean lIN_CLOSE_WRITE = (linuxMask & JNotify_linux.IN_CLOSE_WRITE) != 0; boolean lIN_CLOSE_NOWRITE = (linuxMask & JNotify_linux.IN_CLOSE_NOWRITE) != 0; boolean lIN_OPEN = (linuxMask & JNotify_linux.IN_OPEN) != 0; boolean lIN_MOVED_FROM = (linuxMask & JNotify_linux.IN_MOVED_FROM) != 0; boolean lIN_MOVED_TO = (linuxMask & JNotify_linux.IN_MOVED_TO) != 0; boolean lIN_CREATE = (linuxMask & JNotify_linux.IN_CREATE) != 0; boolean lIN_DELETE = (linuxMask & JNotify_linux.IN_DELETE) != 0; boolean lIN_DELETE_SELF = (linuxMask & JNotify_linux.IN_DELETE_SELF) != 0; boolean lIN_MOVE_SELF = (linuxMask & JNotify_linux.IN_MOVE_SELF) != 0; boolean lIN_UNMOUNT = (linuxMask & JNotify_linux.IN_UNMOUNT) != 0; boolean lIN_Q_OVERFLOW = (linuxMask & JNotify_linux.IN_Q_OVERFLOW) != 0; boolean lIN_IGNORED = (linuxMask & JNotify_linux.IN_IGNORED) != 0; String s =""; if (lIN_ACCESS) s += "IN_ACCESS|"; if (lIN_MODIFY) s += "IN_MODIFY|"; if (lIN_ATTRIB) s += "IN_ATTRIB|"; if (lIN_CLOSE_WRITE) s += "IN_CLOSE_WRITE|"; if (lIN_CLOSE_NOWRITE) s += "IN_CLOSE_NOWRITE|"; if (lIN_OPEN) s += "IN_OPEN|"; if (lIN_MOVED_FROM) s += "IN_MOVED_FROM|"; if (lIN_MOVED_TO) s += "IN_MOVED_TO|"; if (lIN_CREATE) s += "IN_CREATE|"; if (lIN_DELETE) s += "IN_DELETE|"; if (lIN_DELETE_SELF) s += "IN_DELETE_SELF|"; if (lIN_MOVE_SELF) s += "IN_MOVE_SELF|"; if (lIN_UNMOUNT) s += "IN_UNMOUNT|"; if (lIN_Q_OVERFLOW) s += "IN_Q_OVERFLOW|"; if (lIN_IGNORED) s += "IN_IGNORED|"; return s; } static void debug(String msg) { if (DEBUG) { System.out.println(msg); } } public static void warn(String warning) { if (WARN) { System.err.println(warning); } } }