Skip to content

Commit 2128da9

Browse files
committed
moved file watcher into NRSDK
1 parent 09633dc commit 2128da9

File tree

2 files changed

+216
-0
lines changed

2 files changed

+216
-0
lines changed
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
package com.neuronrobotics.sdk.util;
2+
3+
/*
4+
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
5+
*
6+
* Redistribution and use in source and binary forms, with or without
7+
* modification, are permitted provided that the following conditions
8+
* are met:
9+
*
10+
* - Redistributions of source code must retain the above copyright
11+
* notice, this list of conditions and the following disclaimer.
12+
*
13+
* - Redistributions in binary form must reproduce the above copyright
14+
* notice, this list of conditions and the following disclaimer in the
15+
* documentation and/or other materials provided with the distribution.
16+
*
17+
* - Neither the name of Oracle nor the names of its
18+
* contributors may be used to endorse or promote products derived
19+
* from this software without specific prior written permission.
20+
*
21+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22+
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23+
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
25+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26+
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27+
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28+
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29+
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30+
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32+
*/
33+
34+
import java.io.File;
35+
import java.io.IOException;
36+
import java.nio.file.*;
37+
38+
import static java.nio.file.StandardWatchEventKinds.*;
39+
import static java.nio.file.LinkOption.*;
40+
41+
import java.nio.file.attribute.*;
42+
import java.io.*;
43+
import java.util.*;
44+
45+
public class FileChangeWatcher extends Thread {
46+
47+
private File fileToWatch;
48+
private boolean run = true;
49+
private final WatchService watcher;
50+
private final Map<WatchKey, Path> keys;
51+
private final boolean recursive;
52+
private ArrayList<IFileChangeListener> listeners = new ArrayList<IFileChangeListener>();
53+
54+
public FileChangeWatcher(File fileToWatch) throws IOException {
55+
this.setFileToWatch(fileToWatch);
56+
setName("File Watcher Thread for " + fileToWatch.getAbsolutePath());
57+
this.watcher = FileSystems.getDefault().newWatchService();
58+
this.keys = new HashMap<WatchKey, Path>();
59+
this.recursive = true;
60+
Path dir = Paths.get(fileToWatch.getParent());
61+
if (recursive) {
62+
System.out.format("Scanning %s ...\n", dir);
63+
registerAll(dir);
64+
System.out.println("Done.");
65+
} else {
66+
register(dir);
67+
}
68+
}
69+
70+
public void addIFileChangeListener(IFileChangeListener l){
71+
if(!listeners.contains(l)){
72+
listeners.add(l);
73+
}
74+
}
75+
76+
public void removeIFileChangeListener(IFileChangeListener l){
77+
if(listeners.contains(l)){
78+
listeners.remove(l);
79+
}
80+
}
81+
82+
@SuppressWarnings("unchecked")
83+
static <T> WatchEvent<T> cast(WatchEvent<?> event) {
84+
return (WatchEvent<T>) event;
85+
}
86+
87+
/**
88+
* Register the given directory with the WatchService
89+
*/
90+
private void register(Path dir) throws IOException {
91+
WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE,ENTRY_MODIFY);
92+
93+
Path prev = keys.get(key);
94+
if (prev == null) {
95+
//System.out.format("register: %s\n", dir);
96+
} else {
97+
if (!dir.equals(prev)) {
98+
//System.out.format("update: %s -> %s\n", prev, dir);
99+
}
100+
}
101+
102+
keys.put(key, dir);
103+
}
104+
105+
/**
106+
* Register the given directory, and all its sub-directories, with the
107+
* WatchService.
108+
*/
109+
private void registerAll(final Path start) throws IOException {
110+
// register directory and sub-directories
111+
Files.walkFileTree(start, new SimpleFileVisitor<Path>() {
112+
@Override
113+
public FileVisitResult preVisitDirectory(Path dir,
114+
BasicFileAttributes attrs) throws IOException {
115+
register(dir);
116+
return FileVisitResult.CONTINUE;
117+
}
118+
});
119+
}
120+
121+
@Override
122+
public void run() {
123+
while (run) {
124+
try {
125+
Thread.sleep(100);
126+
} catch (InterruptedException e) {
127+
// TODO Auto-generated catch block
128+
e.printStackTrace();
129+
}
130+
// wait for key to be signalled
131+
WatchKey key;
132+
try {
133+
key = watcher.take();
134+
} catch (InterruptedException x) {
135+
return;
136+
}
137+
138+
Path dir = keys.get(key);
139+
if (dir == null) {
140+
System.err.println("WatchKey not recognized!!");
141+
continue;
142+
}
143+
144+
for (WatchEvent<?> event : key.pollEvents()) {
145+
WatchEvent.Kind kind = event.kind();
146+
147+
// TBD - provide example of how OVERFLOW event is handled
148+
if (kind == OVERFLOW) {
149+
continue;
150+
}
151+
152+
// Context for directory entry event is the file name of entry
153+
WatchEvent<Path> ev = cast(event);
154+
Path name = ev.context();
155+
Path child = dir.resolve(name);
156+
157+
// print out event
158+
//System.out.format("%s: %s\n", event.kind().name(), child);
159+
for(IFileChangeListener l: listeners){
160+
l.onFileChange(child.toFile(), event);
161+
}
162+
163+
// if directory is created, and watching recursively, then
164+
// register it and its sub-directories
165+
if (recursive && (kind == ENTRY_CREATE)) {
166+
try {
167+
if (Files.isDirectory(child, NOFOLLOW_LINKS)) {
168+
registerAll(child);
169+
}
170+
} catch (IOException x) {
171+
// ignore to keep sample readbale
172+
}
173+
}
174+
}
175+
176+
// reset key and remove from set if directory no longer accessible
177+
boolean valid = key.reset();
178+
if (!valid) {
179+
keys.remove(key);
180+
181+
// all directories are inaccessible
182+
if (keys.isEmpty()) {
183+
break;
184+
}
185+
}
186+
}
187+
}
188+
189+
public File getFileToWatch() {
190+
return fileToWatch;
191+
}
192+
193+
public void setFileToWatch(File fileToWatch) {
194+
this.fileToWatch = fileToWatch;
195+
}
196+
197+
public boolean isRun() {
198+
return run;
199+
}
200+
201+
public void close() {
202+
this.run = false;
203+
204+
}
205+
206+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.neuronrobotics.sdk.util;
2+
3+
import java.io.File;
4+
import java.nio.file.WatchEvent;
5+
6+
public interface IFileChangeListener {
7+
8+
public void onFileChange(File fileThatChanged,WatchEvent event);
9+
10+
}

0 commit comments

Comments
 (0)