JNotify
JNotify
Nativ megoldás. Az operációs rendszer értesít a változásokról.
A websiton található sample minimális átirat.
1public class JNotifySample { 2 public static void main(String args[]) throws Exception { 3 // path to watch 4 String path ="c:/TEMP"; 5 // watch mask, specify events you care about, 6 // or JNotify.FILE_ANY for all events. 7 int mask = JNotify.FILE_CREATED | 8 JNotify.FILE_DELETED | 9 JNotify.FILE_MODIFIED | 10 JNotify.FILE_RENAMED; 11 12 // watch subtree? 13 boolean watchSubtree = true; 14 15 // add actual watch 16 int watchID = JNotify.addWatch(path, mask, watchSubtree, new Listener()); 17 18 // sleep a little, the application will exit if you 19 // don't (watching is asynchronous), depending on your 20 // application, this may not be required 21 Thread.sleep(1000000); 22 23 // to remove watch the watch 24 boolean res = JNotify.removeWatch(watchID); 25 if (!res) { 26 // invalid watch ID specified. 27 } 28 } 29 30 static class Listener implements JNotifyListener { 31 public void fileRenamed(int wd, String rootPath, String oldName, 32 String newName) { 33 print("renamed " + rootPath + " : " + oldName + " -> " + newName); 34 } 35 36 public void fileModified(int wd, String rootPath, String name) { 37 print("modified " + rootPath + " : " + name); 38 } 39 40 public void fileDeleted(int wd, String rootPath, String name) { 41 print("deleted " + rootPath + " : " + name); 42 } 43 44 public void fileCreated(int wd, String rootPath, String name) { 45 print("created " + rootPath + " : " + name); 46 } 47 48 void print(String msg) { 49 System.err.println(msg); 50 } 51 } 52}
Működésének jellemzői:
- Aszinkron értesítés folyik. Semmi ráhatásunk nincs, hogy mikor kapjuk az értesítést.
- Könyvtár létrehozás:
-
created c:/TEMP : notify\dir
az új könyvtár létrehozása -
modified c:/TEMP : notify
szülő könyvtár módosulása(!)
-
- könyvtár törlése:
deleted c:/TEMP : notify\dir
modified c:/TEMP : notify
- file létrehozása
created c:/TEMP : notify\file.txt
modified c:/TEMP : notify
- file módosítása
modified c:/TEMP : notify\file.txt
- file átnevezése
renamed c:/TEMP : notify\file.txt -> notify\file2.txt
modified c:/TEMP : notify
modified c:/TEMP : notify\file2.txt
modified c:/TEMP : notify\file2.txt
- file törlés
deleted c:/TEMP : notify\file2.txt
modified c:/TEMP : notify
- file másolása a figyelt könvtárba
created c:/TEMP : notify\alcatraz.101.hdtv-lol.avi
modified c:/TEMP : notify
modified c:/TEMP : notify\alcatraz.101.hdtv-lol.avi
modified c:/TEMP : notify\alcatraz.101.hdtv-lol.avi
- külső librarikat kell futtató környezetnek adni a
-Djava.library.path=
jvm argumentummal - alap file műveletekre komplex értesítés érkezik, ami jó
- alap file műveletekre komplex értesítés érkezik, ami rossz
- java 5
- rekurzívan tud könyvtárakat figyelni
Elég körülményes egy buildelő rendszert ráépíteni, mert a file módosításon kívül igen komplex értesítéseket kapunk. Amire lehet egy kicsit építeni az az, hogy bármi is történik vagy a file vagy egy könyvtár módosul. A gond az, hogy többször is. Ha több fájlról van szó, akkor meg állományonként, ami igen nagy.
Igen részletesen lehet az fájlrendszer értesítéseit elkapni, de pont emiatt nagyon nehéz egy olyan egyszerű funkcionalitást is ráépíteni mint az én kis dokumentum fordításom.
A probléma megoldása lehet az, hogy ha értesülünk az eseményről:
- lekapcsolódunk az eseményekről egy kicsit, elvégre már az első esemény is elegendő.
- Várunk egy kicsit, hogy a folyamatban lévő műveletek be tudjanak fejeződni.
- Visszaállunk figyelésre. A végrehajtandó tevékenység lehet, hogy annyi ideig tart, hogy közben teljesen valid másik file esemény megtörténte is.
- Végrehajtjuk amit akarunk.
A triggerelt esemény végrehajtásának hosszától függően a 3. és 4. esemény fel is cserélhető.
Konkrétan:
Csupaszítsuk le egy kicsit az alapprogramot:
1public class JNotifySample2 { 2 public static void main(String args[]) throws Exception { 3 String path = "c:/TEMP/notify"; 4 int mask = JNotify.FILE_CREATED | 5 JNotify.FILE_DELETED | 6 JNotify.FILE_MODIFIED | 7 JNotify.FILE_RENAMED; 8 boolean watchSubtree = false; 9 JNotify.addWatch(path, mask, watchSubtree, new JNotifyExecutorListener()); 10 System.out.println("Press CTR+C to stop..."); 11 for (; true;) { 12 Thread.sleep(10000); 13 } 14 } 15}
És a listenert is készítsük el:
1package public class JNotifyExecutorListener extends JNotifyAdapter { 2 volatile boolean executing = false; 3 static void p(String s){ 4 System.out.println(s); 5 } 6 @Override 7 public void fileModified(int wd, String rootPath, String name) { 8 p("modification is notified"); 9 if(!name.endsWith(".txt")){ 10 return; 11 } 12 p("executing something? "+executing); 13 if (!executing) { 14 p("start the BatchExecutor thread"); 15 Thread t = new Thread(new BatchExecutor()); 16 t.start(); 17 } 18 p("modification handler method end"); 19 } 20 21 class BatchExecutor implements Runnable { 22 @Override 23 public void run() { 24 p("setting to execution..."); 25 // Indicating that it make no sense to 26 executing = true; 27 p("executing something (BatchExecutor)? "+executing); 28 try { 29 p("sleep a bit..."); 30 Thread.sleep(1 * 1000); // 1 sec 31 } 32 catch (InterruptedException e) { 33 p(e.toString()); 34 return; 35 } 36 finally { 37 p("setting back flag"); 38 // ready to catch the next event 39 executing = false; 40 } 41 p("executing something (BatchExecutor 2)? "+executing); 42 43 try { 44 p("Start command line..."); 45 Runtime.getRuntime().exec("cmd /c Path_to/build.bat "); 46 } 47 catch (IOException e) { 48 e.printStackTrace(); 49 } 50 p("command is ready"); 51 } 52 } 53}
Directory Watcher
- Mi az a Directory Watcher?
- Java directory watcher
- JNotify
- JPathwatch
- Java 7 NIO notification
- Pollozó megoldás
- Groovy directory diff
- Groovy pollozó megoldás