parent() {
+ return Optional.empty();
+ }
+
+}
diff --git a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/Folder.java b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/Folder.java
new file mode 100644
index 000000000..e3bcb678d
--- /dev/null
+++ b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/Folder.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Markus Kreusch
+ * This file is licensed under the terms of the MIT license.
+ * See the LICENSE.txt file for more info.
+ ******************************************************************************/
+package org.cryptomator.filesystem;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.stream.Stream;
+
+/**
+ * A {@link Folder} in a {@link FileSystem}.
+ *
+ * @author Markus Kreusch
+ */
+public interface Folder extends Node {
+
+ /**
+ *
+ * Creates a {@link Stream} over all child nodes of this {@code Folder}.
+ *
+ * Note: The {@link Stream} may be lazily populated and thus
+ * {@link IOException IOExceptions} may occurs after this method returned.
+ * In this case implementors should throw a {@link UncheckedIOException}
+ * from any method that produces an {@link IOException}. Thus users should
+ * expect {@link UncheckedIOException UncheckedIOExceptions} when invoking
+ * methods on the returned {@code Stream}.
+ *
+ * @return the created {@code Stream}
+ * @throws IOException
+ * if an {@link IOException} occurs while initializing the
+ * stream
+ */
+ Stream children() throws IOException;
+
+ File file(String name) throws IOException;
+
+ Folder folder(String name) throws IOException;
+
+ void create(FolderCreateMode mode) throws IOException;
+
+ void delete() throws IOException;
+
+ /**
+ * @return the result of {@link #children()} filtered to contain only
+ * {@link File Files}
+ */
+ default Stream files() throws IOException {
+ return children() //
+ .filter(File.class::isInstance) //
+ .map(File.class::cast);
+ }
+
+ /**
+ * @return the result of {@link #children()} filtered to contain only
+ * {@link Folder Folders}
+ */
+ default Stream folders() throws IOException {
+ return children() //
+ .filter(Folder.class::isInstance) //
+ .map(Folder.class::cast);
+ }
+
+}
diff --git a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/FolderCreateMode.java b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/FolderCreateMode.java
new file mode 100644
index 000000000..1084a389b
--- /dev/null
+++ b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/FolderCreateMode.java
@@ -0,0 +1,12 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Markus Kreusch
+ * This file is licensed under the terms of the MIT license.
+ * See the LICENSE.txt file for more info.
+ ******************************************************************************/
+package org.cryptomator.filesystem;
+
+public enum FolderCreateMode {
+
+ FAIL_IF_PARENT_IS_MISSING, INCLUDING_PARENTS
+
+}
diff --git a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/Node.java b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/Node.java
new file mode 100644
index 000000000..b18566a05
--- /dev/null
+++ b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/Node.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Markus Kreusch
+ * This file is licensed under the terms of the MIT license.
+ * See the LICENSE.txt file for more info.
+ ******************************************************************************/
+package org.cryptomator.filesystem;
+
+import java.io.IOException;
+import java.time.Instant;
+import java.util.Optional;
+
+/**
+ * Represents a node, namely a {@link File} or {@link Folder}, in a
+ * {@link FileSystem}.
+ *
+ * @author Markus Kreusch
+ * @see Folder
+ * @see File
+ */
+public interface Node {
+
+ String name() throws IOException;
+
+ Optional parent() throws IOException;
+
+ boolean exists() throws IOException;
+
+ Instant lastModified() throws IOException;
+
+}
diff --git a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/ReadableBytes.java b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/ReadableBytes.java
new file mode 100644
index 000000000..476b320ea
--- /dev/null
+++ b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/ReadableBytes.java
@@ -0,0 +1,17 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Markus Kreusch
+ * This file is licensed under the terms of the MIT license.
+ * See the LICENSE.txt file for more info.
+ ******************************************************************************/
+package org.cryptomator.filesystem;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+public interface ReadableBytes {
+
+ void read(ByteBuffer target) throws IOException;
+
+ void read(ByteBuffer target, int position) throws IOException;
+
+}
diff --git a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/ReadableFile.java b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/ReadableFile.java
new file mode 100644
index 000000000..e6dc79a24
--- /dev/null
+++ b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/ReadableFile.java
@@ -0,0 +1,17 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Markus Kreusch
+ * This file is licensed under the terms of the MIT license.
+ * See the LICENSE.txt file for more info.
+ ******************************************************************************/
+package org.cryptomator.filesystem;
+
+import java.io.IOException;
+
+public interface ReadableFile extends File, ReadableBytes, AutoCloseable {
+
+ WritableFile copyTo(WritableFile other) throws IOException;
+
+ @Override
+ void close() throws IOException;
+
+}
diff --git a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/WritableBytes.java b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/WritableBytes.java
new file mode 100644
index 000000000..1b111b49e
--- /dev/null
+++ b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/WritableBytes.java
@@ -0,0 +1,17 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Markus Kreusch
+ * This file is licensed under the terms of the MIT license.
+ * See the LICENSE.txt file for more info.
+ ******************************************************************************/
+package org.cryptomator.filesystem;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+public interface WritableBytes {
+
+ void write(ByteBuffer source) throws IOException;
+
+ void write(ByteBuffer source, int position) throws IOException;
+
+}
diff --git a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/WritableFile.java b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/WritableFile.java
new file mode 100644
index 000000000..491e6c6ce
--- /dev/null
+++ b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/WritableFile.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Markus Kreusch
+ * This file is licensed under the terms of the MIT license.
+ * See the LICENSE.txt file for more info.
+ ******************************************************************************/
+package org.cryptomator.filesystem;
+
+import java.io.IOException;
+import java.time.Instant;
+
+public interface WritableFile extends File, WritableBytes, AutoCloseable {
+
+ WritableFile moveTo(WritableFile other) throws IOException;
+
+ void setLastModified(Instant instant) throws IOException;
+
+ void delete() throws IOException;
+
+ void truncate() throws IOException;
+
+ @Override
+ void close() throws IOException;
+
+}
diff --git a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/package-info.java b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/package-info.java
new file mode 100644
index 000000000..4b9a00fae
--- /dev/null
+++ b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * Defines a file system abstraction to allow access to real and virtual file
+ * systems through a common API.
+ */
+package org.cryptomator.filesystem;
\ No newline at end of file
diff --git a/main/pom.xml b/main/pom.xml
index f0dddf885..1199de99f 100644
--- a/main/pom.xml
+++ b/main/pom.xml
@@ -59,6 +59,11 @@
core
${project.version}
+
+ org.cryptomator
+ filesystem-api
+ ${project.version}
+
org.cryptomator
crypto-api
@@ -192,6 +197,7 @@
+ filesystem-api
crypto-api
crypto-aes
core