Skip to content

Commit 1cb2a2b

Browse files
committed
Merge pull request #3 from robertroeser/master
cleaned up api
2 parents c6c0ba9 + 6d8cd80 commit 1cb2a2b

5 files changed

Lines changed: 169 additions & 87 deletions

File tree

‎CONTRIBUTING.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ If you are adding a new file it should have a header like this:
1414

1515
```
1616
/**
17-
* Copyright 2014 Netflix, Inc.
17+
* Copyright 2015 Netflix, Inc.
1818
*
1919
* Licensed under the Apache License, Version 2.0 (the "License");
2020
* you may not use this file except in compliance with the License.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* Copyright 2015 Netflix, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
5+
* compliance with the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is
10+
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
11+
* the License for the specific language governing permissions and limitations under the License.
12+
*/
13+
package rx.fileutils;
14+
15+
import java.nio.file.Path;
16+
import java.nio.file.StandardWatchEventKinds;
17+
import java.nio.file.WatchEvent;
18+
19+
public class FileSystemEvent {
20+
private FileSystemEventKind fileSystemEventKind;
21+
22+
private Path path;
23+
24+
FileSystemEvent(WatchEvent event) {
25+
WatchEvent.Kind kind = event.kind();
26+
if (StandardWatchEventKinds.OVERFLOW != kind) {
27+
this.path = (Path) event.context();
28+
}
29+
30+
this.fileSystemEventKind = FileSystemEventKind.toFileSystemEventKind(kind);
31+
}
32+
33+
public FileSystemEventKind getFileSystemEventKind() {
34+
return fileSystemEventKind;
35+
}
36+
37+
public Path getPath() {
38+
return path;
39+
}
40+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package rx.fileutils;
2+
3+
import java.nio.file.StandardWatchEventKinds;
4+
import java.nio.file.WatchEvent;
5+
import java.util.Arrays;
6+
import java.util.stream.Collectors;
7+
8+
/**
9+
* Created by rroeser on 7/17/15.
10+
*/
11+
public enum FileSystemEventKind {
12+
OVERFLOW,
13+
ENTRY_CREATE,
14+
ENTRY_DELETE,
15+
ENTRY_MODIFY;
16+
17+
static WatchEvent.Kind<?> toWatchEventKind(FileSystemEventKind fileSystemEventKind) {
18+
WatchEvent.Kind kind = null;
19+
20+
switch (fileSystemEventKind) {
21+
case OVERFLOW:
22+
kind = StandardWatchEventKinds.OVERFLOW;
23+
break;
24+
case ENTRY_CREATE:
25+
kind = StandardWatchEventKinds.ENTRY_CREATE;
26+
break;
27+
case ENTRY_DELETE:
28+
kind = StandardWatchEventKinds.ENTRY_DELETE;
29+
break;
30+
case ENTRY_MODIFY:
31+
kind = StandardWatchEventKinds.ENTRY_MODIFY;
32+
break;
33+
}
34+
35+
return kind;
36+
}
37+
38+
static WatchEvent.Kind<?>[] toWatchEventKinds(FileSystemEventKind... fileSystemEventKinds) {
39+
return Arrays
40+
.asList(fileSystemEventKinds)
41+
.stream()
42+
.map(FileSystemEventKind::toWatchEventKind)
43+
.collect(Collectors.toList())
44+
.toArray(new WatchEvent.Kind<?>[fileSystemEventKinds.length]);
45+
}
46+
47+
static FileSystemEventKind toFileSystemEventKind(WatchEvent.Kind<?> watchEventKind) {
48+
FileSystemEventKind kind = null;
49+
50+
if (watchEventKind == StandardWatchEventKinds.OVERFLOW) {
51+
kind = OVERFLOW;
52+
} else if (watchEventKind == StandardWatchEventKinds.ENTRY_CREATE) {
53+
kind = ENTRY_CREATE;
54+
} else if (watchEventKind == StandardWatchEventKinds.ENTRY_DELETE) {
55+
kind = ENTRY_DELETE;
56+
} else if (watchEventKind == StandardWatchEventKinds.ENTRY_MODIFY) {
57+
kind = ENTRY_MODIFY;
58+
}
59+
60+
return kind;
61+
}
62+
63+
}

src/main/java/rx/fileutils/WatcherEventObservable.java renamed to src/main/java/rx/fileutils/FileSystemWatcher.java

Lines changed: 43 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,7 @@
2929
import java.util.HashMap;
3030
import java.util.Map;
3131

32-
import static java.nio.file.StandardWatchEventKinds.OVERFLOW;
33-
34-
/**
35-
* Created by rroeser on 7/8/15.
36-
*/
37-
public class WatcherEventObservable extends Observable<WatchEvent<?>> {
32+
public final class FileSystemWatcher {
3833

3934
static final boolean IS_MAC;
4035

@@ -43,39 +38,32 @@ public class WatcherEventObservable extends Observable<WatchEvent<?>> {
4338
IS_MAC = os.contains("mac");
4439
}
4540

46-
protected WatcherEventOnSubscribe watcherEventOnSubscribe;
41+
private FileSystemWatcher() {}
4742

48-
private static class WatcherEventOnSubscribe implements OnSubscribe<WatchEvent<?>> {
43+
private static class FileSystemEventOnSubscribe implements Observable.OnSubscribe<FileSystemEvent> {
4944
private WatchService watcher;
5045

5146
private Scheduler scheduler;
5247

5348
private volatile boolean close = false;
5449

55-
public void addPath(Path path, WatchEvent.Kind... kinds) throws Exception {
56-
if (IS_MAC) {
57-
final WatchableFile watchableFile = new WatchableFile(path);
58-
watchableFile.register(watcher, kinds);
59-
} else {
60-
path.register(watcher, kinds, SensitivityWatchEventModifier.HIGH);
61-
}
62-
}
63-
64-
public WatcherEventOnSubscribe(Map<Path, WatchEvent.Kind[]> paths, Scheduler scheduler) {
50+
public FileSystemEventOnSubscribe(Map<Path, FileSystemEventKind[]> paths, Scheduler scheduler) {
6551
try {
6652
if (IS_MAC) {
6753
this.watcher = MacOSXWatchServiceFactory.newWatchService();
6854

6955
for (Path path : paths.keySet()) {
7056
final WatchableFile watchableFile = new WatchableFile(path);
71-
watchableFile.register(watcher, paths.get(path));
57+
FileSystemEventKind[] kinds = paths.get(path);
58+
watchableFile.register(watcher, FileSystemEventKind.toWatchEventKinds(kinds));
7259
}
7360
}
7461
else {
7562
this.watcher = FileSystems.getDefault().newWatchService();
7663

7764
for (Path path : paths.keySet()) {
78-
path.register(watcher, paths.get(path), SensitivityWatchEventModifier.HIGH);
65+
FileSystemEventKind[] kinds = paths.get(path);
66+
path.register(watcher, FileSystemEventKind.toWatchEventKinds(kinds), SensitivityWatchEventModifier.HIGH);
7967
}
8068
}
8169
this.scheduler = scheduler;
@@ -85,8 +73,7 @@ public WatcherEventOnSubscribe(Map<Path, WatchEvent.Kind[]> paths, Scheduler sch
8573
}
8674

8775
@Override
88-
public void call(Subscriber<? super WatchEvent<?>> subscriber) {
89-
76+
public void call(Subscriber<? super FileSystemEvent> subscriber) {
9077
Scheduler.Worker worker = scheduler.createWorker();
9178
subscriber.add(worker);
9279

@@ -99,14 +86,10 @@ public void call(Subscriber<? super WatchEvent<?>> subscriber) {
9986
}
10087

10188
for (WatchEvent<?> event : key.pollEvents()) {
102-
WatchEvent.Kind<?> kind = event.kind();
103-
104-
if (kind == OVERFLOW) {
105-
continue;
106-
} else {
107-
subscriber.onNext(event);
108-
}
89+
FileSystemEvent fileSystemEvent = new FileSystemEvent(event);
90+
subscriber.onNext(fileSystemEvent);
10991
}
92+
11093
if (!key.reset()) {
11194
close();
11295
}
@@ -127,64 +110,53 @@ public void close() {
127110
} catch (Exception e) {}
128111
}
129112

130-
public boolean isClosed() {
131-
return close;
132-
}
133113
}
134114

135-
protected WatcherEventObservable(WatcherEventOnSubscribe subscribe) {
136-
super(subscribe);
137-
138-
this.watcherEventOnSubscribe = subscribe;
139-
}
115+
public static class Builder {
116+
private Map<Path, FileSystemEventKind[]> paths = new HashMap<>();
140117

141-
public static WatcherEventObservable create(Map<Path, WatchEvent.Kind[]> paths, Scheduler scheduler) {
142-
try {
143-
WatcherEventOnSubscribe watcherEventOnSubscribe
144-
= new WatcherEventOnSubscribe(paths, scheduler);
118+
private Scheduler scheduler = Schedulers.newThread();
145119

146-
WatcherEventObservable watcherEventObservable
147-
= new WatcherEventObservable(watcherEventOnSubscribe);
120+
Builder() {}
148121

149-
watcherEventObservable
150-
.doOnSubscribe(() -> {
151-
})
152-
.doOnUnsubscribe(watcherEventOnSubscribe::close);
122+
public Builder addPath(Path path, FileSystemEventKind... kinds) {
123+
paths.put(path, kinds);
153124

154-
return watcherEventObservable;
155-
} catch (Exception e) {
156-
throw new RuntimeException(e);
125+
return this;
157126
}
158-
}
159-
160-
public static WatcherEventObservable create(Map<Path, WatchEvent.Kind[]> paths) {
161-
return create(paths, Schedulers.newThread());
162-
}
163127

164-
public static WatcherEventObservable create(Path path, WatchEvent.Kind... kinds) {
165-
Map<Path, WatchEvent.Kind[]> paths = new HashMap<>();
128+
public Builder addPaths(Map<Path, FileSystemEventKind[]> paths) {
129+
this.paths.putAll(paths);
166130

167-
paths.put(path, kinds);
131+
return this;
132+
}
168133

169-
return create(paths);
170-
}
134+
public Builder withScheduler(Scheduler scheduler) {
135+
this.scheduler = scheduler;
171136

172-
public WatcherEventObservable addPath(Path path, WatchEvent.Kind... kinds) {
173-
try {
174-
watcherEventOnSubscribe.addPath(path, kinds);
175-
} catch (Exception e) {
176-
throw new RuntimeException(e);
137+
return this;
177138
}
178139

179-
return this;
180-
}
140+
public Observable<FileSystemEvent> build() {
141+
try {
142+
FileSystemEventOnSubscribe fileSystemEventOnSubscribe
143+
= new FileSystemEventOnSubscribe(paths, scheduler);
144+
145+
Observable<FileSystemEvent> fileSystemEventObservable
146+
= Observable.create(fileSystemEventOnSubscribe);
147+
148+
fileSystemEventObservable
149+
.doOnUnsubscribe(fileSystemEventOnSubscribe::close);
181150

151+
return fileSystemEventObservable;
152+
} catch (Exception e) {
153+
throw new RuntimeException(e);
154+
}
155+
}
182156

183-
public void close() {
184-
watcherEventOnSubscribe.close();
185157
}
186158

187-
public boolean isClosed() {
188-
return watcherEventOnSubscribe.isClosed();
159+
public static Builder newBuilder() {
160+
return new Builder();
189161
}
190162
}

src/test/java/rx/fileutils/WatcherEventOnSubscribeTest.java renamed to src/test/java/rx/fileutils/FileSystemEventOnSubscribeTest.java

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,20 @@
1616
import org.junit.Assert;
1717
import org.junit.Before;
1818
import org.junit.Test;
19+
import rx.Observable;
20+
import rx.Subscription;
1921
import rx.observers.TestSubscriber;
22+
import rx.schedulers.Schedulers;
2023

2124
import java.io.File;
2225
import java.io.FileWriter;
2326
import java.nio.file.Path;
24-
import java.nio.file.StandardWatchEventKinds;
25-
import java.nio.file.WatchEvent;
2627
import java.util.HashMap;
28+
import java.util.Map;
2729
import java.util.UUID;
2830
import java.util.concurrent.CountDownLatch;
2931

30-
public class WatcherEventOnSubscribeTest {
32+
public class FileSystemEventOnSubscribeTest {
3133
private static final String testDirPath = "/tmp/testDirPath-" + UUID.randomUUID().toString();
3234

3335
private static File dir;
@@ -61,28 +63,33 @@ public static void deleteRecursive(File path){
6163

6264
@Test(timeout = 15_000)
6365
public void testWatchForFileCreateAndModify() throws Exception {
64-
HashMap<Path, WatchEvent.Kind[]> paths = new HashMap<>();
66+
Map<Path, FileSystemEventKind[]> paths = new HashMap<>();
6567

66-
paths.put(dir.toPath(), new WatchEvent.Kind[] {
67-
StandardWatchEventKinds.ENTRY_CREATE,
68-
StandardWatchEventKinds.ENTRY_MODIFY } );
68+
paths.put(dir.toPath(), new FileSystemEventKind[] {
69+
FileSystemEventKind.ENTRY_CREATE,
70+
FileSystemEventKind.ENTRY_MODIFY } );
6971

70-
WatcherEventObservable watcherEventObservable = WatcherEventObservable.create(paths);
72+
Observable<FileSystemEvent> fileSystemWatcher =
73+
FileSystemWatcher
74+
.newBuilder()
75+
.addPaths(paths)
76+
.withScheduler(Schedulers.io())
77+
.build();
7178

7279
TestSubscriber subscriber = new TestSubscriber();
7380

74-
CountDownLatch latch = new CountDownLatch(WatcherEventObservable.IS_MAC ? 3 : 2);
75-
watcherEventObservable
81+
CountDownLatch latch = new CountDownLatch(FileSystemWatcher.IS_MAC ? 3 : 2);
82+
Subscription subscribe = fileSystemWatcher
7683
.doOnNext(a -> {
7784
latch.countDown();
78-
WatchEvent.Kind<?> kind = a.kind();
85+
FileSystemEventKind kind = a.getFileSystemEventKind();
7986

8087
System.out.println("Got an event for " + kind.name());
8188

8289
})
8390
.subscribe(subscriber);
8491

85-
boolean closed = watcherEventObservable.isClosed();
92+
boolean closed = subscribe.isUnsubscribed();
8693

8794
Assert.assertFalse(closed);
8895

@@ -98,13 +105,13 @@ public void testWatchForFileCreateAndModify() throws Exception {
98105

99106
latch.await();
100107

101-
watcherEventObservable.close();
108+
subscribe.unsubscribe();
102109

103-
closed = watcherEventObservable.isClosed();
110+
closed = subscribe.isUnsubscribed();
104111

105112
Assert.assertTrue(closed);
106113

107-
if (WatcherEventObservable.IS_MAC) {
114+
if (FileSystemWatcher.IS_MAC) {
108115
subscriber.assertValueCount(3);
109116
} else {
110117
subscriber.assertValueCount(2);

0 commit comments

Comments
 (0)