Skip to content

Commit 0dc6898

Browse files
committed
nna
1 parent 61d0290 commit 0dc6898

File tree

14 files changed

+413
-55
lines changed

14 files changed

+413
-55
lines changed

common/src/main/java/dev/felnull/fnjl/io/FileWatcher.java

Lines changed: 0 additions & 41 deletions
This file was deleted.

common/src/main/java/dev/felnull/fnjl/io/resource/impl/ResourceEntryImpl.java renamed to common/src/main/java/dev/felnull/fnjl/io/resource/ResourceEntryImpl.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
package dev.felnull.fnjl.io.resource.impl;
1+
package dev.felnull.fnjl.io.resource;
22

3-
import dev.felnull.fnjl.io.resource.ResourceEntry;
43
import dev.felnull.fnjl.util.FNDataUtil;
4+
import org.jetbrains.annotations.ApiStatus;
55
import org.jetbrains.annotations.NotNull;
66

77
import java.io.InputStream;
88
import java.util.Objects;
99

10+
@ApiStatus.Internal
1011
public class ResourceEntryImpl implements ResourceEntry {
1112
private final String name;
1213
private final boolean directory;
@@ -39,7 +40,7 @@ public boolean isDirectory() {
3940

4041
@Override
4142
public InputStream openInputStream() {
42-
if(isDirectory())
43+
if (isDirectory())
4344
throw new RuntimeException("directory");
4445

4546
return FNDataUtil.resourceExtractor(clazz, path);

common/src/main/java/dev/felnull/fnjl/io/resource/impl/package-info.java

Lines changed: 0 additions & 5 deletions
This file was deleted.
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package dev.felnull.fnjl.io.watcher;
2+
3+
import dev.felnull.fnjl.util.FNArrayUtils;
4+
import org.jetbrains.annotations.ApiStatus;
5+
6+
import java.io.IOException;
7+
import java.nio.file.*;
8+
import java.util.ArrayList;
9+
import java.util.List;
10+
import java.util.concurrent.ThreadFactory;
11+
import java.util.stream.Stream;
12+
13+
/**
14+
* ディレクトリ内のファイルツリーの更新等を監視
15+
*
16+
* @author MORIMORI0317
17+
* @since 1.56
18+
*/
19+
@ApiStatus.Internal
20+
public class DirectoryTreeWatcherImpl extends FileSystemWatcherImpl {
21+
private final List<Path> watchingPaths = new ArrayList<>();
22+
private final Path rootPath;
23+
private final boolean flowSymbolic;
24+
private final boolean create;
25+
private final WatchEvent.Kind<?>[] events;
26+
27+
protected DirectoryTreeWatcherImpl(Path rootPath, WatchEventListener watchEventListener, ThreadFactory threadFactory, boolean flowSymbolic, WatchEvent.Kind<?>... events) throws IOException {
28+
super(watchEventListener, threadFactory);
29+
this.rootPath = rootPath;
30+
if (!FNArrayUtils.contains(events, StandardWatchEventKinds.ENTRY_CREATE)) {
31+
events = FNArrayUtils.add(events, StandardWatchEventKinds.ENTRY_CREATE);
32+
create = false;
33+
} else {
34+
create = true;
35+
}
36+
registerFiles(rootPath, flowSymbolic, events);
37+
this.flowSymbolic = flowSymbolic;
38+
this.events = events;
39+
}
40+
41+
@Override
42+
protected void destroy() {
43+
super.destroy();
44+
watchingPaths.clear();
45+
}
46+
47+
public DirectoryTreeWatcherImpl(Path rootPath, WatchEventListener watchEventListener, boolean flowSymbolic, WatchEvent.Kind<?>... events) throws IOException {
48+
super(watchEventListener, rootPath + "-directory-tree-watcher");
49+
this.rootPath = rootPath;
50+
if (!FNArrayUtils.contains(events, StandardWatchEventKinds.ENTRY_CREATE)) {
51+
events = FNArrayUtils.add(events, StandardWatchEventKinds.ENTRY_CREATE);
52+
create = false;
53+
} else {
54+
create = true;
55+
}
56+
registerFiles(rootPath, flowSymbolic, events);
57+
this.flowSymbolic = flowSymbolic;
58+
this.events = events;
59+
}
60+
61+
@Override
62+
protected void onEvent(WatchKey key, WatchEvent<Path> watchEvent, int count) {
63+
if (watchEvent.kind() == StandardWatchEventKinds.ENTRY_CREATE) {
64+
synchronized (watchingPaths) {
65+
Path ap = getPath(key, watchEvent);
66+
if (!watchingPaths.contains(ap) && Files.isDirectory(ap, flowSymbolic ? new LinkOption[0] : new LinkOption[]{LinkOption.NOFOLLOW_LINKS})) {
67+
watchingPaths.add(ap);
68+
try {
69+
watchKeyPath.put(ap.register(watchService, events), ap);
70+
} catch (IOException e) {
71+
throw new RuntimeException(e);
72+
}
73+
}
74+
}
75+
if (!create)
76+
return;
77+
}
78+
79+
super.onEvent(key, watchEvent, count);
80+
}
81+
82+
private void registerFiles(Path path, boolean flowSymbolic, WatchEvent.Kind<?>... events) throws IOException {
83+
try (Stream<Path> stream = Files.walk(path, flowSymbolic ? new FileVisitOption[]{FileVisitOption.FOLLOW_LINKS} : new FileVisitOption[0])) {
84+
stream.forEach(p -> {
85+
if (Files.isDirectory(p, flowSymbolic ? new LinkOption[0] : new LinkOption[]{LinkOption.NOFOLLOW_LINKS})) {
86+
Path pa = p.toAbsolutePath();
87+
watchingPaths.add(pa);
88+
try {
89+
watchKeyPath.put(pa.register(watchService, events), pa);
90+
} catch (IOException e) {
91+
throw new RuntimeException(e);
92+
}
93+
}
94+
});
95+
}
96+
}
97+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package dev.felnull.fnjl.io.watcher;
2+
3+
import org.jetbrains.annotations.ApiStatus;
4+
5+
import java.io.IOException;
6+
import java.nio.file.Path;
7+
import java.nio.file.WatchEvent;
8+
import java.util.concurrent.ThreadFactory;
9+
10+
/**
11+
* ディレクトリ内のファイルの更新等を監視
12+
*
13+
* @author MORIMORI0317
14+
* @since 1.56
15+
*/
16+
@ApiStatus.Internal
17+
public class DirectoryWatcherImpl extends SingleFileSystemWatcherImpl {
18+
protected DirectoryWatcherImpl(Path path, FileSystemWatcher.WatchEventListener watchEventListener, ThreadFactory threadFactory, WatchEvent.Kind<?>... events) throws IOException {
19+
super(path, watchEventListener, threadFactory, events);
20+
}
21+
22+
protected DirectoryWatcherImpl(Path path, FileSystemWatcher.WatchEventListener watchEventListener, WatchEvent.Kind<?>... events) throws IOException {
23+
super(path, watchEventListener, path + "-directory-watcher", events);
24+
}
25+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package dev.felnull.fnjl.io.watcher;
2+
3+
import org.jetbrains.annotations.NotNull;
4+
5+
import java.io.IOException;
6+
import java.nio.file.Path;
7+
import java.nio.file.WatchEvent;
8+
import java.util.concurrent.ThreadFactory;
9+
10+
public interface FileSystemWatcher {
11+
/**
12+
* ファイルを監視
13+
*
14+
* @param path 監視対象パス
15+
* @param watchEventListener 監視リスナー
16+
* @param threadFactory 監視用スレッドのファクトリー
17+
* @param events 監視イベントの類 StandardWatchEventKinds.ENTRY_MODIFYなど
18+
* @return FileWatcher
19+
* @throws IOException 例外
20+
*/
21+
@NotNull
22+
static FileSystemWatcher newFileWatcher(@NotNull Path path, @NotNull FileSystemWatcher.WatchEventListener watchEventListener, @NotNull ThreadFactory threadFactory, @NotNull WatchEvent.Kind<?>... events) throws IOException {
23+
return new FileWatcherImpl(path, watchEventListener, threadFactory, events);
24+
}
25+
26+
/**
27+
* ファイルを監視
28+
*
29+
* @param path 監視対象パス
30+
* @param watchEventListener 監視リスナー
31+
* @param events 監視イベントの類 StandardWatchEventKinds.ENTRY_MODIFYなど
32+
* @return FileWatcher
33+
* @throws IOException 例外
34+
*/
35+
@NotNull
36+
static FileSystemWatcher newFileWatcher(@NotNull Path path, @NotNull FileSystemWatcher.WatchEventListener watchEventListener, @NotNull WatchEvent.Kind<?>... events) throws IOException {
37+
return new FileWatcherImpl(path, watchEventListener, events);
38+
}
39+
40+
@NotNull
41+
static FileSystemWatcher newDirectoryWatcher(@NotNull Path path, @NotNull FileSystemWatcher.WatchEventListener watchEventListener, @NotNull ThreadFactory threadFactory, @NotNull WatchEvent.Kind<?>... events) throws IOException {
42+
return new DirectoryWatcherImpl(path, watchEventListener, threadFactory, events);
43+
}
44+
45+
@NotNull
46+
static FileSystemWatcher newDirectoryWatcher(@NotNull Path path, @NotNull FileSystemWatcher.WatchEventListener watchEventListener, @NotNull WatchEvent.Kind<?>... events) throws IOException {
47+
return new DirectoryWatcherImpl(path, watchEventListener, events);
48+
}
49+
50+
void stop();
51+
52+
interface WatchEventListener {
53+
void onWatchEvent(@NotNull WatchEvent<Path> watchEvent, @NotNull Path path);
54+
}
55+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package dev.felnull.fnjl.io.watcher;
2+
3+
import org.jetbrains.annotations.ApiStatus;
4+
5+
import java.io.IOException;
6+
import java.nio.file.*;
7+
import java.util.HashMap;
8+
import java.util.Map;
9+
import java.util.concurrent.ThreadFactory;
10+
11+
@ApiStatus.Internal
12+
public abstract class FileSystemWatcherImpl implements FileSystemWatcher {
13+
protected final WatchService watchService;
14+
protected final FileSystemWatcher.WatchEventListener watchEventListener;
15+
protected final Map<WatchKey, Path> watchKeyPath = new HashMap<>();
16+
private final Thread thread;
17+
18+
protected FileSystemWatcherImpl(FileSystemWatcher.WatchEventListener watchEventListener, ThreadFactory threadFactory) throws IOException {
19+
this.watchService = FileSystems.getDefault().newWatchService();
20+
this.watchEventListener = watchEventListener;
21+
this.thread = threadFactory.newThread(this::run);
22+
this.thread.start();
23+
}
24+
25+
protected FileSystemWatcherImpl(FileSystemWatcher.WatchEventListener watchEventListener, String name) throws IOException {
26+
this(watchEventListener, defaultThreadFactory(name));
27+
}
28+
29+
private void run() {
30+
try {
31+
loop();
32+
} finally {
33+
destroy();
34+
}
35+
}
36+
37+
private void loop() {
38+
while (true) {
39+
try {
40+
WatchKey take = watchService.take();
41+
for (WatchEvent<?> pollEvent : take.pollEvents()) {
42+
Object co = pollEvent.context();
43+
if (co instanceof Path)
44+
onEvent(take, (WatchEvent<Path>) pollEvent, pollEvent.count());
45+
}
46+
take.reset();
47+
} catch (InterruptedException ignored) {
48+
}
49+
}
50+
}
51+
52+
@Override
53+
public void stop() {
54+
thread.interrupt();
55+
}
56+
57+
protected void destroy() {
58+
watchKeyPath.clear();
59+
try {
60+
watchService.close();
61+
} catch (IOException e) {
62+
throw new RuntimeException(e);
63+
}
64+
}
65+
66+
protected void onEvent(WatchKey key, WatchEvent<Path> watchEvent, int count) {
67+
this.watchEventListener.onWatchEvent(watchEvent, getPath(key, watchEvent));
68+
}
69+
70+
private static ThreadFactory defaultThreadFactory(String name) {
71+
return r -> {
72+
Thread t = new Thread(r);
73+
t.setDaemon(true);
74+
t.setName(name);
75+
return t;
76+
};
77+
}
78+
79+
protected Path getPath(WatchKey key, WatchEvent<Path> watchEvent) {
80+
return watchKeyPath.get(key).resolve(watchEvent.context().toString());
81+
}
82+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package dev.felnull.fnjl.io.watcher;
2+
3+
import org.jetbrains.annotations.ApiStatus;
4+
5+
import java.io.IOException;
6+
import java.nio.file.Path;
7+
import java.nio.file.WatchEvent;
8+
import java.nio.file.WatchKey;
9+
import java.util.concurrent.ThreadFactory;
10+
11+
/**
12+
* ファイル更新等を監視
13+
*
14+
* @author MORIMORI0317
15+
* @since 1.56
16+
*/
17+
@ApiStatus.Internal
18+
public class FileWatcherImpl extends SingleFileSystemWatcherImpl {
19+
private final Path targetPath;
20+
21+
protected FileWatcherImpl(Path path, FileSystemWatcher.WatchEventListener watchEventListener, ThreadFactory threadFactory, WatchEvent.Kind<?>... events) throws IOException {
22+
super(path.getParent(), watchEventListener, threadFactory, events);
23+
this.targetPath = path;
24+
}
25+
26+
protected FileWatcherImpl(Path path, FileSystemWatcher.WatchEventListener watchEventListener, WatchEvent.Kind<?>... events) throws IOException {
27+
super(path.getParent(), watchEventListener, path + "file-watcher", events);
28+
this.targetPath = path;
29+
}
30+
31+
@Override
32+
protected void onEvent(WatchKey key, WatchEvent<Path> watchEvent, int count) {
33+
if (!targetPath.getFileName().equals(watchEvent.context().getFileName())) return;
34+
super.onEvent(key, watchEvent, count);
35+
}
36+
}

common/src/main/java/dev/felnull/fnjl/io/FolderWatcher.java renamed to common/src/main/java/dev/felnull/fnjl/io/watcher/FolderWatcher.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package dev.felnull.fnjl.io;
1+
package dev.felnull.fnjl.io.watcher;
22

33
import java.io.IOException;
44
import java.nio.file.*;

0 commit comments

Comments
 (0)