]> git.argeo.org Git - lgpl/argeo-commons.git/blob - FsContentProvider.java
59a4d8deb5616f12c6b1b24c61406726f3f121b2
[lgpl/argeo-commons.git] / FsContentProvider.java
1 package org.argeo.cms.acr.fs;
2
3 import java.io.IOException;
4 import java.nio.ByteBuffer;
5 import java.nio.charset.StandardCharsets;
6 import java.nio.file.Files;
7 import java.nio.file.Path;
8 import java.nio.file.attribute.UserDefinedFileAttributeView;
9 import java.util.Iterator;
10 import java.util.Map;
11 import java.util.NavigableMap;
12 import java.util.Objects;
13 import java.util.TreeMap;
14 import java.util.stream.Collectors;
15
16 import org.argeo.api.acr.ContentResourceException;
17 import org.argeo.api.acr.CrName;
18 import org.argeo.api.acr.NamespaceUtils;
19 import org.argeo.api.acr.RuntimeNamespaceContext;
20 import org.argeo.api.acr.spi.ContentProvider;
21 import org.argeo.api.acr.spi.ProvidedContent;
22 import org.argeo.api.acr.spi.ProvidedSession;
23
24 /** Access a file system as a {@link ContentProvider}. */
25 public class FsContentProvider implements ContentProvider {
26 final static String XMLNS_ = "xmlns:";
27
28 protected String mountPath;
29 protected Path rootPath;
30
31 private NavigableMap<String, String> prefixes = new TreeMap<>();
32
33 public FsContentProvider(String mountPath, Path rootPath) {
34 Objects.requireNonNull(mountPath);
35 Objects.requireNonNull(rootPath);
36
37 this.mountPath = mountPath;
38 this.rootPath = rootPath;
39 // FIXME make it more robust
40 initNamespaces();
41 }
42
43 protected FsContentProvider() {
44
45 }
46
47 protected void initNamespaces() {
48 try {
49 UserDefinedFileAttributeView udfav = Files.getFileAttributeView(rootPath,
50 UserDefinedFileAttributeView.class);
51 if (udfav == null)
52 return;
53 for (String name : udfav.list()) {
54 if (name.startsWith(XMLNS_)) {
55 ByteBuffer buf = ByteBuffer.allocate(udfav.size(name));
56 udfav.read(name, buf);
57 buf.flip();
58 String namespace = StandardCharsets.UTF_8.decode(buf).toString();
59 String prefix = name.substring(XMLNS_.length());
60 prefixes.put(prefix, namespace);
61 }
62 }
63
64 // defaults
65 addDefaultNamespace(udfav, CrName.CR_DEFAULT_PREFIX, CrName.CR_NAMESPACE_URI);
66 addDefaultNamespace(udfav, "basic", CrName.CR_NAMESPACE_URI);
67 addDefaultNamespace(udfav, "owner", CrName.CR_NAMESPACE_URI);
68 addDefaultNamespace(udfav, "posix", CrName.CR_NAMESPACE_URI);
69 } catch (IOException e) {
70 throw new RuntimeException("Cannot read namespaces from " + rootPath, e);
71 }
72
73 }
74
75 protected void addDefaultNamespace(UserDefinedFileAttributeView udfav, String prefix, String namespace)
76 throws IOException {
77 if (!prefixes.containsKey(prefix)) {
78 ByteBuffer bb = ByteBuffer.wrap(namespace.getBytes(StandardCharsets.UTF_8));
79 udfav.write(XMLNS_ + prefix, bb);
80 prefixes.put(prefix, namespace);
81 }
82 }
83
84 public void registerPrefix(String prefix, String namespace) {
85 if (prefixes.containsKey(prefix))
86 prefixes.remove(prefix);
87 try {
88 UserDefinedFileAttributeView udfav = Files.getFileAttributeView(rootPath,
89 UserDefinedFileAttributeView.class);
90 addDefaultNamespace(udfav, prefix, namespace);
91 } catch (IOException e) {
92 throw new RuntimeException("Cannot register namespace " + prefix + " " + namespace + " on " + rootPath, e);
93 }
94
95 }
96
97 @Override
98 public String getMountPath() {
99 return mountPath;
100 }
101
102 boolean isMountBase(Path path) {
103 try {
104 return Files.isSameFile(rootPath, path);
105 } catch (IOException e) {
106 throw new ContentResourceException(e);
107 }
108 }
109
110 @Override
111 public ProvidedContent get(ProvidedSession session, String relativePath) {
112 return new FsContent(session, this, rootPath.resolve(relativePath));
113 }
114
115 @Override
116 public boolean exists(ProvidedSession session, String relativePath) {
117 return Files.exists(rootPath.resolve(relativePath));
118 }
119
120 /*
121 * NAMESPACE CONTEXT
122 */
123
124 @Override
125 public String getNamespaceURI(String prefix) {
126 return NamespaceUtils.getNamespaceURI((p) -> prefixes.get(p), prefix);
127 }
128
129 @Override
130 public Iterator<String> getPrefixes(String namespaceURI) {
131 Iterator<String> res = NamespaceUtils.getPrefixes((ns) -> prefixes.entrySet().stream()
132 .filter(e -> e.getValue().equals(ns)).map(Map.Entry::getKey).collect(Collectors.toUnmodifiableSet()),
133 namespaceURI);
134 if (!res.hasNext()) {
135 String prefix = RuntimeNamespaceContext.getNamespaceContext().getPrefix(namespaceURI);
136 if (prefix != null) {
137 registerPrefix(prefix, namespaceURI);
138 return getPrefixes(namespaceURI);
139 } else {
140 throw new IllegalArgumentException("Unknown namespace " + namespaceURI);
141 }
142 }
143 return res;
144 }
145
146 }