1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.mycore.datamodel.niofs;
20
21 import java.io.IOException;
22 import java.net.URI;
23 import java.net.URISyntaxException;
24 import java.nio.file.DirectoryNotEmptyException;
25 import java.nio.file.FileAlreadyExistsException;
26 import java.nio.file.FileSystem;
27 import java.nio.file.FileSystemException;
28 import java.nio.file.FileSystemNotFoundException;
29 import java.nio.file.Files;
30 import java.nio.file.NoSuchFileException;
31 import java.nio.file.Path;
32 import java.nio.file.PathMatcher;
33 import java.nio.file.WatchService;
34 import java.nio.file.attribute.UserPrincipalLookupService;
35 import java.nio.file.spi.FileSystemProvider;
36 import java.util.Collections;
37 import java.util.Objects;
38 import java.util.Set;
39
40 import org.apache.logging.log4j.LogManager;
41 import org.mycore.common.MCRException;
42 import org.mycore.common.MCRUtils;
43
44 import com.google.common.cache.CacheBuilder;
45 import com.google.common.cache.CacheLoader;
46 import com.google.common.cache.LoadingCache;
47 import com.google.common.collect.Iterables;
48 import com.google.common.collect.Sets;
49
50 public abstract class MCRAbstractFileSystem extends FileSystem {
51
52 public static final char SEPARATOR = '/';
53
54 public static final String SEPARATOR_STRING = String.valueOf(SEPARATOR);
55
56 private final LoadingCache<String, MCRPath> rootDirectoryCache = CacheBuilder.newBuilder().weakValues()
57 .build(new CacheLoader<String, MCRPath>() {
58
59 @Override
60 public MCRPath load(final String owner) throws Exception {
61 return getPath(owner, "/", instance());
62 }
63 });
64
65 private final MCRPath emptyPath;
66
67 public MCRAbstractFileSystem() {
68 super();
69 emptyPath = getPath(null, "", this);
70 }
71
72
73
74
75
76
77
78 public static MCRAbstractFileSystem getInstance(String scheme) {
79 URI uri;
80 try {
81 uri = MCRPaths.getURI(scheme, "helper", SEPARATOR_STRING);
82 } catch (URISyntaxException e) {
83 throw new MCRException(e);
84 }
85 for (FileSystemProvider provider : Iterables.concat(MCRPaths.webAppProvider,
86 FileSystemProvider.installedProviders())) {
87 if (provider.getScheme().equals(scheme)) {
88 return (MCRAbstractFileSystem) provider.getFileSystem(uri);
89 }
90 }
91 throw new FileSystemNotFoundException("Provider \"" + scheme + "\" not found");
92 }
93
94 public static MCRPath getPath(final String owner, final String path, final MCRAbstractFileSystem fs) {
95 Objects.requireNonNull(fs, MCRAbstractFileSystem.class.getSimpleName() + " instance may not be null.");
96 return new MCRPath(owner, path) {
97
98 @Override
99 public MCRAbstractFileSystem getFileSystem() {
100 return fs;
101 }
102 };
103 }
104
105
106
107
108
109
110
111
112
113
114
115 public abstract void createRoot(String owner) throws FileSystemException;
116
117
118
119
120
121
122
123
124 public boolean verifies(MCRPath path) throws NoSuchFileException {
125 try {
126 return verifies(path, Files.readAttributes(path, MCRFileAttributes.class));
127 } catch (IOException e) {
128 if (e instanceof NoSuchFileException) {
129 throw (NoSuchFileException) e;
130 }
131 return false;
132 }
133 }
134
135
136
137
138
139
140
141
142
143 public boolean verifies(MCRPath path, MCRFileAttributes<?> attrs) throws NoSuchFileException {
144 if (Files.notExists(Objects.requireNonNull(path, "Path may not be null."))) {
145 throw new NoSuchFileException(path.toString());
146 }
147 Objects.requireNonNull(attrs, "attrs may not be null");
148 String md5Sum;
149 try {
150 md5Sum = MCRUtils.getMD5Sum(Files.newInputStream(path));
151 } catch (IOException e) {
152 LogManager.getLogger(getClass()).error("Could not verify path: {}", path, e);
153 return false;
154 }
155 boolean returns = md5Sum.matches(attrs.md5sum());
156 if (!returns) {
157 LogManager.getLogger(getClass()).warn("MD5sum does not match: {}", path);
158 }
159 return returns;
160 }
161
162
163
164
165
166
167
168
169
170
171
172 public abstract void removeRoot(String owner) throws FileSystemException;
173
174 @Override
175 public void close() throws IOException {
176 throw new UnsupportedOperationException();
177 }
178
179 public MCRPath emptyPath() {
180 return emptyPath;
181 }
182
183 @Override
184 public Path getPath(final String first, final String... more) {
185 String root = null;
186 final StringBuilder path = new StringBuilder();
187 if (!first.isEmpty() && first.charAt(first.length() - 1) == ':') {
188
189 root = first;
190 path.append(SEPARATOR);
191 } else {
192 path.append(first);
193 }
194 boolean addSep = path.length() > 0;
195 for (final String element : more) {
196 if (!element.isEmpty()) {
197 if (addSep) {
198 path.append(SEPARATOR);
199 } else {
200 addSep = true;
201 }
202 path.append(element);
203 }
204 }
205 return getPath(root, path.toString(), this);
206 }
207
208 @Override
209 public PathMatcher getPathMatcher(final String syntaxAndPattern) {
210 final int pos = syntaxAndPattern.indexOf(':');
211 if (pos <= 0 || pos == syntaxAndPattern.length()) {
212 throw new IllegalArgumentException();
213 }
214 final String syntax = syntaxAndPattern.substring(0, pos);
215 final String pattern = syntaxAndPattern.substring(pos + 1);
216 switch (syntax) {
217 case "glob":
218 return new MCRGlobPathMatcher(pattern);
219 case "regex":
220 return new MCRPathMatcher(pattern);
221 default:
222 throw new UnsupportedOperationException("If the pattern syntax '" + syntax + "' is not known.");
223 }
224 }
225
226 public MCRPath getRootDirectory(final String owner) {
227 return rootDirectoryCache.getUnchecked(owner);
228 }
229
230 @Override
231 public String getSeparator() {
232 return SEPARATOR_STRING;
233 }
234
235 @Override
236 public UserPrincipalLookupService getUserPrincipalLookupService() {
237 throw new UnsupportedOperationException();
238 }
239
240 @Override
241 public boolean isOpen() {
242 return true;
243 }
244
245 @Override
246 public boolean isReadOnly() {
247 return false;
248 }
249
250 @Override
251 public WatchService newWatchService() throws IOException {
252 throw new UnsupportedOperationException();
253 }
254
255 @Override
256 public Set<String> supportedFileAttributeViews() {
257 return Collections.unmodifiableSet(Sets.newHashSet("basic", "mcrifs"));
258 }
259
260 public MCRPath toThisFileSystem(final MCRPath other) {
261 if (Objects.requireNonNull(other).getFileSystem() == this) {
262 return other;
263 }
264 return getPath(other.root, other.path, this);
265 }
266
267 private MCRAbstractFileSystem instance() {
268 return this;
269 }
270
271 }