1 package org
.argeo
.jcr
.fs
;
4 import java
.io
.IOException
;
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
;
18 import javax
.jcr
.Node
;
19 import javax
.jcr
.RepositoryException
;
21 /** A {@link Path} which contains a reference to a JCR {@link Node}. */
22 public class JcrPath
implements Path
{
23 final static String separator
= "/";
24 final static char separatorChar
= '/';
26 private final JcrFileSystem fs
;
27 /** null for non absolute paths */
28 private final WorkspaceFileStore fileStore
;
29 private final String
[] path
;// null means root
30 private final boolean absolute
;
33 private final int hashCode
;
35 public JcrPath(JcrFileSystem filesSystem
, String path
) {
36 this.fs
= filesSystem
;
38 throw new JcrFsException("Path cannot be null");
39 if (path
.equals(separator
)) {// root
43 this.fileStore
= fs
.getBaseFileStore();
45 } else if (path
.equals("")) {// empty path
46 this.path
= new String
[] { "" };
47 this.absolute
= false;
48 this.fileStore
= null;
49 this.hashCode
= "".hashCode();
53 if (path
.equals("~")) {// home
54 path
= filesSystem
.getUserHomePath();
56 throw new JcrFsException("No home directory available");
59 this.absolute
= path
.charAt(0) == separatorChar ?
true : false;
61 this.fileStore
= absolute ? fs
.getFileStore(path
) : null;
63 String trimmedPath
= path
.substring(absolute ?
1 : 0,
64 path
.charAt(path
.length() - 1) == separatorChar ? path
.length() - 1 : path
.length());
65 this.path
= trimmedPath
.split(separator
);
66 for (int i
= 0; i
< this.path
.length
; i
++) {
67 this.path
[i
] = Text
.unescapeIllegalJcrChars(this.path
[i
]);
69 this.hashCode
= this.path
[this.path
.length
- 1].hashCode();
70 assert !(absolute
&& fileStore
== null);
73 public JcrPath(JcrFileSystem filesSystem
, Node node
) throws RepositoryException
{
74 this(filesSystem
, filesSystem
.getFileStore(node
).toFsPath(node
));
77 /** Internal optimisation */
78 private JcrPath(JcrFileSystem filesSystem
, WorkspaceFileStore fileStore
, String
[] path
, boolean absolute
) {
79 this.fs
= filesSystem
;
81 this.absolute
= path
== null ?
true : absolute
;
82 if (this.absolute
&& fileStore
== null)
83 throw new IllegalArgumentException("Absolute path requires a file store");
84 if (!this.absolute
&& fileStore
!= null)
85 throw new IllegalArgumentException("A file store should not be provided for a relative path");
86 this.fileStore
= fileStore
;
87 this.hashCode
= path
== null ?
0 : path
[path
.length
- 1].hashCode();
88 assert !(absolute
&& fileStore
== null);
92 public FileSystem
getFileSystem() {
97 public boolean isAbsolute() {
102 public Path
getRoot() {
105 return new JcrPath(fs
, separator
);
109 public String
toString() {
110 return toFsPath(path
);
113 private String
toFsPath(String
[] path
) {
116 StringBuilder sb
= new StringBuilder();
119 for (int i
= 0; i
< path
.length
; i
++) {
124 return sb
.toString();
128 // private String toJcrPath() {
129 // return toJcrPath(path);
133 // private String toJcrPath(String[] path) {
136 // StringBuilder sb = new StringBuilder();
139 // for (int i = 0; i < path.length; i++) {
142 // sb.append(Text.escapeIllegalJcrChars(path[i]));
144 // return sb.toString();
148 public Path
getFileName() {
151 return new JcrPath(fs
, path
[path
.length
- 1]);
155 public Path
getParent() {
158 if (path
.length
== 1)// root
159 return new JcrPath(fs
, separator
);
160 String
[] parentPath
= Arrays
.copyOfRange(path
, 0, path
.length
- 1);
162 return new JcrPath(fs
, null, parentPath
, absolute
);
164 return new JcrPath(fs
, toFsPath(parentPath
));
168 public int getNameCount() {
175 public Path
getName(int index
) {
178 return new JcrPath(fs
, path
[index
]);
182 public Path
subpath(int beginIndex
, int endIndex
) {
185 String
[] parentPath
= Arrays
.copyOfRange(path
, beginIndex
, endIndex
);
186 return new JcrPath(fs
, null, parentPath
, false);
190 public boolean startsWith(Path other
) {
191 return toString().startsWith(other
.toString());
195 public boolean startsWith(String other
) {
196 return toString().startsWith(other
);
200 public boolean endsWith(Path other
) {
201 return toString().endsWith(other
.toString());
205 public boolean endsWith(String other
) {
206 return toString().endsWith(other
);
210 public Path
normalize() {
216 public Path
resolve(Path other
) {
217 JcrPath otherPath
= (JcrPath
) other
;
218 if (otherPath
.isAbsolute())
222 newPath
= new String
[otherPath
.path
.length
];
223 System
.arraycopy(otherPath
.path
, 0, newPath
, 0, otherPath
.path
.length
);
225 newPath
= new String
[path
.length
+ otherPath
.path
.length
];
226 System
.arraycopy(path
, 0, newPath
, 0, path
.length
);
227 System
.arraycopy(otherPath
.path
, 0, newPath
, path
.length
, otherPath
.path
.length
);
230 return new JcrPath(fs
, null, newPath
, absolute
);
232 return new JcrPath(fs
, toFsPath(newPath
));
237 public final Path
resolve(String other
) {
238 return resolve(getFileSystem().getPath(other
));
242 public final Path
resolveSibling(Path other
) {
244 throw new NullPointerException();
245 Path parent
= getParent();
246 return (parent
== null) ? other
: parent
.resolve(other
);
250 public final Path
resolveSibling(String other
) {
251 return resolveSibling(getFileSystem().getPath(other
));
255 public final Iterator
<Path
> iterator() {
256 return new Iterator
<Path
>() {
260 public boolean hasNext() {
261 return (i
< getNameCount());
266 if (i
< getNameCount()) {
267 Path result
= getName(i
);
271 throw new NoSuchElementException();
276 public void remove() {
277 throw new UnsupportedOperationException();
283 public Path
relativize(Path other
) {
285 return new JcrPath(fs
, "");
286 if (other
.startsWith(this)) {
287 String p1
= toString();
288 String p2
= other
.toString();
289 String relative
= p2
.substring(p1
.length(), p2
.length());
290 if (relative
.charAt(0) == '/')
291 relative
= relative
.substring(1);
292 return new JcrPath(fs
, relative
);
294 throw new IllegalArgumentException(other
+ " cannot be relativized against " + this);
300 return new URI(fs
.provider().getScheme(), toString(), null);
301 } catch (URISyntaxException e
) {
302 throw new JcrFsException("Cannot create URI for " + toString(), e
);
307 public Path
toAbsolutePath() {
310 return new JcrPath(fs
, fileStore
, path
, true);
314 public Path
toRealPath(LinkOption
... options
) throws IOException
{
319 public File
toFile() {
320 throw new UnsupportedOperationException();
324 public WatchKey
register(WatchService watcher
, Kind
<?
>[] events
, Modifier
... modifiers
) throws IOException
{
325 // TODO Auto-generated method stub
330 public WatchKey
register(WatchService watcher
, Kind
<?
>... events
) throws IOException
{
331 // TODO Auto-generated method stub
336 public int compareTo(Path other
) {
337 return toString().compareTo(other
.toString());
340 public Node
getNode() throws RepositoryException
{
341 if (!isAbsolute())// TODO default dir
342 throw new JcrFsException("Cannot get a JCR node from a relative path");
343 assert fileStore
!= null;
344 return fileStore
.toNode(path
);
345 // String pathStr = toJcrPath();
346 // Session session = fs.getSession();
347 // // TODO synchronize on the session ?
348 // if (!session.itemExists(pathStr))
350 // return session.getNode(pathStr);
354 public boolean equals(Object obj
) {
355 if (!(obj
instanceof JcrPath
))
357 JcrPath other
= (JcrPath
) obj
;
359 if (path
== null) {// root
360 if (other
.path
== null)// root
365 if (other
.path
== null)// root
369 if (path
.length
!= other
.path
.length
)
371 for (int i
= 0; i
< path
.length
; i
++) {
372 if (!path
[i
].equals(other
.path
[i
]))
379 public int hashCode() {
384 protected Object
clone() throws CloneNotSupportedException
{
385 return new JcrPath(fs
, toString());
389 protected void finalize() throws Throwable
{
390 Arrays
.fill(path
, null);