import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
import static java.nio.file.StandardWatchEventKinds.OVERFLOW;
+import static java.util.Objects.requireNonNull;
import java.io.File;
import java.io.IOException;
+import java.lang.ref.Cleaner;
+import java.lang.ref.Cleaner.Cleanable;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Singleton;
+import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.concepts.AbstractRegistration;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
@Singleton
@Component(immediate = true, service = FileWatcher.class)
public final class DefaultFileWatcher extends AbstractRegistration implements FileWatcher {
+ // TODO: this allocates a thread to the cleaning action, which really is a safety net. if we get some centralized
+ // place for low-usage ODL threads we want to use that.
+ private static final Cleaner CLEANER = Cleaner.create();
+
+ private static final class State implements Runnable {
+ final @NonNull WatchService watchService;
+
+ State(final WatchService watchService) {
+ this.watchService = requireNonNull(watchService);
+ }
+
+ @Override
+ public void run() {
+ try {
+ watchService.close();
+ } catch (IOException e) {
+ LOG.warn("Failed to close watch service", e);
+ }
+ }
+ }
+
private static final Logger LOG = LoggerFactory.getLogger(DefaultFileWatcher.class);
//BGPCEP config folder OS agnostic path
private static final Path PATH = Paths.get("etc","opendaylight","bgpcep");
- private final WatchService watchService;
+ private final State state;
+ private final Cleanable cleanable;
public DefaultFileWatcher() throws IOException {
- watchService = FileSystems.getDefault().newWatchService();
- Runtime.getRuntime().addShutdownHook(new Thread(this::close));
+ state = new State(FileSystems.getDefault().newWatchService());
+ cleanable = CLEANER.register(this, state);
}
@Override
@Override
public WatchService getWatchService() {
- return watchService;
+ return state.watchService;
}
@Activate
}
}
- PATH.register(this.watchService, OVERFLOW, ENTRY_CREATE);
+ PATH.register(getWatchService(), OVERFLOW, ENTRY_CREATE);
LOG.info("File Watcher service started");
}
@Override
protected void removeRegistration() {
- try {
- watchService.close();
- } catch (IOException e) {
- LOG.warn("Failed to close watch service", e);
- }
+ cleanable.clean();
LOG.info("File Watcher service stopped");
}
}