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<? extends OpenOption> 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)
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) {
+ discardChanges(node);
throw new IOException("Cannot read file", e);
}
}
public DirectoryStream<Path> newDirectoryStream(Path dir, Filter<? super Path> 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 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 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);
- 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) {
+ 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) {
+ 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) {
+ 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 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
@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 IOException("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
@Override
public <A extends BasicFileAttributes> A readAttributes(Path path, Class<A> type, LinkOption... options)
throws IOException {
- try {
- // 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);
- } catch (RepositoryException e) {
- throw new IOException("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
@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) {
+ discardChanges(node);
throw new IOException("Cannot set attribute " + attribute + " on " + path, e);
}
}
- protected Node toNode(Path path) throws RepositoryException {
- return ((JcrPath) path).getNode();
+ protected Node toNode(Path path) {
+ try {
+ return ((JcrPath) path).getNode();
+ } catch (RepositoryException e) {
+ throw new JcrFsException("Cannot convert path " + path + " to JCR Node", e);
+ }
+ }
+
+ /** 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();
}
/**
*
* @return null by default
*/
- public Node getUserHome(Session session) {
+ public Node getUserHome(Repository session) {
return null;
}
+
}