summaryrefslogtreecommitdiff
path: root/src/main/java/io/skas/melbjvm/nio2
diff options
context:
space:
mode:
authorSzymon Szukalski <szymon.szukalski@gmail.com>2012-10-03 10:45:23 +1000
committerSzymon Szukalski <szymon.szukalski@gmail.com>2012-10-03 10:45:23 +1000
commit6ddaaf8555d6b94684d061289249cac67c6eb09f (patch)
treeab4041586a70dcd1140cb32263c71354c2901e2b /src/main/java/io/skas/melbjvm/nio2
parent9c632725afb73bbf0966e52ca50c6d66c12d853b (diff)
Added example of SimpleFileVisitor usage
Diffstat (limited to 'src/main/java/io/skas/melbjvm/nio2')
-rw-r--r--src/main/java/io/skas/melbjvm/nio2/App.java32
-rw-r--r--src/main/java/io/skas/melbjvm/nio2/AsynchronousFileReader.java15
-rw-r--r--src/main/java/io/skas/melbjvm/nio2/Nio2MetaDataLoggingUtils.java26
-rw-r--r--src/main/java/io/skas/melbjvm/nio2/VisitingWatcher.java111
-rw-r--r--src/main/java/io/skas/melbjvm/nio2/Watcher.java21
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);
}
}