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
index af9718ce6..72bcde132 100644
--- a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/Folder.java
+++ b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/Folder.java
@@ -7,7 +7,6 @@ package org.cryptomator.filesystem;
import java.io.IOException;
import java.io.UncheckedIOException;
-import java.time.Instant;
import java.util.stream.Stream;
/**
@@ -151,17 +150,4 @@ public interface Folder extends Node {
}
}
- /**
- *
- * Sets the creation time of the folder.
- *
- * Setting the creation time may not be supported by all {@link FileSystem FileSystems}. If the {@code FileSystem} this {@code Folder} belongs to does not support the
- * setting the creation time the behavior of this method is unspecified.
- *
- * @param instant the time to set as creation time
- */
- default void setCreationTime(Instant instant) throws UncheckedIOException {
- throw new UncheckedIOException(new IOException("CreationTime not supported"));
- }
-
}
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
index 5d5ee3890..a5fab7d2c 100644
--- a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/Node.java
+++ b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/Node.java
@@ -5,6 +5,7 @@
******************************************************************************/
package org.cryptomator.filesystem;
+import java.io.IOException;
import java.io.UncheckedIOException;
import java.time.Instant;
import java.util.Optional;
@@ -45,6 +46,19 @@ public interface Node {
return Optional.empty();
}
+ /**
+ *
+ * Sets the creation time of this node.
+ *
+ * Setting the creation time may not be supported by all {@link FileSystem FileSystems}. If the {@code FileSystem} this {@code Node} belongs to does not support the
+ * setting the creation time the behavior of this method is unspecified.
+ *
+ * @param instant the time to set as creation time
+ */
+ default void setCreationTime(Instant instant) throws UncheckedIOException {
+ throw new UncheckedIOException(new IOException("CreationTime not supported"));
+ }
+
/**
* @return the {@link FileSystem} this Node belongs to
*/
diff --git a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingFile.java b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingFile.java
index 89ac586be..4d8db50ef 100644
--- a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingFile.java
+++ b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingFile.java
@@ -9,6 +9,7 @@
package org.cryptomator.filesystem.delegating;
import java.io.UncheckedIOException;
+import java.time.Instant;
import java.util.Optional;
import org.cryptomator.filesystem.File;
@@ -69,4 +70,14 @@ public abstract class DelegatingFile> extends D
}
}
+ @Override
+ public Optional creationTime() throws UncheckedIOException {
+ return delegate.creationTime();
+ }
+
+ @Override
+ public void setCreationTime(Instant instant) throws UncheckedIOException {
+ delegate.setCreationTime(instant);
+ }
+
}
diff --git a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingFolder.java b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingFolder.java
index afb6823da..d62b9740c 100644
--- a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingFolder.java
+++ b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingFolder.java
@@ -97,6 +97,11 @@ public abstract class DelegatingFolder, F exten
}
}
+ @Override
+ public Optional creationTime() throws UncheckedIOException {
+ return delegate.creationTime();
+ }
+
@Override
public void setCreationTime(Instant instant) throws UncheckedIOException {
delegate.setCreationTime(instant);
diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/blockaligned/BlockAlignedWritableFile.java b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/blockaligned/BlockAlignedWritableFile.java
index 4bb406b79..a79285f8c 100644
--- a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/blockaligned/BlockAlignedWritableFile.java
+++ b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/blockaligned/BlockAlignedWritableFile.java
@@ -143,6 +143,11 @@ class BlockAlignedWritableFile implements WritableFile {
delegate.get().setLastModified(instant);
}
+ @Override
+ public void setCreationTime(Instant instant) throws UncheckedIOException {
+ delegate.get().setCreationTime(instant);
+ }
+
@Override
public void delete() throws UncheckedIOException {
delegate.get().delete();
diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFile.java b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFile.java
index e8c4aa9b6..24e33c3b3 100644
--- a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFile.java
+++ b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFile.java
@@ -12,7 +12,6 @@ import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.UncheckedIOException;
import java.time.Instant;
-import java.util.Optional;
import org.cryptomator.crypto.engine.Cryptor;
import org.cryptomator.filesystem.File;
@@ -57,9 +56,4 @@ public class CryptoFile extends CryptoNode implements File {
return toString().compareTo(o.toString());
}
- @Override
- public Optional creationTime() throws UncheckedIOException {
- return physicalFile().creationTime();
- }
-
}
diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFolder.java b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFolder.java
index d67a2ff3a..f1457d84a 100644
--- a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFolder.java
+++ b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFolder.java
@@ -13,10 +13,9 @@ import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.IOException;
import java.io.Reader;
import java.io.UncheckedIOException;
-import java.nio.ByteBuffer;
+import java.io.Writer;
import java.nio.channels.Channels;
import java.time.Instant;
-import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Predicate;
@@ -30,7 +29,6 @@ import org.cryptomator.filesystem.Deleter;
import org.cryptomator.filesystem.File;
import org.cryptomator.filesystem.Folder;
import org.cryptomator.filesystem.Node;
-import org.cryptomator.filesystem.WritableFile;
class CryptoFolder extends CryptoNode implements Folder {
@@ -131,14 +129,16 @@ class CryptoFolder extends CryptoNode implements Folder {
@Override
public void create() {
final File dirFile = physicalFile();
- if (dirFile.exists()) {
+ final Folder dir = physicalFolder();
+ if (dirFile.exists() && dir.exists()) {
return;
}
parent.create();
final String directoryId = getDirectoryId();
- try (WritableFile writable = dirFile.openWritable()) {
- final ByteBuffer buf = ByteBuffer.wrap(directoryId.getBytes());
- writable.write(buf);
+ try (Writer writer = Channels.newWriter(dirFile.openWritable(), UTF_8.newEncoder(), -1)) {
+ writer.write(directoryId);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
}
physicalFolder().create();
}
@@ -157,13 +157,15 @@ class CryptoFolder extends CryptoNode implements Folder {
throw new IllegalArgumentException("Can not move directories containing one another (src: " + this + ", dst: " + target + ")");
}
+ // directoryId will be used by target, from now on we must no longer use the same id
+ // a new one will be generated on-demand.
+ final String oldDirectoryId = getDirectoryId();
+ directoryId.set(null);
+
target.physicalFile().parent().get().create();
this.physicalFile().moveTo(target.physicalFile());
- // directoryId is now used by target, we must no longer use the same id
- // (we'll generate a new one when needed)
- target.directoryId.set(getDirectoryId());
- directoryId.set(null);
+ target.directoryId.set(oldDirectoryId);
}
@Override
@@ -172,13 +174,9 @@ class CryptoFolder extends CryptoNode implements Folder {
return;
}
Deleter.deleteContent(this);
- physicalFile().delete();
physicalFolder().delete();
- }
-
- @Override
- public Optional creationTime() throws UncheckedIOException {
- return physicalFile().creationTime();
+ physicalFile().delete();
+ directoryId.set(null);
}
@Override
diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoNode.java b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoNode.java
index 384ddab7e..cfa2f0d79 100644
--- a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoNode.java
+++ b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoNode.java
@@ -8,6 +8,8 @@
*******************************************************************************/
package org.cryptomator.filesystem.crypto;
+import java.io.UncheckedIOException;
+import java.time.Instant;
import java.util.Optional;
import org.cryptomator.crypto.engine.Cryptor;
@@ -55,7 +57,16 @@ abstract class CryptoNode implements Node {
@Override
public boolean exists() {
return physicalFile().exists();
- // return parent.children().anyMatch(node -> node.equals(this));
+ }
+
+ @Override
+ public Optional creationTime() throws UncheckedIOException {
+ return physicalFile().creationTime();
+ }
+
+ @Override
+ public void setCreationTime(Instant instant) throws UncheckedIOException {
+ physicalFile().setCreationTime(instant);
}
@Override
diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoWritableFile.java b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoWritableFile.java
index 681687d98..7eb2a8b9d 100644
--- a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoWritableFile.java
+++ b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoWritableFile.java
@@ -86,6 +86,11 @@ class CryptoWritableFile implements WritableFile {
file.setLastModified(instant);
}
+ @Override
+ public void setCreationTime(Instant instant) throws UncheckedIOException {
+ file.setCreationTime(instant);
+ }
+
@Override
public void delete() {
writeTask.cancel(true);
@@ -99,11 +104,6 @@ class CryptoWritableFile implements WritableFile {
initialize(0);
}
- @Override
- public void setCreationTime(Instant instant) throws UncheckedIOException {
- file.setCreationTime(instant);
- }
-
@Override
public boolean isOpen() {
return file.isOpen();
diff --git a/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryFile.java b/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryFile.java
index 31fe9a64e..ea143eb49 100644
--- a/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryFile.java
+++ b/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryFile.java
@@ -71,10 +71,6 @@ class InMemoryFile extends InMemoryNode implements File {
this.lastModified = lastModified;
}
- private void setCreationTime(Instant creationTime) {
- this.creationTime = creationTime;
- }
-
private ByteBuffer getContent() {
return content;
}
diff --git a/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryFolder.java b/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryFolder.java
index d6bfb5d1d..6d76b8f6b 100644
--- a/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryFolder.java
+++ b/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryFolder.java
@@ -10,15 +10,15 @@ package org.cryptomator.filesystem.inmem;
import static java.lang.String.format;
-import java.io.IOException;
+import java.io.FileNotFoundException;
import java.io.UncheckedIOException;
+import java.nio.file.FileAlreadyExistsException;
import java.time.Instant;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;
-import org.apache.commons.io.FileExistsException;
import org.cryptomator.common.WeakValuedCache;
import org.cryptomator.filesystem.Folder;
@@ -38,7 +38,7 @@ class InMemoryFolder extends InMemoryNode implements Folder {
if (exists()) {
return existingChildren.values().stream();
} else {
- throw new UncheckedIOException(new IOException(format("Folder %s does not exist", this)));
+ throw new UncheckedIOException(new FileNotFoundException(format("Folder %s does not exist", this)));
}
}
@@ -69,7 +69,7 @@ class InMemoryFolder extends InMemoryNode implements Folder {
parent.existingChildren.compute(name, (k, v) -> {
if (v != null) {
// other file or folder with same name already exists.
- throw new UncheckedIOException(new FileExistsException(k));
+ throw new UncheckedIOException(new FileAlreadyExistsException(k));
} else {
this.lastModified = Instant.now();
return this;
@@ -113,11 +113,6 @@ class InMemoryFolder extends InMemoryNode implements Folder {
assert!this.exists();
}
- @Override
- public void setCreationTime(Instant instant) throws UncheckedIOException {
- creationTime = instant;
- }
-
@Override
public String toString() {
return parent.toString() + name + "/";
diff --git a/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryNode.java b/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryNode.java
index f20d28d88..55dd2d012 100644
--- a/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryNode.java
+++ b/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryNode.java
@@ -83,4 +83,9 @@ class InMemoryNode implements Node {
}
}
+ @Override
+ public void setCreationTime(Instant creationTime) throws UncheckedIOException {
+ this.creationTime = creationTime;
+ }
+
}
diff --git a/main/filesystem-nio/src/main/java/org/cryptomator/filesystem/nio/NioNode.java b/main/filesystem-nio/src/main/java/org/cryptomator/filesystem/nio/NioNode.java
index db3d32494..f7ed1ac8c 100644
--- a/main/filesystem-nio/src/main/java/org/cryptomator/filesystem/nio/NioNode.java
+++ b/main/filesystem-nio/src/main/java/org/cryptomator/filesystem/nio/NioNode.java
@@ -3,6 +3,7 @@ package org.cryptomator.filesystem.nio;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Path;
+import java.nio.file.attribute.FileTime;
import java.time.Instant;
import java.util.Optional;
@@ -59,4 +60,13 @@ abstract class NioNode implements Node {
}
}
+ @Override
+ public void setCreationTime(Instant creationTime) throws UncheckedIOException {
+ try {
+ nioAccess.setCreationTime(path, FileTime.from(creationTime));
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
}
diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/jackrabbitservlet/DavFolder.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/jackrabbitservlet/DavFolder.java
index f22ca07f5..4992967cd 100644
--- a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/jackrabbitservlet/DavFolder.java
+++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/jackrabbitservlet/DavFolder.java
@@ -147,15 +147,20 @@ class DavFolder extends DavNode {
@Override
public void copy(DavResource destination, boolean shallow) throws DavException {
- if (destination instanceof DavFolder) {
- DavFolder dst = (DavFolder) destination;
- if (dst.node.exists()) {
- dst.node.delete();
- } else if (!dst.node.parent().get().exists()) {
+ if (!node.exists()) {
+ throw new DavException(DavServletResponse.SC_NOT_FOUND);
+ }
+ if (destination instanceof DavNode) {
+ DavNode> dst = (DavNode>) destination;
+ if (!dst.node.parent().get().exists()) {
throw new DavException(DavServletResponse.SC_CONFLICT, "Destination's parent doesn't exist.");
}
- dst.node.create();
+ }
+ if (destination instanceof DavFolder) {
+ DavFolder dst = (DavFolder) destination;
if (shallow) {
+ // create destination, if it doesn't exist yet:
+ dst.node.create();
// http://www.webdav.org/specs/rfc2518.html#copy.for.collections
node.creationTime().ifPresent(dst::setCreationTime);
dst.setModificationTime(node.lastModified());
@@ -168,8 +173,6 @@ class DavFolder extends DavNode {
Folder newDst = parent.folder(dst.node.name());
if (dst.node.exists()) {
dst.node.delete();
- } else if (!parent.exists()) {
- throw new DavException(DavServletResponse.SC_CONFLICT, "Destination's parent doesn't exist.");
}
node.copyTo(newDst);
} else {