diff options
| author | Szymon Szukalski <szymon.szukalski@gmail.com> | 2012-10-03 10:45:23 +1000 |
|---|---|---|
| committer | Szymon Szukalski <szymon.szukalski@gmail.com> | 2012-10-03 10:45:23 +1000 |
| commit | 6ddaaf8555d6b94684d061289249cac67c6eb09f (patch) | |
| tree | ab4041586a70dcd1140cb32263c71354c2901e2b /src/main/java | |
| parent | 9c632725afb73bbf0966e52ca50c6d66c12d853b (diff) | |
Added example of SimpleFileVisitor usage
Diffstat (limited to 'src/main/java')
5 files changed, 186 insertions, 19 deletions
diff --git a/src/main/java/io/skas/melbjvm/nio2/App.java b/src/main/java/io/skas/melbjvm/nio2/App.java index a586247..f6b986a 100644 --- a/src/main/java/io/skas/melbjvm/nio2/App.java +++ b/src/main/java/io/skas/melbjvm/nio2/App.java @@ -4,6 +4,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.LinkOption; import java.nio.file.Path; import java.nio.file.Paths; @@ -16,20 +18,28 @@ public class App { public static void main(String[] args) throws IOException { - final Path path = Paths.get("/tmp", "doit"); + final Path path = Paths.get("/tmp", "monkeys"); - Nio2MetaDataLoggingUtils.logFileStoreAttributes(path); - Nio2MetaDataLoggingUtils.logBasicFileAttributes(path); - Nio2MetaDataLoggingUtils.logDosFileAttributes(path); - Nio2MetaDataLoggingUtils.logPosixFileAttributes(path); - Nio2MetaDataLoggingUtils.logFileOwnerAttributes(path); + if (Files.exists(path, LinkOption.NOFOLLOW_LINKS)) { - Watcher watcher = new Watcher(); + Nio2MetaDataLoggingUtils.logFileStoreAttributes(path); + Nio2MetaDataLoggingUtils.logBasicFileAttributes(path); + Nio2MetaDataLoggingUtils.logDosFileAttributes(path); + Nio2MetaDataLoggingUtils.logPosixFileAttributes(path); + Nio2MetaDataLoggingUtils.logFileOwnerAttributes(path); + + Watcher watcher = new Watcher(); + + try { + watcher.watchDirectory(path); + } catch (IOException | InterruptedException ex) { + LOG.error(ex.getMessage()); + } + + } else { + + LOG.error("Path {} doesn't exist. Exiting", path); - try { - watcher.watchDirectory(path); - } catch (IOException | InterruptedException ex) { - LOG.error(ex.getMessage()); } } } diff --git a/src/main/java/io/skas/melbjvm/nio2/AsynchronousFileReader.java b/src/main/java/io/skas/melbjvm/nio2/AsynchronousFileReader.java index ff7c82b..273ddc5 100644 --- a/src/main/java/io/skas/melbjvm/nio2/AsynchronousFileReader.java +++ b/src/main/java/io/skas/melbjvm/nio2/AsynchronousFileReader.java @@ -18,7 +18,6 @@ public class AsynchronousFileReader implements CompletionHandler<Integer, ByteBu public static final Logger LOG = LoggerFactory.getLogger(AsynchronousFileReader.class); public static final int BYTES_IN_MEGABYTE = 1048576; - private Long position; private Path path; private ByteBuffer buffer; @@ -36,31 +35,41 @@ public class AsynchronousFileReader implements CompletionHandler<Integer, ByteBu } private void openChannel() { + try { this.asynchronousFileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.READ); } catch (IOException e) { e.printStackTrace(); } + } private void closeChannel() { + try { this.asynchronousFileChannel.close(); } catch (IOException e) { e.printStackTrace(); } + } private void readChannel(long position) { + asynchronousFileChannel.read(buffer, position, buffer, this); + } @Override public void completed(Integer result, ByteBuffer buffer) { + if (result < 0) { + closeChannel(); LOG.debug("read: {} megabytes", position / BYTES_IN_MEGABYTE); + } else { + position += result; if (buffer.hasRemaining()) { readChannel(position); @@ -70,12 +79,16 @@ public class AsynchronousFileReader implements CompletionHandler<Integer, ByteBu buffer.clear(); this.readChannel(position); } + } + } @Override public void failed(Throwable exc, ByteBuffer buffer) { + LOG.error("read failed: {}", exc.getMessage()); exc.printStackTrace(); + } } diff --git a/src/main/java/io/skas/melbjvm/nio2/Nio2MetaDataLoggingUtils.java b/src/main/java/io/skas/melbjvm/nio2/Nio2MetaDataLoggingUtils.java index 0899d60..0133574 100644 --- a/src/main/java/io/skas/melbjvm/nio2/Nio2MetaDataLoggingUtils.java +++ b/src/main/java/io/skas/melbjvm/nio2/Nio2MetaDataLoggingUtils.java @@ -25,9 +25,11 @@ public class Nio2MetaDataLoggingUtils { public static final String POSIX_VIEW = "posix"; public static void logBasicFileAttributes(Path path) throws IOException { + final FileStore fileStore = Files.getFileStore(path); if (fileStore.supportsFileAttributeView(BASIC_VIEW)) { + BasicFileAttributes basicFileAttributes = Files.readAttributes(path, BasicFileAttributes.class); LOG.info("Basic file attributes for path [{}]", path); @@ -35,15 +37,21 @@ public class Nio2MetaDataLoggingUtils { LOG.info(" isOther? {}", basicFileAttributes.isOther()); LOG.info(" isRegularFile? {}", basicFileAttributes.isRegularFile()); LOG.info(" isSymbolicLink? {}", basicFileAttributes.isSymbolicLink()); + } else { + LOG.info("the file store in which [{}] resides doesn't support the [{}] file attribute view", path, BASIC_VIEW); + } + } public static void logDosFileAttributes(Path path) throws IOException { + final FileStore fileStore = Files.getFileStore(path); if (fileStore.supportsFileAttributeView(DOS_VIEW)) { + DosFileAttributes dosFileAttributes = Files.readAttributes(path, DosFileAttributes.class); LOG.info("Dos file attributes for path [{}]", path); @@ -52,15 +60,21 @@ public class Nio2MetaDataLoggingUtils { LOG.info(" isHidden? {}", dosFileAttributes.isHidden()); LOG.info(" isReadOnly? {}", dosFileAttributes.isReadOnly()); LOG.info(" isSystem? {}", dosFileAttributes.isSystem()); + } else { + LOG.info("the file store in which [{}] resides doesn't support the [{}] file attribute view", path, DOS_VIEW); + } + } public static void logPosixFileAttributes(Path path) throws IOException { + final FileStore fileStore = Files.getFileStore(path); if (fileStore.supportsFileAttributeView(POSIX_VIEW)) { + PosixFileAttributes posixFileAttributes = Files.readAttributes(path, PosixFileAttributes.class); final Set<PosixFilePermission> permissions = posixFileAttributes.permissions(); @@ -81,24 +95,33 @@ public class Nio2MetaDataLoggingUtils { (permissions.contains(PosixFilePermission.OTHERS_READ) ? "r" : "-") + (permissions.contains(PosixFilePermission.OTHERS_WRITE) ? "w" : "-") + (permissions.contains(PosixFilePermission.OTHERS_EXECUTE) ? "x" : "-")); + } else { + LOG.info("the file store in which [{}] resides doesn't support the [{}] file attribute view", path, POSIX_VIEW); + } } public static void logFileOwnerAttributes(Path path) throws IOException { + final FileStore fileStore = Files.getFileStore(path); + if (fileStore.supportsFileAttributeView(OWNER_VIEW)) { + final FileOwnerAttributeView fileAttributeView = Files.getFileAttributeView(path, FileOwnerAttributeView.class); LOG.info("Owner file attributes for path [{}]", path); LOG.info(" principal: {}", fileAttributeView.getOwner()); } else { + LOG.info("the file store in which [{}] resides doesn't support the [{}] file attribute view", path, OWNER_VIEW); + } } public static void logFileStoreAttributes(Path path) throws IOException { + final FileStore fileStore = Files.getFileStore(path); LOG.info("File store attributes for path [{}]", path); @@ -108,6 +131,7 @@ public class Nio2MetaDataLoggingUtils { LOG.info(" total space: {}", fileStore.getTotalSpace() / BYTES_IN_MEGABYTE); LOG.info(" total unallocated: {}", fileStore.getUnallocatedSpace() / BYTES_IN_MEGABYTE); LOG.info(" total space: {}", fileStore.getUsableSpace() / BYTES_IN_MEGABYTE); + } -} +}
\ No newline at end of file diff --git a/src/main/java/io/skas/melbjvm/nio2/VisitingWatcher.java b/src/main/java/io/skas/melbjvm/nio2/VisitingWatcher.java new file mode 100644 index 0000000..4ea5ef1 --- /dev/null +++ b/src/main/java/io/skas/melbjvm/nio2/VisitingWatcher.java @@ -0,0 +1,111 @@ +package io.skas.melbjvm.nio2; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.nio.file.*; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.HashMap; +import java.util.Map; + +/** + * VisitingWatcher is a watch service that watches a directory tree using the + * SimpleFileVisitor to register directory trees created within the watched + * directory. + * + * @author Szymon Szukalski [szymon.szukalski@gmail.com] + */ +public class VisitingWatcher { + + private static final Logger LOG = LoggerFactory.getLogger(VisitingWatcher.class); + + private WatchService watchService; + private final Map<WatchKey, Path> watchedPaths = new HashMap<WatchKey, Path>(); + + private void registerDirectory(Path directory) throws IOException { + + WatchKey key = directory.register( + watchService, + StandardWatchEventKinds.ENTRY_CREATE, + StandardWatchEventKinds.ENTRY_MODIFY, + StandardWatchEventKinds.ENTRY_DELETE); + + watchedPaths.put(key, directory); + + } + + private void registerTree(Path startingDirectory) throws IOException { + + Files.walkFileTree(startingDirectory, new SimpleFileVisitor<Path>() { + /** + * Invoked for a directory before entries in the directory are visited. + * <p/> + * <p> Unless overridden, this method returns {@link java.nio.file.FileVisitResult#CONTINUE + * CONTINUE}. + */ + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { + LOG.debug("registering: {}", dir); + registerDirectory(dir); + return FileVisitResult.CONTINUE; + } + }); + + } + + public void watchDirectory(Path directory) throws IOException, InterruptedException { + + watchService = FileSystems.getDefault().newWatchService(); + registerTree(directory); + + while (true) { + + // retrieve and remove the next watch key (waits) + final WatchKey key = watchService.take(); + + // get list of events for the key + for (WatchEvent<?> watchEvent : key.pollEvents()) { + + // get the event kind + final WatchEvent.Kind<?> kind = watchEvent.kind(); + + // get the filename for the event + final WatchEvent<Path> watchEventPath = (WatchEvent<Path>) watchEvent; + final Path filename = watchEventPath.context(); + + LOG.debug("event: {} filename: {}", kind, filename); + + // handle OVERFLOW event + if (kind == StandardWatchEventKinds.OVERFLOW) { + continue; + } + + // handle CREATE event + if (kind == StandardWatchEventKinds.ENTRY_CREATE) { + final Path directoryPath = watchedPaths.get(key); + final Path child = directoryPath.resolve(filename); + + if (Files.isDirectory(child, LinkOption.NOFOLLOW_LINKS)) { + registerTree(child); + } + } + } + + // reset the key + boolean valid = key.reset(); + + // remove the key from watched paths if the key is not valid + // (if the directory was deleted, for example) + if (!valid) { + watchedPaths.remove(key); + + if (watchedPaths.isEmpty()) { + break; + } + } + } + + watchService.close(); + } +}
\ No newline at end of file diff --git a/src/main/java/io/skas/melbjvm/nio2/Watcher.java b/src/main/java/io/skas/melbjvm/nio2/Watcher.java index 1938c9f..c3986a7 100644 --- a/src/main/java/io/skas/melbjvm/nio2/Watcher.java +++ b/src/main/java/io/skas/melbjvm/nio2/Watcher.java @@ -13,11 +13,12 @@ public class Watcher { private static final Logger LOG = LoggerFactory.getLogger(Watcher.class); - public void watchDirectory(Path watchedPath) throws IOException, InterruptedException { + public void watchDirectory(Path directory) throws IOException, InterruptedException { + // New try with resources try (WatchService watchService = FileSystems.getDefault().newWatchService()) { - final WatchKey key = watchedPath.register( + final WatchKey key = directory.register( watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY, @@ -25,21 +26,29 @@ public class Watcher { while (true) { + // retrieve and remove the next watch key (waits) watchService.take(); + // get list of events for the key for (WatchEvent<?> watchEvent : key.pollEvents()) { + + // get the event kind final WatchEvent.Kind<?> kind = watchEvent.kind(); + // get the filename for the event + final WatchEvent<Path> watchEventPath = (WatchEvent<Path>) watchEvent; + final Path filename = watchEventPath.context(); + + LOG.debug("event: {} filename: {}", kind, filename); + // handle OVERFLOW event if (kind == StandardWatchEventKinds.OVERFLOW) { continue; } - final WatchEvent<Path> watchEventPath = (WatchEvent<Path>) watchEvent; - Path newFile = watchedPath.resolve(watchEventPath.context()); - + // handle CREATE event if (kind == StandardWatchEventKinds.ENTRY_CREATE) { - new AsynchronousFileReader(newFile); + new AsynchronousFileReader(filename); } } |
