X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.jcr%2Fsrc%2Forg%2Fargeo%2Fjcr%2Ffs%2FJcrFileSystemProvider.java;h=74d9a198e71299e8a08af786494792c74752afb6;hb=46cc2039ac20703c484aa994b830a2da113f2c97;hp=dcc59476ff646b59a97a54567958c325f19bbb84;hpb=cc04167de22122c17425975a86f5a2d7fae53c4f;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.jcr/src/org/argeo/jcr/fs/JcrFileSystemProvider.java b/org.argeo.jcr/src/org/argeo/jcr/fs/JcrFileSystemProvider.java index dcc59476f..74d9a198e 100644 --- a/org.argeo.jcr/src/org/argeo/jcr/fs/JcrFileSystemProvider.java +++ b/org.argeo.jcr/src/org/argeo/jcr/fs/JcrFileSystemProvider.java @@ -25,39 +25,42 @@ import javax.jcr.Node; import javax.jcr.Property; import javax.jcr.PropertyIterator; import javax.jcr.PropertyType; +import javax.jcr.Repository; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.nodetype.NodeType; import javax.jcr.nodetype.PropertyDefinition; -import org.apache.commons.io.FileExistsException; import org.argeo.jcr.JcrUtils; +/** Operations on a {@link JcrFileSystem}. */ public abstract class JcrFileSystemProvider extends FileSystemProvider { + @Override public SeekableByteChannel newByteChannel(Path path, Set options, FileAttribute... attrs) throws IOException { + Node node = toNode(path); try { - Node node = toNode(path); if (node == null) { Node parent = toNode(path.getParent()); if (parent == null) - throw new JcrFsException("No parent directory for " + path); + throw new IOException("No parent directory for " + path); if (parent.getPrimaryNodeType().isNodeType(NodeType.NT_FILE) || parent.getPrimaryNodeType().isNodeType(NodeType.NT_LINKED_FILE)) - throw new JcrFsException(path + " parent is a file"); + throw new IOException(path + " parent is a file"); String fileName = path.getFileName().toString(); fileName = Text.escapeIllegalJcrChars(fileName); node = parent.addNode(fileName, NodeType.NT_FILE); node.addMixin(NodeType.MIX_CREATED); - node.addMixin(NodeType.MIX_LAST_MODIFIED); +// node.addMixin(NodeType.MIX_LAST_MODIFIED); } if (!node.isNodeType(NodeType.NT_FILE)) throw new UnsupportedOperationException(node + " must be a file"); - return new BinaryChannel(node); + return new BinaryChannel(node, path); } catch (RepositoryException e) { - throw new JcrFsException("Cannot read file", e); + discardChanges(node); + throw new IOException("Cannot read file", e); } } @@ -65,82 +68,115 @@ public abstract class JcrFileSystemProvider extends FileSystemProvider { public DirectoryStream newDirectoryStream(Path dir, Filter filter) throws IOException { try { Node base = toNode(dir); - return new NodeDirectoryStream((JcrFileSystem) dir.getFileSystem(), base.getNodes(), filter); + if (base == null) + throw new IOException(dir + " is not a JCR node"); + JcrFileSystem fileSystem = (JcrFileSystem) dir.getFileSystem(); + return new NodeDirectoryStream(fileSystem, base.getNodes(), fileSystem.listDirectMounts(dir), filter); } catch (RepositoryException e) { - throw new JcrFsException("Cannot list directory", e); + throw new IOException("Cannot list directory", e); } } @Override public void createDirectory(Path dir, FileAttribute... attrs) throws IOException { + Node node = toNode(dir); try { - Node node = toNode(dir); if (node == null) { Node parent = toNode(dir.getParent()); if (parent == null) throw new IOException("Parent of " + dir + " does not exist"); - if (parent.getPrimaryNodeType().isNodeType(NodeType.NT_FILE) - || parent.getPrimaryNodeType().isNodeType(NodeType.NT_LINKED_FILE)) - throw new JcrFsException(dir + " parent is a file"); - String fileName = dir.getFileName().toString(); - fileName = Text.escapeIllegalJcrChars(fileName); - node = parent.addNode(fileName, NodeType.NT_FOLDER); - node.addMixin(NodeType.MIX_CREATED); - node.addMixin(NodeType.MIX_LAST_MODIFIED); - node.getSession().save(); + Session session = parent.getSession(); + synchronized (session) { + if (parent.getPrimaryNodeType().isNodeType(NodeType.NT_FILE) + || parent.getPrimaryNodeType().isNodeType(NodeType.NT_LINKED_FILE)) + throw new IOException(dir + " parent is a file"); + String fileName = dir.getFileName().toString(); + fileName = Text.escapeIllegalJcrChars(fileName); + node = parent.addNode(fileName, NodeType.NT_FOLDER); + node.addMixin(NodeType.MIX_CREATED); + node.addMixin(NodeType.MIX_LAST_MODIFIED); + save(session); + } } else { - if (!node.getPrimaryNodeType().isNodeType(NodeType.NT_FOLDER)) - throw new FileExistsException(dir + " exists and is not a directory"); + // if (!node.getPrimaryNodeType().isNodeType(NodeType.NT_FOLDER)) + // throw new FileExistsException(dir + " exists and is not a directory"); } } catch (RepositoryException e) { - throw new JcrFsException("Cannot create directory " + dir, e); + discardChanges(node); + throw new IOException("Cannot create directory " + dir, e); } - } @Override public void delete(Path path) throws IOException { + Node node = toNode(path); try { - Node node = toNode(path); if (node == null) throw new NoSuchFileException(path + " does not exist"); Session session = node.getSession(); - if (node.getPrimaryNodeType().isNodeType(NodeType.NT_FILE)) - node.remove(); - else if (node.getPrimaryNodeType().isNodeType(NodeType.NT_FOLDER)) { - if (node.hasNodes())// TODO check only files - throw new DirectoryNotEmptyException(path.toString()); - node.remove(); + synchronized (session) { + session.refresh(false); + if (node.getPrimaryNodeType().isNodeType(NodeType.NT_FILE)) + node.remove(); + else if (node.getPrimaryNodeType().isNodeType(NodeType.NT_FOLDER)) { + if (node.hasNodes())// TODO check only files + throw new DirectoryNotEmptyException(path.toString()); + node.remove(); + } + save(session); } - session.save(); } catch (RepositoryException e) { - throw new JcrFsException("Cannot delete " + path, e); + discardChanges(node); + throw new IOException("Cannot delete " + path, e); } } @Override public void copy(Path source, Path target, CopyOption... options) throws IOException { + Node sourceNode = toNode(source); + Node targetNode = toNode(target); try { - Node sourceNode = toNode(source); - Node targetNode = toNode(target); - JcrUtils.copy(sourceNode, targetNode); - sourceNode.getSession().save(); + Session targetSession = targetNode.getSession(); + synchronized (targetSession) { + JcrUtils.copy(sourceNode, targetNode); + save(targetSession); + } } catch (RepositoryException e) { - throw new JcrFsException("Cannot copy from " + source + " to " + target, e); + discardChanges(sourceNode); + discardChanges(targetNode); + throw new IOException("Cannot copy from " + source + " to " + target, e); } } @Override public void move(Path source, Path target, CopyOption... options) throws IOException { + JcrFileSystem sourceFileSystem = (JcrFileSystem) source.getFileSystem(); + WorkspaceFileStore sourceStore = sourceFileSystem.getFileStore(source.toString()); + WorkspaceFileStore targetStore = sourceFileSystem.getFileStore(target.toString()); try { - Node sourceNode = toNode(source); - Session session = sourceNode.getSession(); - session.move(sourceNode.getPath(), target.toString()); - session.save(); + if (sourceStore.equals(targetStore)) { + sourceStore.getWorkspace().move(sourceStore.toJcrPath(source.toString()), + targetStore.toJcrPath(target.toString())); + } else { + // TODO implement it + throw new UnsupportedOperationException("Can only move paths within the same workspace."); + } } catch (RepositoryException e) { - throw new JcrFsException("Cannot move from " + source + " to " + target, e); + throw new IOException("Cannot move from " + source + " to " + target, e); } + +// Node sourceNode = toNode(source); +// try { +// Session session = sourceNode.getSession(); +// synchronized (session) { +// session.move(sourceNode.getPath(), target.toString()); +// save(session); +// } +// } catch (RepositoryException e) { +// discardChanges(sourceNode); +// throw new IOException("Cannot move from " + source + " to " + target, e); +// } } @Override @@ -156,7 +192,7 @@ public abstract class JcrFileSystemProvider extends FileSystemProvider { Node node2 = toNode(path2); return node.isSame(node2); } catch (RepositoryException e) { - throw new JcrFsException("Cannot check whether " + path + " and " + path2 + " are same", e); + throw new IOException("Cannot check whether " + path + " and " + path2 + " are same", e); } } @@ -164,25 +200,21 @@ public abstract class JcrFileSystemProvider extends FileSystemProvider { @Override public boolean isHidden(Path path) throws IOException { - return false; + return path.getFileName().toString().charAt(0) == '.'; } @Override public FileStore getFileStore(Path path) throws IOException { - Session session = ((JcrFileSystem) path.getFileSystem()).getSession(); - return new WorkSpaceFileStore(session.getWorkspace()); + JcrFileSystem fileSystem = (JcrFileSystem) path.getFileSystem(); + return fileSystem.getFileStore(path.toString()); } @Override public void checkAccess(Path path, AccessMode... modes) throws IOException { - try { - Session session = ((JcrFileSystem) path.getFileSystem()).getSession(); - if (!session.itemExists(path.toString())) - throw new NoSuchFileException(path + " does not exist"); - // TODO check access via JCR api - } catch (RepositoryException e) { - throw new JcrFsException("Cannot delete " + path, e); - } + Node node = toNode(path); + if (node == null) + throw new NoSuchFileException(path + " does not exist"); + // TODO check access via JCR api } @Override @@ -194,13 +226,12 @@ public abstract class JcrFileSystemProvider extends FileSystemProvider { @Override public A readAttributes(Path path, Class type, LinkOption... options) throws IOException { - try { - // TODO check if assignable - Node node = toNode(path); - return (A) new JcrBasicfileAttributes(node); - } catch (RepositoryException e) { - throw new JcrFsException("Cannot read basic attributes of " + path, e); + // TODO check if assignable + Node node = toNode(path); + if (node == null) { + throw new IOException("JCR node not found for " + path); } + return (A) new JcrBasicfileAttributes(node); } @Override @@ -239,29 +270,68 @@ public abstract class JcrFileSystemProvider extends FileSystemProvider { } return res; } catch (RepositoryException e) { - throw new JcrFsException("Cannot read attributes of " + path, e); + throw new IOException("Cannot read attributes of " + path, e); } } @Override public void setAttribute(Path path, String attribute, Object value, LinkOption... options) throws IOException { + Node node = toNode(path); try { - Node node = toNode(path); - if (value instanceof byte[]) { - JcrUtils.setBinaryAsBytes(node, attribute, (byte[]) value); - } else if (value instanceof Calendar) { - node.setProperty(attribute, (Calendar) value); - } else { - node.setProperty(attribute, value.toString()); + Session session = node.getSession(); + synchronized (session) { + if (value instanceof byte[]) { + JcrUtils.setBinaryAsBytes(node, attribute, (byte[]) value); + } else if (value instanceof Calendar) { + node.setProperty(attribute, (Calendar) value); + } else { + node.setProperty(attribute, value.toString()); + } + save(session); } - node.getSession().save(); } catch (RepositoryException e) { - throw new JcrFsException("Cannot set attribute " + attribute + " on " + path, e); + discardChanges(node); + throw new IOException("Cannot set attribute " + attribute + " on " + path, e); + } + } + + protected Node toNode(Path path) { + try { + return ((JcrPath) path).getNode(); + } catch (RepositoryException e) { + throw new JcrFsException("Cannot convert path " + path + " to JCR Node", e); } } - protected Node toNode(Path path) throws RepositoryException { - return ((JcrPath) path).getNode(); + /** Discard changes in the underlying session */ + protected void discardChanges(Node node) { + if (node == null) + return; + try { + // discard changes + node.getSession().refresh(false); + } catch (RepositoryException e) { + e.printStackTrace(); + // TODO log out session? + // TODO use Commons logging? + } + } + + /** Make sure save is robust. */ + protected void save(Session session) throws RepositoryException { + session.refresh(true); + session.save(); + session.notifyAll(); + } + + /** + * To be overriden in order to support the ~ path, with an implementation + * specific concept of user home. + * + * @return null by default + */ + public Node getUserHome(Repository session) { + return null; } }