diff options
| -rw-r--r-- | README | 1 | ||||
| -rw-r--r-- | melbjvm-nio2.iml | 19 | ||||
| -rw-r--r-- | pom.xml | 62 | ||||
| -rw-r--r-- | src/main/java/io/skas/melbjvm/nio2/App.java | 34 | ||||
| -rw-r--r-- | src/main/java/io/skas/melbjvm/nio2/FileReader.java | 76 | ||||
| -rw-r--r-- | src/main/java/io/skas/melbjvm/nio2/Nio2MetaDataLoggingUtils.java | 115 | ||||
| -rw-r--r-- | src/main/java/io/skas/melbjvm/nio2/Watcher.java | 53 | ||||
| -rw-r--r-- | src/main/resources/logback.xml | 14 |
8 files changed, 374 insertions, 0 deletions
@@ -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> + @@ -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 |
