+
+ private class Log4jConfWatcherThread extends Thread {
+ private Path log4jConfigurationPath;
+
+ public Log4jConfWatcherThread(Path log4jConfigurationPath) {
+ super("Log4j Configuration Watcher");
+ try {
+ this.log4jConfigurationPath = log4jConfigurationPath.toRealPath();
+ } catch (IOException e) {
+ this.log4jConfigurationPath = log4jConfigurationPath.toAbsolutePath();
+ stdOut("Cannot determine real path for " + log4jConfigurationPath + ": " + e.getMessage());
+ }
+ }
+
+ public void run() {
+ Path parentDir = log4jConfigurationPath.getParent();
+ try (final WatchService watchService = FileSystems.getDefault().newWatchService()) {
+ parentDir.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);
+ WatchKey wk;
+ watching: while ((wk = watchService.take()) != null) {
+ for (WatchEvent<?> event : wk.pollEvents()) {
+ final Path changed = (Path) event.context();
+ if (log4jConfigurationPath.equals(parentDir.resolve(changed))) {
+ if (isInternalDebugEnabled())
+ debug(log4jConfigurationPath + " has changed, reloading.");
+ PropertyConfigurator.configure(log4jConfigurationPath.toUri().toURL());
+ }
+ }
+ // reset the key
+ boolean valid = wk.reset();
+ if (!valid) {
+ break watching;
+ }
+ }
+ } catch (IOException | InterruptedException e) {
+ stdErr("Log4j configuration watcher failed: " + e.getMessage());
+ }
+ }
+ }