/*
* Copyright 2016 the original author or authors.
*
* This file is part of HotswapAgent.
*
* HotswapAgent is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 2 of the License, or (at your
* option) any later version.
*
* HotswapAgent is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with HotswapAgent. If not, see http://www.gnu.org/licenses/.
*/
package org.hotswap.agent.watch.nio;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
/**
* <p>
* NIO2 watcher implementation for systems which support
* ExtendedWatchEventModifier.FILE_TREE (windows)
* </p>
* <p>
* Java 7 (NIO2) watch a directory (or tree) for changes to files.
* </p>
*
* @author alpapad@gmail.com
*/
public class TreeWatcherNIO extends AbstractNIO2Watcher {
private final static WatchEvent.Modifier HIGH;
private final static WatchEvent.Modifier FILE_TREE;
private final static WatchEvent.Modifier[] MODIFIERS;
static {
// try to set high sensitivity
HIGH = getWatchEventModifier("com.sun.nio.file.SensitivityWatchEventModifier","HIGH");
// try to set file tree modifier
FILE_TREE = getWatchEventModifier("com.sun.nio.file.ExtendedWatchEventModifier", "FILE_TREE");
if(FILE_TREE != null) {
MODIFIERS = new WatchEvent.Modifier[] { FILE_TREE, HIGH };
} else {
MODIFIERS = new WatchEvent.Modifier[] { HIGH };
}
}
/**
* Instantiates a new tree watcher nio.
*
* @throws IOException Signals that an I/O exception has occurred.
*/
public TreeWatcherNIO() throws IOException {
super();
}
/**
* Register the given directory with the WatchService.
*
* @param watched the watched path
* @param target the target path (could be different than watched)
* @throws IOException Signals that an I/O exception has occurred.
*/
private void register(Path watched, Path target) throws IOException {
for(PathPair p: keys.values()) {
// This may NOT be correct for all cases (ensure resolve will work!)
if(p.isWatching(target)) {
LOGGER.debug("Path {} watched via {}", target, p.getWatched());
return;
}
}
if (FILE_TREE == null) {
LOGGER.debug("WATCHING:ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY - high} {}", watched);
} else {
LOGGER.debug("WATCHING: ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY - fileTree,high {}", watched);
}
final WatchKey key = watched.register(watcher, KINDS, MODIFIERS);
keys.put(key, new PathPair(target, watched));
}
/**
* Register the given directory, with the
* WatchService. Sub-directories are automatically watched (filesystem supported)
*
* @param watched the watched
* @param target the target
* @throws IOException Signals that an I/O exception has occurred.
*/
protected void registerAll(Path watched, Path target) throws IOException {
if(watched == null){
watched = target.getParent();
}
LOGGER.info("Registering directory target {} via watched: {}", target, watched);
register(watched, target);
}
}