@@ -2935,43 +2935,23 @@ public FileSystemWatcher(Directory directory) throws IOException {
29352935 public final void run (){
29362936
29372937 if (File .loadDLL ()){
2938- try {
2939- long osWaitHandle = FileSystemWatcherNative .FindFirstChangeNotification (directory .getPath (), includeSubdirectories , -1 );
2940- this .osHandle = new Long (osWaitHandle );
2941-
2942- FileSystemWatcherNative .FindNextChangeNotification (osWaitHandle );
29432938
2944- //Process events. Note that the ReadDirectoryChangesW method will
2945- //block until the next event comes in.
2946- String event = null ;
2947- while (!terminationRequested && ( event = FileSystemWatcherNative .ReadDirectoryChangesW ()) != null ){
2948- for (String e : event .split ("\n " )) addEvent (e .trim ());
2949- }
29502939
2951- //I have no idea what this block of code does. Probably safe to delete.
2952- if (FileSystemWatcherNative .WaitForSingleObject (osWaitHandle ,
2953- FileSystemWatcherNative .INFINITE ) != FileSystemWatcherNative .WAIT_OBJECT_0 ) {
2954- throw new Exception ("Wait failed while waiting for OS to signal file system event." );
2955- }
2940+ //Generate list of folders to watch. The FileSystemWatcherNative DLL
2941+ //skips events generated within junctions (symlinked folders). As a
2942+ //workaround, we have to create FileWatchers for individual junctions.
2943+ HashSet <Directory > watchFolders = new HashSet <>();
2944+ watchFolders .add (directory );
2945+ for (Directory link : getLinks (directory )){
2946+ watchFolders .add (link );
29562947 }
2957- catch (Exception ex ) {
2958- //nothing can be done here except logging the error.
2959- //Logger.getLogger("FileSystemWatcher").log(Level.WARNING, "Exception encountered.", ex);
2960- }
2961- finally {
2962- if (this .osHandle != null ) {
2963- System .out .println ("Shutting down..." );
2964- try {
2965- FileSystemWatcherNative .FindCloseChangeNotification (this .osHandle .longValue ());
2966- }
2967- catch (Exception ex2 ) {
2968- //nothing can be done here except logging the error.
2969- //Logger.getLogger("FileSystemWatcher").log(Level.WARNING,
2970- //"Unable to close file system watch handle.", ex2);
2971- }
2972- this .osHandle = null ;
2973- }
2948+
2949+
2950+ //Start streaming events for each watch folder
2951+ for (Directory dir : watchFolders ){
2952+ initFileSystemWatcherDLL (dir );
29742953 }
2954+
29752955 }
29762956 else {
29772957 if (javaxt .utils .Java .version >6 && !isWindows && !isMac ){
@@ -3001,6 +2981,89 @@ public final void run(){
30012981 }
30022982
30032983
2984+ //**************************************************************************
2985+ //** getLinks
2986+ //**************************************************************************
2987+ /** Used to find symlinks in a given directory
2988+ */
2989+ private HashSet <Directory > getLinks (Directory directory ){
2990+ HashSet <Directory > links = new HashSet <>();
2991+ java .util .List files = directory .getChildren (true , null , false );
2992+ Object obj ;
2993+ while (true ){
2994+ synchronized (files ) {
2995+ while (files .isEmpty ()) {
2996+ try {
2997+ files .wait ();
2998+ }
2999+ catch (InterruptedException e ) {
3000+ break ;
3001+ }
3002+ }
3003+ obj = files .remove (0 );
3004+ files .notifyAll ();
3005+ }
3006+
3007+ if (obj ==null ){
3008+ break ;
3009+ }
3010+ else {
3011+ if (obj instanceof Directory ){
3012+ Directory dir = (Directory ) obj ;
3013+ if (dir .isLink ()) links .add (dir );
3014+ }
3015+ }
3016+ }
3017+ return links ;
3018+ }
3019+
3020+
3021+ //**************************************************************************
3022+ //** initFileSystemWatcherDLL
3023+ //**************************************************************************
3024+ /** Used to instantiate FileSystemWatcherNative (Windows DLL)
3025+ */
3026+ private void initFileSystemWatcherDLL (Directory dir ){
3027+ try {
3028+ long osWaitHandle = FileSystemWatcherNative .FindFirstChangeNotification (dir .getPath (), includeSubdirectories , -1 );
3029+ this .osHandle = new Long (osWaitHandle );
3030+
3031+ FileSystemWatcherNative .FindNextChangeNotification (osWaitHandle );
3032+
3033+ //Process events. Note that the ReadDirectoryChangesW method will
3034+ //block until the next event comes in.
3035+ String event = null ;
3036+ while (!terminationRequested && ( event = FileSystemWatcherNative .ReadDirectoryChangesW ()) != null ){
3037+ for (String e : event .split ("\n " )) addEvent (e .trim ());
3038+ }
3039+
3040+ //I have no idea what this block of code does. Probably safe to delete.
3041+ if (FileSystemWatcherNative .WaitForSingleObject (osWaitHandle ,
3042+ FileSystemWatcherNative .INFINITE ) != FileSystemWatcherNative .WAIT_OBJECT_0 ) {
3043+ throw new Exception ("Wait failed while waiting for OS to signal file system event." );
3044+ }
3045+ }
3046+ catch (Exception ex ) {
3047+ //nothing can be done here except logging the error.
3048+ //Logger.getLogger("FileSystemWatcher").log(Level.WARNING, "Exception encountered.", ex);
3049+ }
3050+ finally {
3051+ if (this .osHandle != null ) {
3052+ System .out .println ("Shutting down..." );
3053+ try {
3054+ FileSystemWatcherNative .FindCloseChangeNotification (this .osHandle .longValue ());
3055+ }
3056+ catch (Exception ex2 ) {
3057+ //nothing can be done here except logging the error.
3058+ //Logger.getLogger("FileSystemWatcher").log(Level.WARNING,
3059+ //"Unable to close file system watch handle.", ex2);
3060+ }
3061+ this .osHandle = null ;
3062+ }
3063+ }
3064+ }
3065+
3066+
30043067 //**************************************************************************
30053068 //** startPolling
30063069 //**************************************************************************
0 commit comments