|
8 | 8 | *******************************************************************************/ |
9 | 9 | package org.cryptomator.cryptofs.attr; |
10 | 10 |
|
11 | | -import org.cryptomator.cryptofs.common.ArrayUtils; |
12 | | -import org.cryptomator.cryptofs.common.CiphertextFileType; |
13 | | -import org.cryptomator.cryptofs.CryptoFileSystemProperties; |
| 11 | +import org.cryptomator.cryptofs.CryptoFileSystemScoped; |
14 | 12 | import org.cryptomator.cryptofs.CryptoPath; |
15 | 13 | import org.cryptomator.cryptofs.CryptoPathMapper; |
16 | | -import org.cryptomator.cryptofs.fh.OpenCryptoFiles; |
17 | | -import org.cryptomator.cryptofs.CryptoFileSystemScoped; |
18 | 14 | import org.cryptomator.cryptofs.Symlinks; |
19 | | -import org.cryptomator.cryptofs.fh.OpenCryptoFile; |
20 | | -import org.cryptomator.cryptolib.api.Cryptor; |
| 15 | +import org.cryptomator.cryptofs.common.ArrayUtils; |
| 16 | +import org.cryptomator.cryptofs.common.CiphertextFileType; |
21 | 17 |
|
22 | 18 | import javax.inject.Inject; |
23 | 19 | import java.io.IOException; |
24 | 20 | import java.nio.file.Files; |
25 | 21 | import java.nio.file.LinkOption; |
26 | 22 | import java.nio.file.Path; |
27 | 23 | import java.nio.file.attribute.BasicFileAttributes; |
28 | | -import java.nio.file.attribute.DosFileAttributes; |
29 | | -import java.nio.file.attribute.PosixFileAttributes; |
30 | | -import java.util.HashMap; |
31 | | -import java.util.Map; |
32 | 24 | import java.util.Optional; |
33 | 25 |
|
34 | 26 | @CryptoFileSystemScoped |
35 | 27 | public class AttributeProvider { |
36 | 28 |
|
37 | | - private static final Map<Class<? extends BasicFileAttributes>, AttributesConstructor<? extends BasicFileAttributes>> ATTR_CONSTRUCTORS; |
38 | | - |
39 | | - static { |
40 | | - ATTR_CONSTRUCTORS = new HashMap<>(); |
41 | | - ATTR_CONSTRUCTORS.put(BasicFileAttributes.class, (AttributesConstructor<BasicFileAttributes>) CryptoBasicFileAttributes::new); |
42 | | - ATTR_CONSTRUCTORS.put(PosixFileAttributes.class, (AttributesConstructor<PosixFileAttributes>) CryptoPosixFileAttributes::new); |
43 | | - ATTR_CONSTRUCTORS.put(DosFileAttributes.class, (AttributesConstructor<DosFileAttributes>) CryptoDosFileAttributes::new); |
44 | | - } |
45 | | - |
46 | | - private final Cryptor cryptor; |
| 29 | + private final AttributeComponent.Builder attributeComponentBuilder; |
47 | 30 | private final CryptoPathMapper pathMapper; |
48 | | - private final OpenCryptoFiles openCryptoFiles; |
49 | | - private final CryptoFileSystemProperties fileSystemProperties; |
50 | 31 | private final Symlinks symlinks; |
51 | 32 |
|
52 | 33 | @Inject |
53 | | - AttributeProvider(Cryptor cryptor, CryptoPathMapper pathMapper, OpenCryptoFiles openCryptoFiles, CryptoFileSystemProperties fileSystemProperties, Symlinks symlinks) { |
54 | | - this.cryptor = cryptor; |
| 34 | + AttributeProvider(AttributeComponent.Builder attributeComponentBuilder, CryptoPathMapper pathMapper, Symlinks symlinks) { |
| 35 | + this.attributeComponentBuilder = attributeComponentBuilder; |
55 | 36 | this.pathMapper = pathMapper; |
56 | | - this.openCryptoFiles = openCryptoFiles; |
57 | | - this.fileSystemProperties = fileSystemProperties; |
58 | 37 | this.symlinks = symlinks; |
59 | 38 | } |
60 | 39 |
|
61 | 40 | public <A extends BasicFileAttributes> A readAttributes(CryptoPath cleartextPath, Class<A> type, LinkOption... options) throws IOException { |
62 | | - if (!ATTR_CONSTRUCTORS.containsKey(type)) { |
63 | | - throw new UnsupportedOperationException("Unsupported file attribute type: " + type); |
64 | | - } |
65 | 41 | CiphertextFileType ciphertextFileType = pathMapper.getCiphertextFileType(cleartextPath); |
66 | | - switch (ciphertextFileType) { |
67 | | - case SYMLINK: { |
68 | | - if (ArrayUtils.contains(options, LinkOption.NOFOLLOW_LINKS)) { |
69 | | - Path ciphertextPath = pathMapper.getCiphertextFilePath(cleartextPath).getSymlinkFilePath(); |
70 | | - return readAttributes(ciphertextFileType, ciphertextPath, type); |
71 | | - } else { |
72 | | - CryptoPath resolved = symlinks.resolveRecursively(cleartextPath); |
73 | | - return readAttributes(resolved, type, options); |
74 | | - } |
75 | | - } |
76 | | - case DIRECTORY: { |
77 | | - Path ciphertextPath = pathMapper.getCiphertextDir(cleartextPath).path; |
78 | | - return readAttributes(ciphertextFileType, ciphertextPath, type); |
79 | | - } |
80 | | - case FILE: { |
81 | | - Path ciphertextPath = pathMapper.getCiphertextFilePath(cleartextPath).getFilePath(); |
82 | | - return readAttributes(ciphertextFileType, ciphertextPath, type); |
83 | | - } |
84 | | - default: |
85 | | - throw new UnsupportedOperationException("Unhandled node type " + ciphertextFileType); |
| 42 | + if (ciphertextFileType == CiphertextFileType.SYMLINK && !ArrayUtils.contains(options, LinkOption.NOFOLLOW_LINKS)) { |
| 43 | + cleartextPath = symlinks.resolveRecursively(cleartextPath); |
| 44 | + ciphertextFileType = pathMapper.getCiphertextFileType(cleartextPath); |
86 | 45 | } |
87 | | - } |
88 | | - |
89 | | - private <A extends BasicFileAttributes> A readAttributes(CiphertextFileType ciphertextFileType, Path ciphertextPath, Class<A> type) throws IOException { |
90 | | - assert ATTR_CONSTRUCTORS.containsKey(type); |
| 46 | + Path ciphertextPath = getCiphertextPath(cleartextPath, ciphertextFileType); |
91 | 47 | A ciphertextAttrs = Files.readAttributes(ciphertextPath, type); |
92 | | - AttributesConstructor<A> constructor = (AttributesConstructor<A>) ATTR_CONSTRUCTORS.get(type); |
93 | | - return constructor.construct(ciphertextAttrs, ciphertextFileType, ciphertextPath, cryptor, openCryptoFiles.get(ciphertextPath), fileSystemProperties.readonly()); |
| 48 | + Optional<BasicFileAttributes> cleartextAttrs = attributeComponentBuilder // |
| 49 | + .type(type) // |
| 50 | + .ciphertextFileType(ciphertextFileType) // |
| 51 | + .ciphertextPath(ciphertextPath) // |
| 52 | + .ciphertextAttributes(ciphertextAttrs) // |
| 53 | + .build() // |
| 54 | + .attributes(); |
| 55 | + if (cleartextAttrs.isPresent() && type.isInstance(cleartextAttrs.get())) { |
| 56 | + return type.cast(cleartextAttrs.get()); |
| 57 | + } else { |
| 58 | + throw new UnsupportedOperationException("Unsupported file attribute type: " + type); |
| 59 | + } |
94 | 60 | } |
95 | 61 |
|
96 | | - @FunctionalInterface |
97 | | - private interface AttributesConstructor<A extends BasicFileAttributes> { |
98 | | - A construct(A delegate, CiphertextFileType ciphertextFileType, Path ciphertextPath, Cryptor cryptor, Optional<OpenCryptoFile> openCryptoFile, boolean readonlyFileSystem); |
| 62 | + private Path getCiphertextPath(CryptoPath path, CiphertextFileType type) throws IOException { |
| 63 | + switch (type) { |
| 64 | + case SYMLINK: |
| 65 | + return pathMapper.getCiphertextFilePath(path).getSymlinkFilePath(); |
| 66 | + case DIRECTORY: |
| 67 | + return pathMapper.getCiphertextDir(path).path; |
| 68 | + case FILE: |
| 69 | + return pathMapper.getCiphertextFilePath(path).getFilePath(); |
| 70 | + default: |
| 71 | + throw new UnsupportedOperationException("Unhandled node type " + type); |
| 72 | + } |
99 | 73 | } |
100 | 74 |
|
101 | 75 | } |
0 commit comments