use of java.nio.file.WatchEvent in project rxjava-file by davidmoten.
the class OperatorFileTailer method reportNewLines.
private static Func1<Object, Observable<byte[]>> reportNewLines(final File file, final AtomicLong currentPosition, final int maxBytesPerEmission) {
return new Func1<Object, Observable<byte[]>>() {
@Override
public Observable<byte[]> call(Object event) {
// reset current position if file is moved or deleted
if (event instanceof WatchEvent) {
WatchEvent<?> w = (WatchEvent<?>) event;
String kind = w.kind().name();
if (kind.equals(StandardWatchEventKinds.ENTRY_CREATE.name())) {
currentPosition.set(0);
}
}
long length = file.length();
if (length > currentPosition.get()) {
try {
final FileInputStream fis = new FileInputStream(file);
fis.skip(currentPosition.get());
// termination or unsubscription
return Observable.using(new Func0<InputStream>() {
@Override
public InputStream call() {
return fis;
}
}, new Func1<InputStream, Observable<byte[]>>() {
@Override
public Observable<byte[]> call(InputStream t1) {
return Bytes.from(fis, maxBytesPerEmission).doOnNext(new Action1<byte[]>() {
@Override
public void call(byte[] bytes) {
currentPosition.addAndGet(bytes.length);
}
});
}
}, new Action1<InputStream>() {
@Override
public void call(InputStream is) {
try {
is.close();
} catch (IOException e) {
// don't care
}
}
});
} catch (IOException e) {
return Observable.error(e);
}
} else
return Observable.empty();
}
};
}
use of java.nio.file.WatchEvent in project rxjava-file by davidmoten.
the class FileObservableTest method testCreateAndModifyEventsForANonDirectoryFileBlockForever.
@Test
public void testCreateAndModifyEventsForANonDirectoryFileBlockForever() throws InterruptedException, IOException {
File file = new File("target/f");
Observable<WatchEvent<?>> events = FileObservable.from(file).kind(ENTRY_MODIFY).kind(ENTRY_CREATE).events();
checkCreateAndModifyEvents(file, events);
}
use of java.nio.file.WatchEvent in project rxjava-file by davidmoten.
the class FileObservableTest method checkCreateAndModifyEvents.
private void checkCreateAndModifyEvents(File file, Observable<WatchEvent<?>> events) throws InterruptedException, IOException, FileNotFoundException {
file.delete();
final CountDownLatch latch = new CountDownLatch(1);
@SuppressWarnings("unchecked") final List<Kind<?>> eventKinds = Mockito.mock(List.class);
InOrder inOrder = Mockito.inOrder(eventKinds);
final AtomicInteger errorCount = new AtomicInteger(0);
Subscription sub = events.subscribeOn(Schedulers.io()).subscribe(new Observer<WatchEvent<?>>() {
@Override
public void onCompleted() {
System.out.println("completed");
}
@Override
public void onError(Throwable e) {
errorCount.incrementAndGet();
}
@Override
public void onNext(WatchEvent<?> event) {
System.out.println("event=" + event);
eventKinds.add(event.kind());
latch.countDown();
}
});
// sleep long enough for WatchService to start
Thread.sleep(1000);
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file, true);
fos.write("hello there".getBytes());
fos.close();
// give the WatchService time to register the change
Thread.sleep(100);
assertTrue(latch.await(30000, TimeUnit.MILLISECONDS));
inOrder.verify(eventKinds).add(StandardWatchEventKinds.ENTRY_CREATE);
inOrder.verify(eventKinds).add(StandardWatchEventKinds.ENTRY_MODIFY);
inOrder.verifyNoMoreInteractions();
sub.unsubscribe();
Thread.sleep(100);
assertEquals(0, errorCount.get());
}
use of java.nio.file.WatchEvent in project fakereplace by fakereplace.
the class WatchServiceFileSystemWatcher method run.
@Override
public void run() {
while (!stopped) {
try {
final WatchKey key = watchService.take();
if (key != null) {
try {
PathData pathData = pathDataByKey.get(key);
if (pathData != null) {
List<WatchEvent<?>> events = new ArrayList<>(key.pollEvents());
final List<FileChangeEvent> results = new ArrayList<>();
List<WatchEvent<?>> latest;
do {
// we need to wait till nothing has changed in 500ms to make sure we have picked up all the changes
Thread.sleep(WAIT_TIME);
latest = key.pollEvents();
events.addAll(latest);
} while (!latest.isEmpty());
final Set<Path> addedFiles = new HashSet<>();
final Set<Path> deletedFiles = new HashSet<>();
for (WatchEvent<?> event : events) {
Path eventPath = (Path) event.context();
Path targetFile = ((Path) key.watchable()).resolve(eventPath);
FileChangeEvent.Type type;
if (event.kind() == ENTRY_CREATE) {
type = FileChangeEvent.Type.ADDED;
addedFiles.add(targetFile);
if (Files.isDirectory(targetFile)) {
try {
addWatchedDirectory(pathData, targetFile);
} catch (IOException e) {
e.printStackTrace();
}
}
} else if (event.kind() == ENTRY_MODIFY) {
type = FileChangeEvent.Type.MODIFIED;
} else if (event.kind() == ENTRY_DELETE) {
type = FileChangeEvent.Type.REMOVED;
deletedFiles.add(targetFile);
} else {
continue;
}
results.add(new FileChangeEvent(targetFile, type));
}
key.pollEvents().clear();
// now we need to prune the results, to remove duplicates
// e.g. if the file is modified after creation we only want to
// show the create event
final List<FileChangeEvent> newEvents = new ArrayList<>();
Iterator<FileChangeEvent> it = results.iterator();
while (it.hasNext()) {
FileChangeEvent event = it.next();
boolean added = addedFiles.contains(event.getFile());
boolean deleted = deletedFiles.contains(event.getFile());
if (event.getType() == FileChangeEvent.Type.MODIFIED) {
if (added || deleted) {
it.remove();
}
} else if (event.getType() == FileChangeEvent.Type.ADDED) {
if (deleted) {
it.remove();
// if it was both deleted and added it was modified
newEvents.add(new FileChangeEvent(event.getFile(), FileChangeEvent.Type.MODIFIED));
}
} else if (event.getType() == FileChangeEvent.Type.REMOVED) {
if (added) {
it.remove();
}
}
}
results.addAll(newEvents);
if (!results.isEmpty()) {
for (FileChangeCallback callback : pathData.callbacks) {
invokeCallback(callback, results);
}
}
}
} finally {
// if the key is no longer valid remove it from the files list
if (!key.reset()) {
files.remove(key.watchable());
}
}
}
} catch (InterruptedException e) {
// ignore
} catch (ClosedWatchServiceException cwse) {
// @see https://developer.jboss.org/message/911519
break;
}
}
}
use of java.nio.file.WatchEvent in project sirix by sirixdb.
the class FileSystemWatcher method watch.
/**
* Watch the directory for changes.
*
* @param visitor optional visitor
* @param index an index of the directory paths to watch
* @throws IOException if an I/O error occurs
* @throws NullPointerException if {@code pIndex} is {@code null}
*/
public void watch(final Visitor<XdmNodeWriteTrx> visitor, final Map<Path, FileSystemPath> index) throws IOException {
final WatchService watcher = FileSystems.getDefault().newWatchService();
final WatchRecursivelyVisitor fileVisitor = WatchRecursivelyVisitor.getInstance(watcher);
Files.walkFileTree(mPath, fileVisitor);
checkNotNull(index);
for (; mState == State.LOOP; ) {
// Wait for key to be signaled.
WatchKey key;
try {
key = watcher.take();
} catch (InterruptedException x) {
return;
}
final Map<WatchKey, Path> keys = fileVisitor.getKeys();
final Path dir = keys.get(key);
if (dir == null) {
LOGWRAPPER.error("WatchKey not recognized!!");
continue;
}
for (WatchEvent<?> event : key.pollEvents()) {
final WatchEvent.Kind<?> kind = event.kind();
/*
* This key is registered only for ENTRY_CREATE events, but an OVERFLOW event can occur
* regardless if events are lost or discarded.
*/
if (kind == OVERFLOW) {
continue;
}
/*
* The filename is the context of the event. Cast is safe because we registered a path
* instance.
*/
WatchEvent<?> ev = event;
for (int i = 0; i < ev.count(); i++) {
final Path name = (Path) ev.context();
final Path child = dir.resolve(name);
if (kind == ENTRY_CREATE && Files.isDirectory(child, NOFOLLOW_LINKS)) {
Files.walkFileTree(child, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) throws IOException {
checkNotNull(dir);
checkNotNull(attrs);
final WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
keys.put(key, dir);
entryCreated(visitor, index, dir);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(final Path pFile, final BasicFileAttributes pAttrs) throws IOException {
checkNotNull(pFile);
checkNotNull(pAttrs);
entryCreated(visitor, index, pFile);
return FileVisitResult.CONTINUE;
}
});
} else {
processEvent(ev, visitor, index, watcher, child);
}
}
}
/*
* Reset the key -- this step is critical if you want to receive further watch events. If the
* key is no longer valid, the directory is inaccessible so exit the loop.
*/
final boolean valid = key.reset();
if (!valid) {
keys.remove(key);
// All directories are inaccessible.
if (keys.isEmpty()) {
mState = State.NOLOOP;
}
}
}
watcher.close();
}
Aggregations