Skip to content

Commit b3755f3

Browse files
committed
Merge branch 'release/2.6.3'
2 parents 470bcb5 + b6f15b3 commit b3755f3

22 files changed

+643
-315
lines changed

pom.xml

+17-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<modelVersion>4.0.0</modelVersion>
33
<groupId>org.cryptomator</groupId>
44
<artifactId>cryptofs</artifactId>
5-
<version>2.6.2</version>
5+
<version>2.6.3</version>
66
<name>Cryptomator Crypto Filesystem</name>
77
<description>This library provides the Java filesystem provider used by Cryptomator.</description>
88
<url>https://github.com/cryptomator/cryptofs</url>
@@ -22,6 +22,7 @@
2222
<jwt.version>4.3.0</jwt.version>
2323
<dagger.version>2.44.2</dagger.version>
2424
<guava.version>31.1-jre</guava.version>
25+
<caffeine.version>3.1.4</caffeine.version>
2526
<slf4j.version>2.0.3</slf4j.version>
2627

2728
<!-- test dependencies -->
@@ -81,6 +82,21 @@
8182
<artifactId>guava</artifactId>
8283
<version>${guava.version}</version>
8384
</dependency>
85+
<dependency>
86+
<groupId>com.github.ben-manes.caffeine</groupId>
87+
<artifactId>caffeine</artifactId>
88+
<version>${caffeine.version}</version>
89+
<exclusions>
90+
<exclusion>
91+
<groupId>org.checkerframework</groupId>
92+
<artifactId>checker-qual</artifactId>
93+
</exclusion>
94+
<exclusion>
95+
<groupId>com.google.errorprone</groupId>
96+
<artifactId>error_prone_annotations</artifactId>
97+
</exclusion>
98+
</exclusions>
99+
</dependency>
84100
<dependency>
85101
<groupId>org.slf4j</groupId>
86102
<artifactId>slf4j-api</artifactId>

src/main/java/module-info.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import org.cryptomator.cryptofs.CryptoFileSystemProvider;
2-
import org.cryptomator.cryptofs.common.CiphertextFileType;
32
import org.cryptomator.cryptofs.health.api.HealthCheck;
43
import org.cryptomator.cryptofs.health.dirid.DirIdCheck;
54
import org.cryptomator.cryptofs.health.shortened.ShortenedNamesCheck;
@@ -10,6 +9,7 @@
109
module org.cryptomator.cryptofs {
1110
requires transitive org.cryptomator.cryptolib;
1211
requires com.google.common;
12+
requires com.github.benmanes.caffeine;
1313
requires org.slf4j;
1414
requires dagger;
1515
requires com.auth0.jwt;

src/main/java/org/cryptomator/cryptofs/CryptoPathMapper.java

+16-15
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,9 @@
88
*******************************************************************************/
99
package org.cryptomator.cryptofs;
1010

11-
import com.google.common.base.Throwables;
12-
import com.google.common.cache.Cache;
13-
import com.google.common.cache.CacheBuilder;
14-
import com.google.common.cache.CacheLoader;
15-
import com.google.common.cache.LoadingCache;
11+
import com.github.benmanes.caffeine.cache.Cache;
12+
import com.github.benmanes.caffeine.cache.Caffeine;
13+
import com.github.benmanes.caffeine.cache.LoadingCache;
1614
import com.google.common.io.BaseEncoding;
1715
import org.cryptomator.cryptofs.common.CiphertextFileType;
1816
import org.cryptomator.cryptofs.common.Constants;
@@ -22,6 +20,7 @@
2220

2321
import javax.inject.Inject;
2422
import java.io.IOException;
23+
import java.io.UncheckedIOException;
2524
import java.nio.charset.StandardCharsets;
2625
import java.nio.file.FileAlreadyExistsException;
2726
import java.nio.file.Files;
@@ -32,7 +31,6 @@
3231
import java.time.Duration;
3332
import java.util.Objects;
3433
import java.util.Optional;
35-
import java.util.concurrent.ExecutionException;
3634

3735
import static org.cryptomator.cryptofs.common.Constants.DATA_DIR_NAME;
3836

@@ -61,8 +59,8 @@ public class CryptoPathMapper {
6159
this.dirIdProvider = dirIdProvider;
6260
this.longFileNameProvider = longFileNameProvider;
6361
this.vaultConfig = vaultConfig;
64-
this.ciphertextNames = CacheBuilder.newBuilder().maximumSize(MAX_CACHED_CIPHERTEXT_NAMES).build(CacheLoader.from(this::getCiphertextFileName));
65-
this.ciphertextDirectories = CacheBuilder.newBuilder().maximumSize(MAX_CACHED_DIR_PATHS).expireAfterWrite(MAX_CACHE_AGE).build();
62+
this.ciphertextNames = Caffeine.newBuilder().maximumSize(MAX_CACHED_CIPHERTEXT_NAMES).build(this::getCiphertextFileName);
63+
this.ciphertextDirectories = Caffeine.newBuilder().maximumSize(MAX_CACHED_DIR_PATHS).expireAfterWrite(MAX_CACHE_AGE).build();
6664
this.rootDirectory = resolveDirectory(Constants.ROOT_DIR_ID);
6765
}
6866

@@ -127,7 +125,7 @@ public CiphertextFilePath getCiphertextFilePath(CryptoPath cleartextPath) throws
127125
}
128126

129127
public CiphertextFilePath getCiphertextFilePath(Path parentCiphertextDir, String parentDirId, String cleartextName) {
130-
String ciphertextName = ciphertextNames.getUnchecked(new DirIdAndName(parentDirId, cleartextName));
128+
String ciphertextName = ciphertextNames.get(new DirIdAndName(parentDirId, cleartextName));
131129
Path c9rPath = parentCiphertextDir.resolve(ciphertextName);
132130
if (ciphertextName.length() > vaultConfig.getShorteningThreshold()) {
133131
LongFileNameProvider.DeflatedFileName deflatedFileName = longFileNameProvider.deflate(c9rPath);
@@ -160,13 +158,16 @@ public CiphertextDirectory getCiphertextDir(CryptoPath cleartextPath) throws IOE
160158
return rootDirectory;
161159
} else {
162160
try {
163-
return ciphertextDirectories.get(cleartextPath, () -> {
164-
Path dirFile = getCiphertextFilePath(cleartextPath).getDirFilePath();
165-
return resolveDirectory(dirFile);
161+
return ciphertextDirectories.get(cleartextPath, p -> {
162+
try {
163+
Path dirFile = getCiphertextFilePath(p).getDirFilePath();
164+
return resolveDirectory(dirFile);
165+
} catch (IOException e) {
166+
throw new UncheckedIOException(e);
167+
}
166168
});
167-
} catch (ExecutionException e) {
168-
Throwables.throwIfInstanceOf(e.getCause(), IOException.class);
169-
throw new IOException("Unexpected exception", e);
169+
} catch (UncheckedIOException e) {
170+
throw new IOException(e);
170171
}
171172
}
172173
}

src/main/java/org/cryptomator/cryptofs/DirectoryIdLoader.java

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
package org.cryptomator.cryptofs;
22

3-
import com.google.common.cache.CacheLoader;
3+
import com.github.benmanes.caffeine.cache.CacheLoader;
44

55
import javax.inject.Inject;
66
import java.io.IOException;
77
import java.io.InputStream;
8+
import java.io.UncheckedIOException;
89
import java.nio.channels.Channels;
910
import java.nio.channels.FileChannel;
1011
import java.nio.charset.StandardCharsets;
@@ -14,7 +15,7 @@
1415
import java.util.UUID;
1516

1617
@CryptoFileSystemScoped
17-
class DirectoryIdLoader extends CacheLoader<Path, String> {
18+
class DirectoryIdLoader implements CacheLoader<Path, String> {
1819

1920
private static final int MAX_DIR_ID_LENGTH = 1000;
2021

@@ -23,7 +24,7 @@ public DirectoryIdLoader() {
2324
}
2425

2526
@Override
26-
public String load(Path dirFilePath) throws IOException {
27+
public String load(Path dirFilePath) throws UncheckedIOException {
2728
try (FileChannel ch = FileChannel.open(dirFilePath, StandardOpenOption.READ);
2829
InputStream in = Channels.newInputStream(ch)) {
2930
long size = ch.size();
@@ -39,6 +40,8 @@ public String load(Path dirFilePath) throws IOException {
3940
}
4041
} catch (NoSuchFileException e) {
4142
return UUID.randomUUID().toString();
43+
} catch (IOException e) {
44+
throw new UncheckedIOException(e);
4245
}
4346
}
4447

src/main/java/org/cryptomator/cryptofs/DirectoryIdProvider.java

+9-8
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88
*******************************************************************************/
99
package org.cryptomator.cryptofs;
1010

11-
import java.io.IOException;
12-
import java.nio.file.Path;
13-
import java.util.concurrent.ExecutionException;
11+
import com.github.benmanes.caffeine.cache.Cache;
12+
import com.github.benmanes.caffeine.cache.Caffeine;
13+
import com.github.benmanes.caffeine.cache.LoadingCache;
1414

1515
import javax.inject.Inject;
16-
17-
import com.google.common.cache.CacheBuilder;
18-
import com.google.common.cache.LoadingCache;
16+
import java.io.IOException;
17+
import java.io.UncheckedIOException;
18+
import java.nio.file.Path;
1919

2020
@CryptoFileSystemScoped
2121
class DirectoryIdProvider {
@@ -26,13 +26,13 @@ class DirectoryIdProvider {
2626

2727
@Inject
2828
public DirectoryIdProvider(DirectoryIdLoader directoryIdLoader) {
29-
ids = CacheBuilder.newBuilder().maximumSize(MAX_CACHE_SIZE).build(directoryIdLoader);
29+
this.ids = Caffeine.newBuilder().maximumSize(MAX_CACHE_SIZE).build(directoryIdLoader);
3030
}
3131

3232
public String load(Path dirFilePath) throws IOException {
3333
try {
3434
return ids.get(dirFilePath);
35-
} catch (ExecutionException e) {
35+
} catch (UncheckedIOException e) {
3636
throw new IOException("Failed to load contents of directory file at path " + dirFilePath, e);
3737
}
3838
}
@@ -62,4 +62,5 @@ public void move(Path srcDirFilePath, Path dstDirFilePath) {
6262
}
6363
}
6464

65+
6566
}

src/main/java/org/cryptomator/cryptofs/LongFileNameProvider.java

+19-25
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@
88
*******************************************************************************/
99
package org.cryptomator.cryptofs;
1010

11+
import com.github.benmanes.caffeine.cache.Cache;
12+
import com.github.benmanes.caffeine.cache.Caffeine;
1113
import com.google.common.base.Throwables;
12-
import com.google.common.cache.CacheBuilder;
13-
import com.google.common.cache.CacheLoader;
14-
import com.google.common.cache.LoadingCache;
1514
import com.google.common.io.BaseEncoding;
1615
import org.cryptomator.cryptolib.common.MessageDigestSupplier;
1716

@@ -24,7 +23,6 @@
2423
import java.nio.file.Path;
2524
import java.nio.file.StandardOpenOption;
2625
import java.time.Duration;
27-
import java.util.concurrent.ExecutionException;
2826

2927
import static java.nio.charset.StandardCharsets.UTF_8;
3028
import static org.cryptomator.cryptofs.common.Constants.DEFLATED_FILE_SUFFIX;
@@ -39,31 +37,28 @@ public class LongFileNameProvider {
3937
private static final Duration MAX_CACHE_AGE = Duration.ofMinutes(1);
4038

4139
private final ReadonlyFlag readonlyFlag;
42-
private final LoadingCache<Path, String> longNames; // Maps from c9s paths to inflated filenames
40+
private final Cache<Path, String> longNames; // Maps from c9s paths to inflated filenames
4341

4442
@Inject
4543
public LongFileNameProvider(ReadonlyFlag readonlyFlag) {
4644
this.readonlyFlag = readonlyFlag;
47-
this.longNames = CacheBuilder.newBuilder().expireAfterAccess(MAX_CACHE_AGE).build(new Loader());
45+
this.longNames = Caffeine.newBuilder().expireAfterAccess(MAX_CACHE_AGE).build();
4846
}
4947

50-
private class Loader extends CacheLoader<Path, String> {
51-
52-
@Override
53-
public String load(Path c9sPath) throws IOException {
54-
Path longNameFile = c9sPath.resolve(INFLATED_FILE_NAME);
55-
try (SeekableByteChannel ch = Files.newByteChannel(longNameFile, StandardOpenOption.READ)) {
56-
if (ch.size() > MAX_FILENAME_BUFFER_SIZE) {
57-
throw new IOException("Unexpectedly large file: " + longNameFile);
58-
}
59-
assert ch.size() <= MAX_FILENAME_BUFFER_SIZE;
60-
ByteBuffer buf = ByteBuffer.allocate((int) ch.size());
61-
ch.read(buf);
62-
buf.flip();
63-
return UTF_8.decode(buf).toString();
48+
private String load(Path c9sPath) throws UncheckedIOException {
49+
Path longNameFile = c9sPath.resolve(INFLATED_FILE_NAME);
50+
try (SeekableByteChannel ch = Files.newByteChannel(longNameFile, StandardOpenOption.READ)) {
51+
if (ch.size() > MAX_FILENAME_BUFFER_SIZE) {
52+
throw new IOException("Unexpectedly large file: " + longNameFile);
6453
}
54+
assert ch.size() <= MAX_FILENAME_BUFFER_SIZE;
55+
ByteBuffer buf = ByteBuffer.allocate((int) ch.size());
56+
ch.read(buf);
57+
buf.flip();
58+
return UTF_8.decode(buf).toString();
59+
} catch (IOException e) {
60+
throw new UncheckedIOException(e);
6561
}
66-
6762
}
6863

6964
public boolean isDeflated(String possiblyDeflatedFileName) {
@@ -72,10 +67,9 @@ public boolean isDeflated(String possiblyDeflatedFileName) {
7267

7368
public String inflate(Path c9sPath) throws IOException {
7469
try {
75-
return longNames.get(c9sPath);
76-
} catch (ExecutionException e) {
77-
Throwables.throwIfInstanceOf(e.getCause(), IOException.class);
78-
throw new IllegalStateException("Unexpected exception", e);
70+
return longNames.get(c9sPath, this::load);
71+
} catch (UncheckedIOException e) {
72+
throw e.getCause(); // rethrow original to keep exception types such as NoSuchFileException
7973
}
8074
}
8175

0 commit comments

Comments
 (0)