]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.jcr/src/org/argeo/jcr/fs/JcrPath.java
Move file system support to JCR bundle.
[lgpl/argeo-commons.git] / org.argeo.jcr / src / org / argeo / jcr / fs / JcrPath.java
1 package org.argeo.jcr.fs;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.net.URI;
6 import java.net.URISyntaxException;
7 import java.nio.file.FileSystem;
8 import java.nio.file.LinkOption;
9 import java.nio.file.Path;
10 import java.nio.file.WatchEvent.Kind;
11 import java.nio.file.WatchEvent.Modifier;
12 import java.nio.file.WatchKey;
13 import java.nio.file.WatchService;
14 import java.util.Arrays;
15 import java.util.Iterator;
16 import java.util.NoSuchElementException;
17
18 import javax.jcr.Node;
19 import javax.jcr.RepositoryException;
20 import javax.jcr.Session;
21
22 public class JcrPath implements Path {
23 private final static String delimStr = "/";
24 private final static char delimChar = '/';
25
26 private final JcrFileSystem fs;
27 private final String[] path;// null means root
28 private final boolean absolute;
29
30 // optim
31 private final int hashCode;
32
33 public JcrPath(JcrFileSystem filesSystem, String path) {
34 this.fs = filesSystem;
35 if (path == null)
36 throw new JcrFsException("Path cannot be null");
37 if (path.equals(delimStr)) {// root
38 this.path = null;
39 this.absolute = true;
40 this.hashCode = 0;
41 return;
42 } else if (path.equals("")) {// empty path
43 this.path = new String[] { "" };
44 this.absolute = false;
45 this.hashCode = "".hashCode();
46 return;
47 }
48
49 if (path.equals("~")) {// home
50 path = filesSystem.getUserHomePath();
51 if (path == null)
52 throw new JcrFsException("No home directory available");
53 }
54
55 this.absolute = path.charAt(0) == delimChar ? true : false;
56 String trimmedPath = path.substring(absolute ? 1 : 0,
57 path.charAt(path.length() - 1) == delimChar ? path.length() - 1 : path.length());
58 this.path = trimmedPath.split(delimStr);
59 for (int i = 0; i < this.path.length; i++) {
60 this.path[i] = Text.unescapeIllegalJcrChars(this.path[i]);
61 }
62 this.hashCode = this.path[this.path.length - 1].hashCode();
63 }
64
65 public JcrPath(JcrFileSystem filesSystem, Node node) throws RepositoryException {
66 this(filesSystem, node.getPath());
67 }
68
69 /** Internal optimisation */
70 private JcrPath(JcrFileSystem filesSystem, String[] path, boolean absolute) {
71 this.fs = filesSystem;
72 this.path = path;
73 this.absolute = path == null ? true : absolute;
74 this.hashCode = path == null ? 0 : path[path.length - 1].hashCode();
75 }
76
77 @Override
78 public FileSystem getFileSystem() {
79 return fs;
80 }
81
82 @Override
83 public boolean isAbsolute() {
84 return absolute;
85 }
86
87 @Override
88 public Path getRoot() {
89 try {
90 if (path == null)
91 return this;
92 return new JcrPath(fs, fs.getSession().getRootNode());
93 } catch (RepositoryException e) {
94 throw new JcrFsException("Cannot get root", e);
95 }
96 }
97
98 @Override
99 public String toString() {
100 if (path == null)
101 return "/";
102 StringBuilder sb = new StringBuilder();
103 if (isAbsolute())
104 sb.append('/');
105 for (int i = 0; i < path.length; i++) {
106 if (i != 0)
107 sb.append('/');
108 sb.append(path[i]);
109 }
110 return sb.toString();
111 }
112
113 public String toJcrPath() {
114 if (path == null)
115 return "/";
116 StringBuilder sb = new StringBuilder();
117 if (isAbsolute())
118 sb.append('/');
119 for (int i = 0; i < path.length; i++) {
120 if (i != 0)
121 sb.append('/');
122 sb.append(Text.escapeIllegalJcrChars(path[i]));
123 }
124 return sb.toString();
125 }
126
127 @Override
128 public Path getFileName() {
129 if (path == null)
130 return null;
131 return new JcrPath(fs, path[path.length - 1]);
132 }
133
134 @Override
135 public Path getParent() {
136 if (path == null)
137 return null;
138 if (path.length == 1)// root
139 return new JcrPath(fs, delimStr);
140 String[] parentPath = Arrays.copyOfRange(path, 0, path.length - 1);
141 return new JcrPath(fs, parentPath, absolute);
142 }
143
144 @Override
145 public int getNameCount() {
146 if (path == null)
147 return 0;
148 return path.length;
149 }
150
151 @Override
152 public Path getName(int index) {
153 if (path == null)
154 return null;
155 return new JcrPath(fs, path[index]);
156 }
157
158 @Override
159 public Path subpath(int beginIndex, int endIndex) {
160 if (path == null)
161 return null;
162 String[] parentPath = Arrays.copyOfRange(path, beginIndex, endIndex);
163 return new JcrPath(fs, parentPath, false);
164 }
165
166 @Override
167 public boolean startsWith(Path other) {
168 return toString().startsWith(other.toString());
169 }
170
171 @Override
172 public boolean startsWith(String other) {
173 return toString().startsWith(other);
174 }
175
176 @Override
177 public boolean endsWith(Path other) {
178 return toString().endsWith(other.toString());
179 }
180
181 @Override
182 public boolean endsWith(String other) {
183 return toString().endsWith(other);
184 }
185
186 @Override
187 public Path normalize() {
188 // always normalized
189 return this;
190 }
191
192 @Override
193 public Path resolve(Path other) {
194 JcrPath otherPath = (JcrPath) other;
195 if (otherPath.isAbsolute())
196 return other;
197 String[] newPath;
198 if (path == null) {
199 newPath = new String[otherPath.path.length];
200 System.arraycopy(otherPath.path, 0, newPath, 0, otherPath.path.length);
201 } else {
202 newPath = new String[path.length + otherPath.path.length];
203 System.arraycopy(path, 0, newPath, 0, path.length);
204 System.arraycopy(otherPath.path, 0, newPath, path.length, otherPath.path.length);
205 }
206 return new JcrPath(fs, newPath, absolute);
207 }
208
209 @Override
210 public final Path resolve(String other) {
211 return resolve(getFileSystem().getPath(other));
212 }
213
214 @Override
215 public final Path resolveSibling(Path other) {
216 if (other == null)
217 throw new NullPointerException();
218 Path parent = getParent();
219 return (parent == null) ? other : parent.resolve(other);
220 }
221
222 @Override
223 public final Path resolveSibling(String other) {
224 return resolveSibling(getFileSystem().getPath(other));
225 }
226
227 @Override
228 public final Iterator<Path> iterator() {
229 return new Iterator<Path>() {
230 private int i = 0;
231
232 @Override
233 public boolean hasNext() {
234 return (i < getNameCount());
235 }
236
237 @Override
238 public Path next() {
239 if (i < getNameCount()) {
240 Path result = getName(i);
241 i++;
242 return result;
243 } else {
244 throw new NoSuchElementException();
245 }
246 }
247
248 @Override
249 public void remove() {
250 throw new UnsupportedOperationException();
251 }
252 };
253 }
254
255 @Override
256 public Path relativize(Path other) {
257 if (equals(other))
258 return new JcrPath(fs, "");
259 if (other.startsWith(this)) {
260 String p1 = toString();
261 String p2 = other.toString();
262 String relative = p2.substring(p1.length(), p2.length());
263 if (relative.charAt(0) == '/')
264 relative = relative.substring(1);
265 return new JcrPath(fs, relative);
266 }
267 throw new IllegalArgumentException(other + " cannot be relativized against " + this);
268 }
269
270 @Override
271 public URI toUri() {
272 try {
273 return new URI(fs.provider().getScheme(), toString(), null);
274 } catch (URISyntaxException e) {
275 throw new JcrFsException("Cannot create URI for " + toString(), e);
276 }
277 }
278
279 @Override
280 public Path toAbsolutePath() {
281 if (isAbsolute())
282 return this;
283 return new JcrPath(fs, path, true);
284 }
285
286 @Override
287 public Path toRealPath(LinkOption... options) throws IOException {
288 return this;
289 }
290
291 @Override
292 public File toFile() {
293 throw new UnsupportedOperationException();
294 }
295
296 @Override
297 public WatchKey register(WatchService watcher, Kind<?>[] events, Modifier... modifiers) throws IOException {
298 // TODO Auto-generated method stub
299 return null;
300 }
301
302 @Override
303 public WatchKey register(WatchService watcher, Kind<?>... events) throws IOException {
304 // TODO Auto-generated method stub
305 return null;
306 }
307
308 @Override
309 public int compareTo(Path other) {
310 return toString().compareTo(other.toString());
311 }
312
313 public Node getNode() throws RepositoryException {
314 if (!isAbsolute())// TODO default dir
315 throw new JcrFsException("Cannot get node from relative path");
316 String pathStr = toJcrPath();
317 Session session = fs.getSession();
318 // TODO synchronize on the session ?
319 if (!session.itemExists(pathStr))
320 return null;
321 return session.getNode(pathStr);
322 }
323
324 @Override
325 public boolean equals(Object obj) {
326 if (!(obj instanceof JcrPath))
327 return false;
328 JcrPath other = (JcrPath) obj;
329
330 if (path == null) {// root
331 if (other.path == null)// root
332 return true;
333 else
334 return false;
335 } else {
336 if (other.path == null)// root
337 return false;
338 }
339 // non root
340 if (path.length != other.path.length)
341 return false;
342 for (int i = 0; i < path.length; i++) {
343 if (!path[i].equals(other.path[i]))
344 return false;
345 }
346 return true;
347 }
348
349 @Override
350 public int hashCode() {
351 return hashCode;
352 }
353
354 @Override
355 protected Object clone() throws CloneNotSupportedException {
356 return new JcrPath(fs, toString());
357 }
358
359 @Override
360 protected void finalize() throws Throwable {
361 Arrays.fill(path, null);
362 }
363
364 }