1

I want to use java 7's WatchService to monitor changes to a directory.
It seems it tries to lock the folder, and will throw an exception if it fails, but does not seem to provide any method of locking it before-hand / checking if it is already locked.

I need to know if a directory is currently being used by another a process or not. Since I can't lock it or open a stream to it (because it's a directory), I'm looking for something more intelligent than trying to modify it and sleeping if failed, or try/catch with sleep.

Ideally, I would like a blocking call until it is available.

EDIT: I can't seem to acquire a FileLock on the folder. When I try to lock the folder, I get "FileNotFoundException (access denied)". Googling suggests you can't use that object on a directory.

registration code:

WatchService watchService = path.getFileSystem().newWatchService()
path.register(watchService,
                    StandardWatchEventKinds.ENTRY_CREATE,
                    StandardWatchEventKinds.ENTRY_MODIFY,
                    StandardWatchEventKinds.ENTRY_DELETE)

Failing scenario:
Let's say I'm listening to a folder f for new creation.
If a sub-folder g is created in it, I want to listen to changes in g. However, if I create a new folder in f (in Windows), this will fail because Windows is locking the folder until a name is given.

Thanks

Gal
  • 5,338
  • 5
  • 33
  • 55
  • why do you need to know if it is being used by another process if all you want is monitoring it for changes? –  Aug 10 '13 at 16:32
  • because the method register (http://docs.oracle.com/javase/7/docs/api/java/nio/file/Path.html#register(java.nio.file.WatchService,java.nio.file.WatchEvent.Kind...)) which registers for changes throws an exception if the directory is being used. – Gal Aug 10 '13 at 16:39
  • @Gal can you post some code? – boxed__l Aug 10 '13 at 16:41
  • I've added some code, and a failing scenario – Gal Aug 10 '13 at 16:44
  • 1
    check this tutorial and compare with your code for differences maybe you will see something: http://docs.oracle.com/javase/tutorial/essential/io/notification.html –  Aug 10 '13 at 16:51
  • @A.J.,Thanks, but this does not address the case where the folder is used by another process when trying to register – Gal Aug 10 '13 at 16:52
  • `The Watch Service API takes advantage of this support[native support for file change notification] where available. However, when a file system does not support this mechanism, the Watch Service will poll the file system, waiting for events.` I think this might be the problem – boxed__l Aug 10 '13 at 16:54
  • @boxed__l, I am able to listen and receive events after registering; the problem is that I cannot register to a folder that is being used by another process. – Gal Aug 10 '13 at 16:56
  • 1
    what is the exception that you are getting ? if it is an error because at the time of notification the folder is not yet named in windows, maybe you catch that error and ignore it (for example on that error check if the name of the file object is not set). most probably that after you finish setting the name in windows, another event will be generated, this time with full name. even better, try not to register if the file name is null or empty in the notification and continue waiting. –  Aug 10 '13 at 17:02
  • @A.J., as I mentioned, the error is that the file is being used by another process.
    it does have a name, but when you create a new folder in windows, it's named "New Folder" and requests that you to rename it before unlocking the folder. Right now I'm using a try catch, but I would prefer something more elegant.
    – Gal Aug 10 '13 at 17:04

2 Answers2

2

Taken from here

File file = new File(fileName);
FileChannel channel = new RandomAccessFile(file, "rw").getChannel();
// Get an exclusive lock on the whole file
FileLock lock = channel.lock();
try {
    lock = channel.tryLock();
    // Ok. You get the lock
} catch (OverlappingFileLockException e) {
    // File is open by someone else
} finally {
    lock.release();
}
Community
  • 1
  • 1
RyPope
  • 2,645
  • 27
  • 51
  • 1
    I've already tried that, but whenever I try to lock the file, I get "FileNotFoundException (access denied)". – Gal Aug 10 '13 at 16:21
2

After all the comments, and since your problem looks particular to windows, I wanted to suggest the following library:

http://jpathwatch.wordpress.com/

if you read in the features, you can see the following:

Changes in subdirectories* (recursive monitoring)

this is what you need. seems it does it for you without you having to register every new directory by hand. it is limited to selected platforms. and when checking that, it seems that is available only in windows !!!! see here: http://jpathwatch.wordpress.com/documentation/features/

a very important thing is the possibility to invalidate when a watched directory becomes unavailable. (using java watch service, it a directory is monitored and gets renamed, you still get events with the old path !!)

I think this library would be the most elegant and will save a lot of coding for you for this case.

  • Thanks, but I was really look to a solution to my original problem, which was to find out if a directory is being used by another process. I've already solved the issue ad-hoc by using try-catch-sleep. – Gal Aug 10 '13 at 19:26