Skip to content

Commit

Permalink
✨ Add support for symlinks in FileWatcher
Browse files Browse the repository at this point in the history
This commit allows using symlinks for SSL certificate hot reloading.
  • Loading branch information
TAKETODAY committed Feb 22, 2025
1 parent ad7f7b2 commit 131b1d4
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2017 - 2024 the original author or authors.
* Copyright 2017 - 2025 the original author or authors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -91,14 +91,26 @@ void watch(Set<Path> paths, Runnable action) {
this.thread = new WatcherThread();
this.thread.start();
}
this.thread.register(new Registration(paths, action));
Set<Path> actualPaths = new HashSet<>();
for (Path path : paths) {
actualPaths.add(resolveSymlinkIfNecessary(path));
}
this.thread.register(new Registration(actualPaths, action));
}
catch (IOException ex) {
throw new UncheckedIOException("Failed to register paths for watching: " + paths, ex);
}
}
}

private static Path resolveSymlinkIfNecessary(Path path) throws IOException {
if (Files.isSymbolicLink(path)) {
Path target = Files.readSymbolicLink(path);
return resolveSymlinkIfNecessary(target);
}
return path;
}

public void destroy() throws IOException {
synchronized(this.lock) {
if (this.thread != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2017 - 2024 the original author or authors.
* Copyright 2017 - 2025 the original author or authors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -94,6 +94,32 @@ void shouldWatchFile(@TempDir Path tempDir) throws Exception {
callback.expectChanges();
}

@Test
void shouldFollowSymlink(@TempDir Path tempDir) throws Exception {
Path realFile = tempDir.resolve("realFile.txt");
Path symLink = tempDir.resolve("symlink.txt");
Files.createFile(realFile);
Files.createSymbolicLink(symLink, realFile);
WaitingCallback callback = new WaitingCallback();
this.fileWatcher.watch(Set.of(symLink), callback);
Files.writeString(realFile, "Some content");
callback.expectChanges();
}

@Test
void shouldFollowSymlinkRecursively(@TempDir Path tempDir) throws Exception {
Path realFile = tempDir.resolve("realFile.txt");
Path symLink = tempDir.resolve("symlink.txt");
Path symLink2 = tempDir.resolve("symlink2.txt");
Files.createFile(realFile);
Files.createSymbolicLink(symLink, symLink2);
Files.createSymbolicLink(symLink2, realFile);
WaitingCallback callback = new WaitingCallback();
this.fileWatcher.watch(Set.of(symLink), callback);
Files.writeString(realFile, "Some content");
callback.expectChanges();
}

@Test
void shouldIgnoreNotWatchedFiles(@TempDir Path tempDir) throws Exception {
Path watchedFile = tempDir.resolve("watched.txt");
Expand Down

0 comments on commit 131b1d4

Please sign in to comment.