Skip to content
This repository was archived by the owner on Mar 14, 2025. It is now read-only.

Commit ceeebb3

Browse files
committed
Merge branch 'develop' into release/0.3.0
2 parents d82337d + 24273c6 commit ceeebb3

File tree

4 files changed

+45
-66
lines changed

4 files changed

+45
-66
lines changed

src/main/java/org/cryptomator/cloudaccess/CloudAccess.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,7 @@ public static CloudProvider vaultFormat8GCMCloudAccess(CloudProvider cloudProvid
5454
*/
5555
public static CloudProvider toWebDAV(URL url, String username, CharSequence password) {
5656
// TODO can we pass though CharSequence to the auth mechanism?
57-
var webdavCloudProvider = WebDavCloudProvider.from(WebDavCredential.from(url, username, password.toString()));
58-
return new MetadataCachingProviderDecorator(webdavCloudProvider);
57+
return WebDavCloudProvider.from(WebDavCredential.from(url, username, password.toString()));
5958
}
6059

6160
/**

src/main/java/org/cryptomator/cloudaccess/MetadataCachingProviderDecorator.java

Lines changed: 29 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
import java.util.Optional;
1616
import java.util.concurrent.CompletableFuture;
1717
import java.util.concurrent.CompletionStage;
18-
import java.util.function.Function;
1918

2019
public class MetadataCachingProviderDecorator implements CloudProvider {
2120

@@ -35,122 +34,89 @@ public MetadataCachingProviderDecorator(CloudProvider delegate, Duration cacheEn
3534
public CompletionStage<CloudItemMetadata> itemMetadata(CloudPath node) {
3635
var cachedMetadata = metadataCache.getIfPresent(node);
3736
if (cachedMetadata != null) {
38-
return cachedMetadata
39-
.map(CompletableFuture::completedFuture)
37+
return cachedMetadata //
38+
.map(CompletableFuture::completedFuture) //
4039
.orElseGet(() -> CompletableFuture.failedFuture(new NotFoundException()));
4140
} else {
42-
return delegate.itemMetadata(node)
43-
.handle((metadata, exception) -> {
41+
return delegate.itemMetadata(node) //
42+
.whenComplete((metadata, exception) -> {
4443
if (exception == null) {
4544
assert metadata != null;
4645
metadataCache.put(node, Optional.of(metadata));
47-
return CompletableFuture.completedFuture(metadata);
4846
} else if (exception instanceof NotFoundException) {
4947
metadataCache.put(node, Optional.empty());
50-
return CompletableFuture.<CloudItemMetadata>failedFuture(exception);
5148
} else {
5249
metadataCache.invalidate(node);
53-
return CompletableFuture.<CloudItemMetadata>failedFuture(exception);
5450
}
55-
}).thenCompose(Function.identity());
51+
});
5652
}
5753
}
5854

5955
@Override
6056
public CompletionStage<CloudItemList> list(CloudPath folder, Optional<String> pageToken) {
61-
return delegate.list(folder, pageToken)
62-
.handle((cloudItemList, exception) -> {
57+
return delegate.list(folder, pageToken) //
58+
.whenComplete((cloudItemList, exception) -> {
6359
evictIncludingDescendants(folder);
6460
if (exception == null) {
6561
assert cloudItemList != null;
6662
cloudItemList.getItems().forEach(metadata -> metadataCache.put(metadata.getPath(), Optional.of(metadata)));
67-
return CompletableFuture.completedFuture(cloudItemList);
68-
} else {
69-
return CompletableFuture.<CloudItemList>failedFuture(exception);
7063
}
71-
}).thenCompose(Function.identity());
64+
});
7265
}
7366

7467
@Override
7568
public CompletionStage<InputStream> read(CloudPath file, ProgressListener progressListener) {
76-
return delegate.read(file, progressListener)
77-
.handle((metadata, exception) -> {
78-
if (exception == null) {
79-
assert metadata != null;
80-
return CompletableFuture.completedFuture(metadata);
81-
} else {
69+
return delegate.read(file, progressListener) //
70+
.whenComplete((metadata, exception) -> {
71+
if (exception != null) {
8272
metadataCache.invalidate(file);
83-
return CompletableFuture.<InputStream>failedFuture(exception);
8473
}
85-
}).thenCompose(Function.identity());
74+
});
8675
}
8776

8877
@Override
8978
public CompletionStage<InputStream> read(CloudPath file, long offset, long count, ProgressListener progressListener) {
90-
return delegate.read(file, offset, count, progressListener)
91-
.handle((inputStream, exception) -> {
92-
if (exception == null) {
93-
assert inputStream != null;
94-
return CompletableFuture.completedFuture(inputStream);
95-
} else {
79+
return delegate.read(file, offset, count, progressListener) //
80+
.whenComplete((inputStream, exception) -> {
81+
if (exception != null) {
9682
metadataCache.invalidate(file);
97-
return CompletableFuture.<InputStream>failedFuture(exception);
9883
}
99-
}).thenCompose(Function.identity());
84+
});
10085
}
10186

10287
@Override
10388
public CompletionStage<Void> write(CloudPath file, boolean replace, InputStream data, long size, Optional<Instant> lastModified, ProgressListener progressListener) {
104-
return delegate.write(file, replace, data, size, lastModified, progressListener)
105-
.handle((nullReturn, exception) -> {
106-
if (exception == null) {
107-
return CompletableFuture.completedFuture(nullReturn);
108-
} else {
89+
return delegate.write(file, replace, data, size, lastModified, progressListener) //
90+
.whenComplete((nullReturn, exception) -> {
91+
if (exception != null) {
10992
metadataCache.invalidate(file);
110-
return CompletableFuture.<Void>failedFuture(exception);
11193
}
112-
}).thenCompose(Function.identity());
94+
});
11395
}
11496

11597
@Override
11698
public CompletionStage<CloudPath> createFolder(CloudPath folder) {
117-
return delegate.createFolder(folder)
118-
.handle((metadata, exception) -> {
99+
return delegate.createFolder(folder) //
100+
.whenComplete((metadata, exception) -> {
119101
metadataCache.invalidate(folder);
120-
if (exception == null) {
121-
assert metadata != null;
122-
return CompletableFuture.completedFuture(metadata);
123-
} else {
124-
return CompletableFuture.<CloudPath>failedFuture(exception);
125-
}
126-
}).thenCompose(Function.identity());
102+
});
127103
}
128104

129105
@Override
130106
public CompletionStage<Void> delete(CloudPath node) {
131-
return delegate.delete(node)
132-
.handle((nullReturn, exception) -> {
107+
return delegate.delete(node) //
108+
.whenComplete((nullReturn, exception) -> {
133109
evictIncludingDescendants(node);
134-
if (exception == null) {
135-
return CompletableFuture.completedFuture(nullReturn);
136-
} else {
137-
return CompletableFuture.<Void>failedFuture(exception);
138-
}
139-
}).thenCompose(Function.identity());
110+
});
140111
}
141112

142113
@Override
143114
public CompletionStage<CloudPath> move(CloudPath source, CloudPath target, boolean replace) {
144-
return delegate.move(source, target, replace)
145-
.handle((path, exception) -> {
115+
return delegate.move(source, target, replace) //
116+
.whenComplete((path, exception) -> {
146117
metadataCache.invalidate(source);
147118
metadataCache.invalidate(target);
148-
if (exception == null) {
149-
return CompletableFuture.completedFuture(path);
150-
} else {
151-
return CompletableFuture.<CloudPath>failedFuture(exception);
152-
}
153-
}).thenCompose(Function.identity());
119+
});
154120
}
155121

156122
private void evictIncludingDescendants(CloudPath cleartextPath) {

src/main/java/org/cryptomator/cloudaccess/webdav/WebDavClient.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
import org.cryptomator.cloudaccess.api.exceptions.CloudProviderException;
1414
import org.cryptomator.cloudaccess.api.exceptions.InsufficientStorageException;
1515
import org.cryptomator.cloudaccess.api.exceptions.NotFoundException;
16+
import org.slf4j.Logger;
17+
import org.slf4j.LoggerFactory;
1618
import org.xml.sax.SAXException;
1719

1820
import java.io.ByteArrayInputStream;
@@ -30,6 +32,7 @@
3032

3133
public class WebDavClient {
3234

35+
private static final Logger LOG = LoggerFactory.getLogger(WebDavClient.class);
3336
private static final Comparator<PropfindEntryData> ASCENDING_BY_DEPTH = Comparator.comparingLong(PropfindEntryData::getDepth);
3437

3538
private final WebDavCompatibleHttpClient httpClient;
@@ -42,6 +45,7 @@ public class WebDavClient {
4245
}
4346

4447
CloudItemList list(final CloudPath folder) throws CloudProviderException {
48+
LOG.trace("list {}", folder);
4549
try (final var response = executePropfindRequest(folder, PropfindDepth.ONE)) {
4650
checkExecutionSucceeded(response.code());
4751

@@ -54,6 +58,7 @@ CloudItemList list(final CloudPath folder) throws CloudProviderException {
5458
}
5559

5660
CloudItemMetadata itemMetadata(final CloudPath path) throws CloudProviderException {
61+
LOG.trace("itemMetadata {}", path);
5762
try (final var response = executePropfindRequest(path, PropfindDepth.ZERO)) {
5863
checkExecutionSucceeded(response.code());
5964

@@ -120,6 +125,7 @@ private CloudItemMetadata toCloudItem(final PropfindEntryData data, final CloudP
120125
}
121126

122127
CloudPath move(final CloudPath from, final CloudPath to, boolean replace) throws CloudProviderException {
128+
LOG.trace("move {} to {} (replace: {})", from, to, replace ? "true" : "false");
123129
final var builder = new Request.Builder() //
124130
.method("MOVE", null) //
125131
.url(absoluteURLFrom(from)) //
@@ -145,13 +151,15 @@ CloudPath move(final CloudPath from, final CloudPath to, boolean replace) throws
145151
}
146152

147153
InputStream read(final CloudPath path, final ProgressListener progressListener) throws CloudProviderException {
154+
LOG.trace("read {}", path);
148155
final var getRequest = new Request.Builder() //
149156
.get() //
150157
.url(absoluteURLFrom(path));
151158
return read(getRequest, progressListener);
152159
}
153160

154161
InputStream read(final CloudPath path, final long offset, final long count, final ProgressListener progressListener) throws CloudProviderException {
162+
LOG.trace("read {} (offset: {}, count: {})", path, offset, count);
155163
final var getRequest = new Request.Builder() //
156164
.header("Range", String.format("bytes=%d-%d", offset, offset + count - 1)) //
157165
.get() //
@@ -184,6 +192,7 @@ private InputStream read(final Request.Builder getRequest, final ProgressListene
184192
}
185193

186194
void write(final CloudPath file, final boolean replace, final InputStream data, final long size, final Optional<Instant> lastModified, final ProgressListener progressListener) throws CloudProviderException {
195+
LOG.trace("write {} (size: {}, lastModified: {}, replace: {})", file, size, lastModified, replace ? "true" : "false");
187196
if (!replace && exists(file)) {
188197
throw new AlreadyExistsException("CloudNode already exists and replace is false");
189198
}
@@ -211,6 +220,7 @@ private boolean exists(CloudPath path) throws CloudProviderException {
211220
}
212221

213222
CloudPath createFolder(final CloudPath path) throws CloudProviderException {
223+
LOG.trace("createFolder {}", path);
214224
if (exists(path)) {
215225
throw new AlreadyExistsException(String.format("Folder %s already exists", path.toString()));
216226
}
@@ -228,6 +238,7 @@ CloudPath createFolder(final CloudPath path) throws CloudProviderException {
228238
}
229239

230240
void delete(final CloudPath path) throws CloudProviderException {
241+
LOG.trace("delete {}", path);
231242
final var builder = new Request.Builder() //
232243
.delete() //
233244
.url(absoluteURLFrom(path));
@@ -240,6 +251,7 @@ void delete(final CloudPath path) throws CloudProviderException {
240251
}
241252

242253
void checkServerCompatibility() throws ServerNotWebdavCompatibleException {
254+
LOG.trace("checkServerCompatibility");
243255
final var optionsRequest = new Request.Builder() //
244256
.method("OPTIONS", null) //
245257
.url(baseUrl);
@@ -256,6 +268,7 @@ void checkServerCompatibility() throws ServerNotWebdavCompatibleException {
256268
}
257269

258270
void tryAuthenticatedRequest() throws UnauthorizedException {
271+
LOG.trace("tryAuthenticatedRequest");
259272
try {
260273
itemMetadata(CloudPath.of("/"));
261274
} catch (Exception e) {

src/test/java/org/cryptomator/cloudaccess/localfs/LocalFsCloudProviderTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.nio.file.Path;
2121
import java.time.Duration;
2222
import java.time.Instant;
23+
import java.time.temporal.ChronoUnit;
2324
import java.util.Optional;
2425
import java.util.concurrent.ExecutionException;
2526
import java.util.stream.Collectors;
@@ -146,7 +147,7 @@ public void testWriteToAndReplaceExistingFile() throws IOException {
146147
public void testWriteToNewFileUpdateModificationDate() throws IOException {
147148
var in = new ByteArrayInputStream("hallo welt".getBytes());
148149

149-
var modDate = Instant.now().minus(Duration.ofDays(365));
150+
var modDate = Instant.now().minus(Duration.ofDays(365)).truncatedTo(ChronoUnit.MILLIS);
150151

151152
var result = provider.write(CloudPath.of("/file"), false, in, 10, Optional.of(modDate), ProgressListener.NO_PROGRESS_AWARE);
152153
Assertions.assertTimeoutPreemptively(Duration.ofSeconds(1), () -> result.toCompletableFuture().get());

0 commit comments

Comments
 (0)