Table of Contents
Entities as well as the entire file system, may be configured to be Observable for events. Clients that want to receive notification of entity updates, register a listener of the type EntityObserver on the entity or on the file system object. The listener will then receive all EntityEvent:s that involve the observed entity, or for a file system listener, all events in that file system.
Every event has a sender which is the entity that generated the event.
Example 9.1. Registering an observer on a directory
// d is a directory. Register a simple observer on it. d.addObserver( new EntityObserver() { public void update(EntityEvent<?> ee) { if (ee instanceof ChildEntityAddedEvent) { System.out.println("Child entity " + ((ChildEntityAddedEvent) ee).getChildEntity() + " added to directory " + ee.getSender()); } else { System.out.println("Event: " + ee); } } }); Directories.newFile(d, "f1");
The observer will print out that the file f1
was
added.
Table 9.1. EntityEvent types
EntityEvent | Description |
---|---|
ChildEntityAddedEvent | An entity has been added to a Directory. |
ChildEntityDisappearedEvent | The EntityValidityControlStrategy has detected that an entity has disappeared from a Directory. The entity was not removed through using the file system's methods. It might have been removed by another process altogether. |
ChildEntityModifiedEvent | An entity in a Directory has been modified in a way that updated its last modification time property. For modified files, this event is generated when the client closes its stream or channel on the file. |
ChildEntityRemovedEvent | A child entity has been removed from a Directory, either by deleting it or moving it to another directory. |
ChildEntityRenamedEvent | An entity in a Directory has been renamed within the same directory. |
EntityDeletedEvent | The entity has been deleted. |
EntityDisappearedEvent | The FileSystem's EntityValidityControlStrategy
has detected that the entity has disappeared. It was not removed through using the file
system's methods. The entity is not valid (its isValid
method will return false ) when the observer
receives the event. |
EntityModifiedEvent | The entity was modified in a way that updated its latest modification time. For modified files, this event is generated when the client closes its stream or channel on the file. |
The EntityObserver's update
method is called in the thread that generated the event. This means that, if the
file system is locking, the calling thread is holding a write lock on the
event's sender when update
is called. It also
means that update
should return quickly. If
there is a lot of work to do in response to an event, use an
Executor to schedule the work for execution in another thread.
The following examples show which events that are generated when the file system is modified in different ways.
Example 9.2. Adding a file to a directory
Assume the following file system layout:
+ d (directory) + d1 (directory)
Adding a file f
to the directory
d1
will generate the following events, in this
order:
A ChildEntityAddedEvent for
d1
.
A EntityModifiedEvent for
d1
.
A ChildEntityModifiedEvent for
d
.
A NewEntityEvent for
f
.
Example 9.3. Modifying a file
Assuming the file system layout from the previous example, if the file
f
is opened and written to, when it is closed,
the following events will be generated, in this order:
A EntityModifiedEvent for
f
.
A ChildEntityModifiedEvent for
d1
.
(If f
just had been opened and closed, without
any data being written to it, the same events had been generated anyway.)
Example 9.4. Moving an entity
Assume the following file system layout:
+ d (directory) + d1 (directory) | + d10 (directory) | + f (file) + d2 (directory) + d20 (directory)
Moving the file f
from
d10
to d20
will generate the following events, in this order:
A ChildEntityRemovedEvent for
d10
.
A EntityModifiedEvent for
d10
.
A ChildEntityModifiedEvent for
d1
.
A ChildEntityAddedEvent for
d20
.
A EntityModifiedEvent for
d20
.
A ChildEntityModifiedEvent for
d2
.
A EntityRenamedEvent for
f
.
For directories that can be modified by someone that does not use its file system's methods, for instance by another process, a DirectoryMonitorer can be used to detect updates. Generally, it is not recommended to let entities be modified without using their entity objects, but in some cases, such as when monitoring a directory for incoming files, it can be useful. It requires a good EntityValidityControlStrategy for the file system, though.
Example 9.5. Using a polling directory monitorer to watch for incoming XML files
// d is the directory to monitor. // Create a view that only shows XML files. DirectoryView dv = d.newView(new EFileNameExtensionFilter("xml")); // Create a timer that will tell the monitorer when to scan the directory // for updates. Any old Observable should work; the monitorer will // scan its directory every time the Observable generates an event. // Scan every minute. TimerTicker tt = new TimerTicker(60000); // Create a polling monitorer on the directory view. PollingDirectoryMonitorer mon = new PollingDirectoryMonitorer(dv, tt); // Register an observer on the monitorer mon.addObserver(new EntityObserver() { public void update(EntityEvent ee) { if (ee instanceof ChildEntitiesAddedEvent) { System.out.println("New child entities: " + ee); } } }); // Start the monitorer mon.start(); // Start the timer ticker. tt.start(); // This will generate an event sometime in the next minute Directories.newFile(d, "foo.xml"); // This will not Directories.newFile(d, "bar.txt"); // Neither will this Directories.newDirectory(d, "baz.xml"); // But this will new File( ECFileResolvableUtil.getFileObject(d) + File.separator + "doh.xml").createNewFile();