X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.jcr%2Fsrc%2Forg%2Fargeo%2Fjcr%2Ffs%2FJcrPath.java;h=1a4d747067b1a20baa29d35683256c9efa3dde68;hb=8e5934c1ff5587a5156854839210cc93bb66fc41;hp=e25293517bcc4dfc298b5fec2c2803302a0e2957;hpb=e66b9893b0e511f8ab295e3cee42b7dc966f1597;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.jcr/src/org/argeo/jcr/fs/JcrPath.java b/org.argeo.jcr/src/org/argeo/jcr/fs/JcrPath.java index e25293517..1a4d74706 100644 --- a/org.argeo.jcr/src/org/argeo/jcr/fs/JcrPath.java +++ b/org.argeo.jcr/src/org/argeo/jcr/fs/JcrPath.java @@ -3,6 +3,7 @@ package org.argeo.jcr.fs; import java.io.File; import java.io.IOException; import java.net.URI; +import java.net.URISyntaxException; import java.nio.file.FileSystem; import java.nio.file.LinkOption; import java.nio.file.Path; @@ -10,147 +11,308 @@ import java.nio.file.WatchEvent.Kind; import java.nio.file.WatchEvent.Modifier; import java.nio.file.WatchKey; import java.nio.file.WatchService; +import java.util.Arrays; import java.util.Iterator; +import java.util.NoSuchElementException; import javax.jcr.Node; import javax.jcr.RepositoryException; +/** A {@link Path} which contains a reference to a JCR {@link Node}. */ public class JcrPath implements Path { - private JcrFileSystem filesSystem; - private String path; + final static String separator = "/"; + final static char separatorChar = '/'; + + private final JcrFileSystem fs; + /** null for non absolute paths */ + private final WorkspaceFileStore fileStore; + private final String[] path;// null means root + private final boolean absolute; + + // optim + private final int hashCode; + + public JcrPath(JcrFileSystem filesSystem, String path) { + this.fs = filesSystem; + if (path == null) + throw new JcrFsException("Path cannot be null"); + if (path.equals(separator)) {// root + this.path = null; + this.absolute = true; + this.hashCode = 0; + this.fileStore = fs.getBaseFileStore(); + return; + } else if (path.equals("")) {// empty path + this.path = new String[] { "" }; + this.absolute = false; + this.fileStore = null; + this.hashCode = "".hashCode(); + return; + } + + if (path.equals("~")) {// home + path = filesSystem.getUserHomePath(); + if (path == null) + throw new JcrFsException("No home directory available"); + } + + this.absolute = path.charAt(0) == separatorChar ? true : false; + + this.fileStore = absolute ? fs.getFileStore(path) : null; - private Node node; + String trimmedPath = path.substring(absolute ? 1 : 0, + path.charAt(path.length() - 1) == separatorChar ? path.length() - 1 : path.length()); + this.path = trimmedPath.split(separator); + for (int i = 0; i < this.path.length; i++) { + this.path[i] = Text.unescapeIllegalJcrChars(this.path[i]); + } + this.hashCode = this.path[this.path.length - 1].hashCode(); + assert !(absolute && fileStore == null); + } - public JcrPath(JcrFileSystem filesSystem, Node node) { - super(); - this.filesSystem = filesSystem; - this.node = node; + public JcrPath(JcrFileSystem filesSystem, Node node) throws RepositoryException { + this(filesSystem, filesSystem.getFileStore(node).toFsPath(node)); + } + + /** Internal optimisation */ + private JcrPath(JcrFileSystem filesSystem, WorkspaceFileStore fileStore, String[] path, boolean absolute) { + this.fs = filesSystem; + this.path = path; + this.absolute = path == null ? true : absolute; + if (this.absolute && fileStore == null) + throw new IllegalArgumentException("Absolute path requires a file store"); + if (!this.absolute && fileStore != null) + throw new IllegalArgumentException("A file store should not be provided for a relative path"); + this.fileStore = fileStore; + this.hashCode = path == null ? 0 : path[path.length - 1].hashCode(); + assert !(absolute && fileStore == null); } @Override public FileSystem getFileSystem() { - return filesSystem; + return fs; } @Override public boolean isAbsolute() { - return path.startsWith("/"); + return absolute; } @Override public Path getRoot() { - try { - return new JcrPath(filesSystem, node.getSession().getRootNode()); - } catch (RepositoryException e) { - throw new JcrFsException("Cannot get root", e); + if (path == null) + return this; + return new JcrPath(fs, separator); + } + + @Override + public String toString() { + return toFsPath(path); + } + + private String toFsPath(String[] path) { + if (path == null) + return "/"; + StringBuilder sb = new StringBuilder(); + if (isAbsolute()) + sb.append('/'); + for (int i = 0; i < path.length; i++) { + if (i != 0) + sb.append('/'); + sb.append(path[i]); } + return sb.toString(); } +// @Deprecated +// private String toJcrPath() { +// return toJcrPath(path); +// } +// +// @Deprecated +// private String toJcrPath(String[] path) { +// if (path == null) +// return "/"; +// StringBuilder sb = new StringBuilder(); +// if (isAbsolute()) +// sb.append('/'); +// for (int i = 0; i < path.length; i++) { +// if (i != 0) +// sb.append('/'); +// sb.append(Text.escapeIllegalJcrChars(path[i])); +// } +// return sb.toString(); +// } + @Override public Path getFileName() { - return null; + if (path == null) + return null; + return new JcrPath(fs, path[path.length - 1]); } @Override public Path getParent() { - // TODO Auto-generated method stub - return null; + if (path == null) + return null; + if (path.length == 1)// root + return new JcrPath(fs, separator); + String[] parentPath = Arrays.copyOfRange(path, 0, path.length - 1); + if (!absolute) + return new JcrPath(fs, null, parentPath, absolute); + else + return new JcrPath(fs, toFsPath(parentPath)); } @Override public int getNameCount() { - // TODO Auto-generated method stub - return 0; + if (path == null) + return 0; + return path.length; } @Override public Path getName(int index) { - // TODO Auto-generated method stub - return null; + if (path == null) + return null; + return new JcrPath(fs, path[index]); } @Override public Path subpath(int beginIndex, int endIndex) { - // TODO Auto-generated method stub - return null; + if (path == null) + return null; + String[] parentPath = Arrays.copyOfRange(path, beginIndex, endIndex); + return new JcrPath(fs, null, parentPath, false); } @Override public boolean startsWith(Path other) { - // TODO Auto-generated method stub - return false; + return toString().startsWith(other.toString()); } @Override public boolean startsWith(String other) { - // TODO Auto-generated method stub - return false; + return toString().startsWith(other); } @Override public boolean endsWith(Path other) { - // TODO Auto-generated method stub - return false; + return toString().endsWith(other.toString()); } @Override public boolean endsWith(String other) { - // TODO Auto-generated method stub - return false; + return toString().endsWith(other); } @Override public Path normalize() { - // TODO Auto-generated method stub - return null; + // always normalized + return this; } @Override public Path resolve(Path other) { - // TODO Auto-generated method stub - return null; + JcrPath otherPath = (JcrPath) other; + if (otherPath.isAbsolute()) + return other; + String[] newPath; + if (path == null) { + newPath = new String[otherPath.path.length]; + System.arraycopy(otherPath.path, 0, newPath, 0, otherPath.path.length); + } else { + newPath = new String[path.length + otherPath.path.length]; + System.arraycopy(path, 0, newPath, 0, path.length); + System.arraycopy(otherPath.path, 0, newPath, path.length, otherPath.path.length); + } + if (!absolute) + return new JcrPath(fs, null, newPath, absolute); + else { + return new JcrPath(fs, toFsPath(newPath)); + } } @Override - public Path resolve(String other) { - // TODO Auto-generated method stub - return null; + public final Path resolve(String other) { + return resolve(getFileSystem().getPath(other)); } @Override - public Path resolveSibling(Path other) { - // TODO Auto-generated method stub - return null; + public final Path resolveSibling(Path other) { + if (other == null) + throw new NullPointerException(); + Path parent = getParent(); + return (parent == null) ? other : parent.resolve(other); } @Override - public Path resolveSibling(String other) { - // TODO Auto-generated method stub - return null; + public final Path resolveSibling(String other) { + return resolveSibling(getFileSystem().getPath(other)); + } + + @Override + public final Iterator iterator() { + return new Iterator() { + private int i = 0; + + @Override + public boolean hasNext() { + return (i < getNameCount()); + } + + @Override + public Path next() { + if (i < getNameCount()) { + Path result = getName(i); + i++; + return result; + } else { + throw new NoSuchElementException(); + } + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; } @Override public Path relativize(Path other) { - // TODO Auto-generated method stub - return null; + if (equals(other)) + return new JcrPath(fs, ""); + if (other.startsWith(this)) { + String p1 = toString(); + String p2 = other.toString(); + String relative = p2.substring(p1.length(), p2.length()); + if (relative.charAt(0) == '/') + relative = relative.substring(1); + return new JcrPath(fs, relative); + } + throw new IllegalArgumentException(other + " cannot be relativized against " + this); } @Override public URI toUri() { - // TODO Auto-generated method stub - return null; + try { + return new URI(fs.provider().getScheme(), toString(), null); + } catch (URISyntaxException e) { + throw new JcrFsException("Cannot create URI for " + toString(), e); + } } @Override public Path toAbsolutePath() { - // TODO Auto-generated method stub - return null; + if (isAbsolute()) + return this; + return new JcrPath(fs, fileStore, path, true); } @Override public Path toRealPath(LinkOption... options) throws IOException { - // TODO Auto-generated method stub - return null; + return this; } @Override @@ -159,41 +321,73 @@ public class JcrPath implements Path { } @Override - public WatchKey register(WatchService watcher, Kind[] events, - Modifier... modifiers) throws IOException { + public WatchKey register(WatchService watcher, Kind[] events, Modifier... modifiers) throws IOException { // TODO Auto-generated method stub return null; } @Override - public WatchKey register(WatchService watcher, Kind... events) - throws IOException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Iterator iterator() { + public WatchKey register(WatchService watcher, Kind... events) throws IOException { // TODO Auto-generated method stub return null; } @Override public int compareTo(Path other) { - // TODO Auto-generated method stub - return 0; + return toString().compareTo(other.toString()); } - public Node getNode() { + public Node getNode() throws RepositoryException { if (!isAbsolute())// TODO default dir - throw new JcrFsException("Cannot get node from relative path"); - try { - if (node == null) - node = filesSystem.getSession().getNode(path); - return node; - } catch (RepositoryException e) { - throw new JcrFsException("Cannot get node", e); + throw new JcrFsException("Cannot get a JCR node from a relative path"); + assert fileStore != null; + return fileStore.toNode(path); +// String pathStr = toJcrPath(); +// Session session = fs.getSession(); +// // TODO synchronize on the session ? +// if (!session.itemExists(pathStr)) +// return null; +// return session.getNode(pathStr); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof JcrPath)) + return false; + JcrPath other = (JcrPath) obj; + + if (path == null) {// root + if (other.path == null)// root + return true; + else + return false; + } else { + if (other.path == null)// root + return false; + } + // non root + if (path.length != other.path.length) + return false; + for (int i = 0; i < path.length; i++) { + if (!path[i].equals(other.path[i])) + return false; } + return true; + } + + @Override + public int hashCode() { + return hashCode; + } + + @Override + protected Object clone() throws CloneNotSupportedException { + return new JcrPath(fs, toString()); + } + + @Override + protected void finalize() throws Throwable { + Arrays.fill(path, null); } }