summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README1
-rw-r--r--melbjvm-nio2.iml19
-rw-r--r--pom.xml62
-rw-r--r--src/main/java/io/skas/melbjvm/nio2/App.java34
-rw-r--r--src/main/java/io/skas/melbjvm/nio2/FileReader.java76
-rw-r--r--src/main/java/io/skas/melbjvm/nio2/Nio2MetaDataLoggingUtils.java115
-rw-r--r--src/main/java/io/skas/melbjvm/nio2/Watcher.java53
-rw-r--r--src/main/resources/logback.xml14
8 files changed, 374 insertions, 0 deletions
diff --git a/README b/README
new file mode 100644
index 0000000..e449f60
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+Java 7 NIO.2 Example Application for MelbJVM #8
diff --git a/melbjvm-nio2.iml b/melbjvm-nio2.iml
new file mode 100644
index 0000000..c20d824
--- /dev/null
+++ b/melbjvm-nio2.iml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/target/classes" />
+ <output-test url="file://$MODULE_DIR$/target/test-classes" />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/resources" isTestSource="false" />
+ <excludeFolder url="file://$MODULE_DIR$/target" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.6.4" level="project" />
+ <orderEntry type="library" name="Maven: ch.qos.logback:logback-classic:1.0.1" level="project" />
+ <orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.0.1" level="project" />
+ </component>
+ <component name="POM File Configuration" pomFile="file://$MODULE_DIR$/pom.xml" />
+</module>
+
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..e1953f0
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,62 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>io.skas</groupId>
+ <artifactId>melbjvm-nio2</artifactId>
+ <version>1.0</version>
+ <packaging>jar</packaging>
+
+ <name>MelbJVM #8 NIO.2 Example</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <slf4j.version>1.6.4</slf4j.version>
+ <logback-classic.version>1.0.1</logback-classic.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <scope>compile</scope>
+ <version>${slf4j.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <version>${logback-classic.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.0.2</version>
+ <configuration>
+ <source>1.7</source>
+ <target>1.7</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.2.1</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>java</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <mainClass>io.skas.melbjvm.nio2.App</mainClass>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/src/main/java/io/skas/melbjvm/nio2/App.java b/src/main/java/io/skas/melbjvm/nio2/App.java
new file mode 100644
index 0000000..df6e962
--- /dev/null
+++ b/src/main/java/io/skas/melbjvm/nio2/App.java
@@ -0,0 +1,34 @@
+package io.skas.melbjvm.nio2;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class App {
+
+ public static final Logger LOG = LoggerFactory.getLogger(App.class);
+
+ public static void main(String[] args) throws IOException {
+
+ final Path path = Paths.get("/tmp/doit");
+
+ Watcher watcher = new Watcher();
+
+ try {
+ Nio2MetaDataLoggingUtils.logFileStoreAttributes(path);
+ Nio2MetaDataLoggingUtils.logBasicFileAttributes(path);
+ Nio2MetaDataLoggingUtils.logDosFileAttributes(path);
+ Nio2MetaDataLoggingUtils.logPosixFileAttributes(path);
+ Nio2MetaDataLoggingUtils.logFileOwnerAttributes(path);
+
+ watcher.watchDirectory(path);
+
+ } catch (IOException | InterruptedException ex) {
+ LOG.error(ex.getMessage());
+ }
+ }
+
+}
diff --git a/src/main/java/io/skas/melbjvm/nio2/FileReader.java b/src/main/java/io/skas/melbjvm/nio2/FileReader.java
new file mode 100644
index 0000000..56882ec
--- /dev/null
+++ b/src/main/java/io/skas/melbjvm/nio2/FileReader.java
@@ -0,0 +1,76 @@
+package io.skas.melbjvm.nio2;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.AsynchronousFileChannel;
+import java.nio.channels.CompletionHandler;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+
+/**
+ * @author Szymon Szukalski [szymon.szukalski@portlandrisk.com]
+ */
+public class FileReader implements CompletionHandler<Integer, ByteBuffer> {
+
+ public static final Logger LOG = LoggerFactory.getLogger(FileReader.class);
+
+ private Long fileSize;
+ private Path path;
+ private ByteBuffer buffer;
+ private AsynchronousFileChannel asynchronousFileChannel;
+
+ public FileReader(Path path) {
+ this.fileSize = 0L;
+ this.path = path;
+ this.buffer = ByteBuffer.allocate(1048576);
+ LOG.info("reading {}...", path);
+
+ this.openChannel();
+ this.readChannel(0);
+ }
+
+ private void openChannel() {
+ try {
+ this.asynchronousFileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.READ);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void readChannel(long position) {
+ asynchronousFileChannel.read(buffer, position, buffer, this);
+ }
+
+ private void closeChannel() {
+ try {
+ this.asynchronousFileChannel.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void completed(Integer result, ByteBuffer attachment) {
+ if (result != -1) {
+ this.fileSize += result;
+ attachment.flip();
+ attachment.clear();
+ this.readChannel(this.fileSize);
+ } else {
+
+ LOG.info("... read in: {} bytes from {}", fileSize, path);
+ attachment.flip();
+ attachment.clear();
+ this.closeChannel();
+ }
+ }
+
+ @Override
+ public void failed(Throwable exc, ByteBuffer attachment) {
+ 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
new file mode 100644
index 0000000..3c2451d
--- /dev/null
+++ b/src/main/java/io/skas/melbjvm/nio2/Nio2MetaDataLoggingUtils.java
@@ -0,0 +1,115 @@
+package io.skas.melbjvm.nio2;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.nio.file.FileStore;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.*;
+import java.util.Set;
+
+public class Nio2MetaDataLoggingUtils {
+
+ public static final Logger LOG = LoggerFactory.getLogger(Nio2MetaDataLoggingUtils.class);
+
+ public static final long BYTES_IN_MEGABYTE = 1048576L;
+
+ public static final String BASIC_VIEW = "basic";
+ public static final String OWNER_VIEW = "owner";
+ public static final String USER_VIEW = "user";
+ public static final String UNIX_VIEW = "unix";
+ public static final String DOS_VIEW = "dos";
+ 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);
+
+ LOG.info(" isDirectory? {}", basicFileAttributes.isDirectory());
+ 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);
+
+ LOG.info(" isArchive? {}", dosFileAttributes.isArchive());
+ 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();
+
+ LOG.info("Posix file attributes for path [{}]", path);
+
+ LOG.info(" owner? {}", posixFileAttributes.owner());
+ LOG.info(" group? {}", posixFileAttributes.group());
+ LOG.info(" owner permissions? {}",
+ (permissions.contains(PosixFilePermission.OWNER_READ) ? "r" : "-") +
+ (permissions.contains(PosixFilePermission.OWNER_WRITE) ? "w" : "-") +
+ (permissions.contains(PosixFilePermission.OWNER_EXECUTE) ? "x" : "-"));
+ LOG.info(" group permissions? {}",
+ (permissions.contains(PosixFilePermission.GROUP_READ) ? "r" : "-") +
+ (permissions.contains(PosixFilePermission.GROUP_WRITE) ? "w" : "-") +
+ (permissions.contains(PosixFilePermission.GROUP_EXECUTE) ? "x" : "-"));
+ LOG.info(" others permissions? {}",
+ (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);
+
+ LOG.info(" name: {}", fileStore.name());
+ LOG.info(" type: {}", fileStore.type());
+ 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);
+ }
+
+}
diff --git a/src/main/java/io/skas/melbjvm/nio2/Watcher.java b/src/main/java/io/skas/melbjvm/nio2/Watcher.java
new file mode 100644
index 0000000..2947ef7
--- /dev/null
+++ b/src/main/java/io/skas/melbjvm/nio2/Watcher.java
@@ -0,0 +1,53 @@
+package io.skas.melbjvm.nio2;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.nio.file.*;
+
+public class Watcher {
+
+ private static final Logger LOG = LoggerFactory.getLogger(Watcher.class);
+
+ public void watchDirectory(Path watchedPath) throws IOException, InterruptedException {
+
+ try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
+
+ final WatchKey key = watchedPath.register(
+ watchService,
+ StandardWatchEventKinds.ENTRY_CREATE,
+ StandardWatchEventKinds.ENTRY_MODIFY,
+ StandardWatchEventKinds.ENTRY_DELETE);
+
+ while (true) {
+
+ watchService.take();
+
+ for (WatchEvent<?> watchEvent : key.pollEvents()) {
+ final WatchEvent.Kind<?> kind = watchEvent.kind();
+
+ // handle OVERFLOW event
+ if (kind == StandardWatchEventKinds.OVERFLOW) {
+ continue;
+ }
+
+ final WatchEvent<Path> watchEventPath = (WatchEvent<Path>) watchEvent;
+ Path newFile = watchedPath.resolve(watchEventPath.context());
+
+ if (kind == StandardWatchEventKinds.ENTRY_MODIFY) {
+ new FileReader(newFile);
+ }
+ }
+
+ //reset the key
+ boolean valid = key.reset();
+
+ //exit loop if the key is not valid (if the directory was deleted, for example)
+ if (!valid) {
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml
new file mode 100644
index 0000000..47171c2
--- /dev/null
+++ b/src/main/resources/logback.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration debug="false">
+
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <pattern>%d [%16.16thread{16}] %.-1level %36.36logger{36} - %msg%n</pattern>
+ </layout>
+ </appender>
+
+ <root level="DEBUG">
+ <appender-ref ref="STDOUT"/>
+ </root>
+
+</configuration> \ No newline at end of file