Browse Source

fixed webdav copy/move [ci skip]

Sebastian Stenzel 9 years ago
parent
commit
cf64a6c425

+ 0 - 14
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 {
 		}
 	}
 
-	/**
-	 * <p>
-	 * Sets the creation time of the folder.
-	 * <p>
-	 * 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"));
-	}
-
 }

+ 14 - 0
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();
 	}
 
+	/**
+	 * <p>
+	 * Sets the creation time of this node.
+	 * <p>
+	 * 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
 	 */

+ 11 - 0
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<D extends DelegatingFolder<D, ?>> extends D
 		}
 	}
 
+	@Override
+	public Optional<Instant> creationTime() throws UncheckedIOException {
+		return delegate.creationTime();
+	}
+
+	@Override
+	public void setCreationTime(Instant instant) throws UncheckedIOException {
+		delegate.setCreationTime(instant);
+	}
+
 }

+ 5 - 0
main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingFolder.java

@@ -97,6 +97,11 @@ public abstract class DelegatingFolder<D extends DelegatingFolder<D, F>, F exten
 		}
 	}
 
+	@Override
+	public Optional<Instant> creationTime() throws UncheckedIOException {
+		return delegate.creationTime();
+	}
+
 	@Override
 	public void setCreationTime(Instant instant) throws UncheckedIOException {
 		delegate.setCreationTime(instant);

+ 5 - 0
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();

+ 0 - 6
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<Instant> creationTime() throws UncheckedIOException {
-		return physicalFile().creationTime();
-	}
-
 }

+ 15 - 17
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<Instant> creationTime() throws UncheckedIOException {
-		return physicalFile().creationTime();
+		physicalFile().delete();
+		directoryId.set(null);
 	}
 
 	@Override

+ 12 - 1
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<Instant> creationTime() throws UncheckedIOException {
+		return physicalFile().creationTime();
+	}
+
+	@Override
+	public void setCreationTime(Instant instant) throws UncheckedIOException {
+		physicalFile().setCreationTime(instant);
 	}
 
 	@Override

+ 5 - 5
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();

+ 0 - 4
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;
 	}

+ 4 - 9
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 + "/";

+ 5 - 0
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;
+	}
+
 }

+ 10 - 0
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);
+		}
+	}
+
 }

+ 11 - 8
main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/jackrabbitservlet/DavFolder.java

@@ -147,15 +147,20 @@ class DavFolder extends DavNode<FolderLocator> {
 
 	@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<FolderLocator> {
 			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 {