]> git.argeo.org Git - lgpl/argeo-commons.git/blob - JcrFileSystem.java
3d0fcfe668b9a422bdeb528cde573d6dcc608077
[lgpl/argeo-commons.git] / JcrFileSystem.java
1 package org.argeo.jcr.fs;
2
3 import java.io.IOException;
4 import java.nio.file.FileStore;
5 import java.nio.file.FileSystem;
6 import java.nio.file.Path;
7 import java.nio.file.PathMatcher;
8 import java.nio.file.WatchService;
9 import java.nio.file.attribute.UserPrincipalLookupService;
10 import java.nio.file.spi.FileSystemProvider;
11 import java.util.ArrayList;
12 import java.util.HashSet;
13 import java.util.Iterator;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.Set;
17 import java.util.TreeMap;
18
19 import javax.jcr.Credentials;
20 import javax.jcr.Node;
21 import javax.jcr.Repository;
22 import javax.jcr.RepositoryException;
23 import javax.jcr.Session;
24 import javax.jcr.nodetype.NodeType;
25
26 import org.argeo.api.gcr.fs.AbstractFsStore;
27 import org.argeo.api.gcr.fs.AbstractFsSystem;
28 import org.argeo.jcr.Jcr;
29 import org.argeo.jcr.JcrUtils;
30
31 public class JcrFileSystem extends AbstractFsSystem<WorkspaceFileStore> {
32 private final JcrFileSystemProvider provider;
33
34 private final Repository repository;
35 private Session session;
36 private WorkspaceFileStore baseFileStore;
37
38 private Map<String, WorkspaceFileStore> mounts = new TreeMap<>();
39
40 private String userHomePath = null;
41
42 @Deprecated
43 public JcrFileSystem(JcrFileSystemProvider provider, Session session) throws IOException {
44 super();
45 this.provider = provider;
46 baseFileStore = new WorkspaceFileStore(null, session.getWorkspace());
47 this.session = session;
48 // Node userHome = provider.getUserHome(session);
49 // if (userHome != null)
50 // try {
51 // userHomePath = userHome.getPath();
52 // } catch (RepositoryException e) {
53 // throw new IOException("Cannot retrieve user home path", e);
54 // }
55 this.repository = null;
56 }
57
58 public JcrFileSystem(JcrFileSystemProvider provider, Repository repository) throws IOException {
59 this(provider, repository, null);
60 }
61
62 public JcrFileSystem(JcrFileSystemProvider provider, Repository repository, Credentials credentials)
63 throws IOException {
64 super();
65 this.provider = provider;
66 this.repository = repository;
67 try {
68 this.session = credentials == null ? repository.login() : repository.login(credentials);
69 baseFileStore = new WorkspaceFileStore(null, session.getWorkspace());
70 workspaces: for (String workspaceName : baseFileStore.getWorkspace().getAccessibleWorkspaceNames()) {
71 if (workspaceName.equals(baseFileStore.getWorkspace().getName()))
72 continue workspaces;// do not mount base
73 if (workspaceName.equals("security")) {
74 continue workspaces;// do not mount security workspace
75 // TODO make it configurable
76 }
77 Session mountSession = credentials == null ? repository.login(workspaceName)
78 : repository.login(credentials, workspaceName);
79 String mountPath = JcrPath.separator + workspaceName;
80 mounts.put(mountPath, new WorkspaceFileStore(mountPath, mountSession.getWorkspace()));
81 }
82 } catch (RepositoryException e) {
83 throw new IOException("Cannot initialise file system", e);
84 }
85
86 Node userHome = provider.getUserHome(repository);
87 if (userHome != null)
88 try {
89 userHomePath = toFsPath(userHome);
90 } catch (RepositoryException e) {
91 throw new IOException("Cannot retrieve user home path", e);
92 } finally {
93 JcrUtils.logoutQuietly(Jcr.session(userHome));
94 }
95 }
96
97 public String toFsPath(Node node) throws RepositoryException {
98 return getFileStore(node).toFsPath(node);
99 }
100
101 /** Whether this node should be skipped in directory listings */
102 public boolean skipNode(Node node) throws RepositoryException {
103 if (node.isNodeType(NodeType.NT_HIERARCHY_NODE))
104 return false;
105 return true;
106 }
107
108 public String getUserHomePath() {
109 return userHomePath;
110 }
111
112 public WorkspaceFileStore getFileStore(String path) {
113 WorkspaceFileStore res = baseFileStore;
114 for (String mountPath : mounts.keySet()) {
115 if (path.equals(mountPath))
116 return mounts.get(mountPath);
117 if (path.startsWith(mountPath + JcrPath.separator)) {
118 res = mounts.get(mountPath);
119 // we keep the last one
120 }
121 }
122 assert res != null;
123 return res;
124 }
125
126 public WorkspaceFileStore getFileStore(Node node) throws RepositoryException {
127 String workspaceName = node.getSession().getWorkspace().getName();
128 if (workspaceName.equals(baseFileStore.getWorkspace().getName()))
129 return baseFileStore;
130 for (String mountPath : mounts.keySet()) {
131 WorkspaceFileStore fileStore = mounts.get(mountPath);
132 if (workspaceName.equals(fileStore.getWorkspace().getName()))
133 return fileStore;
134 }
135 throw new IllegalStateException("No workspace mount found for " + node + " in workspace " + workspaceName);
136 }
137
138 public Iterator<JcrPath> listDirectMounts(Path base) {
139 String baseStr = base.toString();
140 Set<JcrPath> res = new HashSet<>();
141 mounts: for (String mountPath : mounts.keySet()) {
142 if (mountPath.equals(baseStr))
143 continue mounts;
144 if (mountPath.startsWith(baseStr)) {
145 JcrPath path = new JcrPath(this, mountPath);
146 Path relPath = base.relativize(path);
147 if (relPath.getNameCount() == 1)
148 res.add(path);
149 }
150 }
151 return res.iterator();
152 }
153
154 public WorkspaceFileStore getBaseFileStore() {
155 return baseFileStore;
156 }
157
158 @Override
159 public FileSystemProvider provider() {
160 return provider;
161 }
162
163 @Override
164 public void close() throws IOException {
165 JcrUtils.logoutQuietly(session);
166 for (String mountPath : mounts.keySet()) {
167 WorkspaceFileStore fileStore = mounts.get(mountPath);
168 try {
169 fileStore.close();
170 } catch (Exception e) {
171 e.printStackTrace();
172 }
173 }
174 }
175
176 @Override
177 public boolean isOpen() {
178 return session.isLive();
179 }
180
181 @Override
182 public boolean isReadOnly() {
183 return false;
184 }
185
186 @Override
187 public String getSeparator() {
188 return JcrPath.separator;
189 }
190
191 @Override
192 public Iterable<Path> getRootDirectories() {
193 Set<Path> single = new HashSet<>();
194 single.add(new JcrPath(this, JcrPath.separator));
195 return single;
196 }
197
198 @Override
199 public Iterable<FileStore> getFileStores() {
200 List<FileStore> stores = new ArrayList<>();
201 stores.add(baseFileStore);
202 stores.addAll(mounts.values());
203 return stores;
204 }
205
206 @Override
207 public Set<String> supportedFileAttributeViews() {
208 try {
209 String[] prefixes = session.getNamespacePrefixes();
210 Set<String> res = new HashSet<>();
211 for (String prefix : prefixes)
212 res.add(prefix);
213 res.add("basic");
214 return res;
215 } catch (RepositoryException e) {
216 throw new JcrFsException("Cannot get supported file attributes views", e);
217 }
218 }
219
220 @Override
221 public Path getPath(String first, String... more) {
222 StringBuilder sb = new StringBuilder(first);
223 // TODO Make it more robust
224 for (String part : more)
225 sb.append('/').append(part);
226 return new JcrPath(this, sb.toString());
227 }
228
229 @Override
230 public PathMatcher getPathMatcher(String syntaxAndPattern) {
231 throw new UnsupportedOperationException();
232 }
233
234 @Override
235 public UserPrincipalLookupService getUserPrincipalLookupService() {
236 throw new UnsupportedOperationException();
237 }
238
239 @Override
240 public WatchService newWatchService() throws IOException {
241 throw new UnsupportedOperationException();
242 }
243
244 // public Session getSession() {
245 // return session;
246 // }
247
248 public Repository getRepository() {
249 return repository;
250 }
251
252 }