]> git.argeo.org Git - lgpl/argeo-commons.git/blob - fs/JcrFileSystemProvider.java
Prepare next development cycle
[lgpl/argeo-commons.git] / fs / JcrFileSystemProvider.java
1 package org.argeo.jcr.fs;
2
3 import java.io.IOException;
4 import java.nio.channels.SeekableByteChannel;
5 import java.nio.file.AccessMode;
6 import java.nio.file.CopyOption;
7 import java.nio.file.DirectoryNotEmptyException;
8 import java.nio.file.DirectoryStream;
9 import java.nio.file.DirectoryStream.Filter;
10 import java.nio.file.FileStore;
11 import java.nio.file.LinkOption;
12 import java.nio.file.NoSuchFileException;
13 import java.nio.file.OpenOption;
14 import java.nio.file.Path;
15 import java.nio.file.attribute.BasicFileAttributes;
16 import java.nio.file.attribute.FileAttribute;
17 import java.nio.file.attribute.FileAttributeView;
18 import java.nio.file.spi.FileSystemProvider;
19 import java.util.Calendar;
20 import java.util.HashMap;
21 import java.util.Map;
22 import java.util.Set;
23
24 import javax.jcr.Node;
25 import javax.jcr.Property;
26 import javax.jcr.PropertyIterator;
27 import javax.jcr.PropertyType;
28 import javax.jcr.RepositoryException;
29 import javax.jcr.Session;
30 import javax.jcr.nodetype.NodeType;
31 import javax.jcr.nodetype.PropertyDefinition;
32
33 import org.apache.commons.io.FileExistsException;
34 import org.argeo.jcr.JcrUtils;
35
36 public abstract class JcrFileSystemProvider extends FileSystemProvider {
37 @Override
38 public SeekableByteChannel newByteChannel(Path path, Set<? extends OpenOption> options, FileAttribute<?>... attrs)
39 throws IOException {
40 try {
41 Node node = toNode(path);
42 if (node == null) {
43 Node parent = toNode(path.getParent());
44 if (parent == null)
45 throw new JcrFsException("No parent directory for " + path);
46 if (parent.getPrimaryNodeType().isNodeType(NodeType.NT_FILE)
47 || parent.getPrimaryNodeType().isNodeType(NodeType.NT_LINKED_FILE))
48 throw new JcrFsException(path + " parent is a file");
49
50 node = parent.addNode(path.getFileName().toString(), NodeType.NT_FILE);
51 node.addMixin(NodeType.MIX_CREATED);
52 node.addMixin(NodeType.MIX_LAST_MODIFIED);
53 }
54 if (!node.isNodeType(NodeType.NT_FILE))
55 throw new UnsupportedOperationException(node + " must be a file");
56 return new BinaryChannel(node);
57 } catch (RepositoryException e) {
58 throw new JcrFsException("Cannot read file", e);
59 }
60 }
61
62 @Override
63 public DirectoryStream<Path> newDirectoryStream(Path dir, Filter<? super Path> filter) throws IOException {
64 try {
65 Node base = toNode(dir);
66 return new NodeDirectoryStream((JcrFileSystem) dir.getFileSystem(), base.getNodes(), filter);
67 } catch (RepositoryException e) {
68 throw new JcrFsException("Cannot list directory", e);
69 }
70 }
71
72 @Override
73 public void createDirectory(Path dir, FileAttribute<?>... attrs) throws IOException {
74 try {
75 Node node = toNode(dir);
76 if (node == null) {
77 Node parent = toNode(dir.getParent());
78 if (parent == null)
79 throw new IOException("Parent of " + dir + " does not exist");
80 if (parent.getPrimaryNodeType().isNodeType(NodeType.NT_FILE)
81 || parent.getPrimaryNodeType().isNodeType(NodeType.NT_LINKED_FILE))
82 throw new JcrFsException(dir + " parent is a file");
83 node = parent.addNode(dir.getFileName().toString(), NodeType.NT_FOLDER);
84 node.addMixin(NodeType.MIX_CREATED);
85 node.addMixin(NodeType.MIX_LAST_MODIFIED);
86 node.getSession().save();
87 } else {
88 if (!node.getPrimaryNodeType().isNodeType(NodeType.NT_FOLDER))
89 throw new FileExistsException(dir + " exists and is not a directory");
90 }
91 } catch (RepositoryException e) {
92 throw new JcrFsException("Cannot create directory " + dir, e);
93 }
94
95 }
96
97 @Override
98 public void delete(Path path) throws IOException {
99 try {
100 Node node = toNode(path);
101 if (node == null)
102 throw new NoSuchFileException(path + " does not exist");
103 Session session = node.getSession();
104 if (node.getPrimaryNodeType().isNodeType(NodeType.NT_FILE))
105 node.remove();
106 else if (node.getPrimaryNodeType().isNodeType(NodeType.NT_FOLDER)) {
107 if (node.hasNodes())// TODO check only files
108 throw new DirectoryNotEmptyException(path.toString());
109 node.remove();
110 }
111 session.save();
112 } catch (RepositoryException e) {
113 throw new JcrFsException("Cannot delete " + path, e);
114 }
115
116 }
117
118 @Override
119 public void copy(Path source, Path target, CopyOption... options) throws IOException {
120 try {
121 Node sourceNode = toNode(source);
122 Node targetNode = toNode(target);
123 JcrUtils.copy(sourceNode, targetNode);
124 sourceNode.getSession().save();
125 } catch (RepositoryException e) {
126 throw new JcrFsException("Cannot copy from " + source + " to " + target, e);
127 }
128 }
129
130 @Override
131 public void move(Path source, Path target, CopyOption... options) throws IOException {
132 try {
133 Node sourceNode = toNode(source);
134 Session session = sourceNode.getSession();
135 session.move(sourceNode.getPath(), target.toString());
136 session.save();
137 } catch (RepositoryException e) {
138 throw new JcrFsException("Cannot move from " + source + " to " + target, e);
139 }
140 }
141
142 @Override
143 public boolean isSameFile(Path path, Path path2) throws IOException {
144 if (path.getFileSystem() != path2.getFileSystem())
145 return false;
146 boolean equ = path.equals(path2);
147 if (equ)
148 return true;
149 else {
150 try {
151 Node node = toNode(path);
152 Node node2 = toNode(path2);
153 return node.isSame(node2);
154 } catch (RepositoryException e) {
155 throw new JcrFsException("Cannot check whether " + path + " and " + path2 + " are same", e);
156 }
157 }
158
159 }
160
161 @Override
162 public boolean isHidden(Path path) throws IOException {
163 return false;
164 }
165
166 @Override
167 public FileStore getFileStore(Path path) throws IOException {
168 Session session = ((JcrFileSystem) path.getFileSystem()).getSession();
169 return new WorkSpaceFileStore(session.getWorkspace());
170 }
171
172 @Override
173 public void checkAccess(Path path, AccessMode... modes) throws IOException {
174 try {
175 Session session = ((JcrFileSystem) path.getFileSystem()).getSession();
176 if (!session.itemExists(path.toString()))
177 throw new NoSuchFileException(path + " does not exist");
178 // TODO check access via JCR api
179 } catch (RepositoryException e) {
180 throw new JcrFsException("Cannot delete " + path, e);
181 }
182 }
183
184 @Override
185 public <V extends FileAttributeView> V getFileAttributeView(Path path, Class<V> type, LinkOption... options) {
186 throw new UnsupportedOperationException();
187 }
188
189 @SuppressWarnings("unchecked")
190 @Override
191 public <A extends BasicFileAttributes> A readAttributes(Path path, Class<A> type, LinkOption... options)
192 throws IOException {
193 try {
194 // TODO check if assignable
195 Node node = toNode(path);
196 return (A) new JcrBasicfileAttributes(node);
197 } catch (RepositoryException e) {
198 throw new JcrFsException("Cannot read basic attributes of " + path, e);
199 }
200 }
201
202 @Override
203 public Map<String, Object> readAttributes(Path path, String attributes, LinkOption... options) throws IOException {
204 try {
205 Node node = toNode(path);
206 String pattern = attributes.replace(',', '|');
207 Map<String, Object> res = new HashMap<String, Object>();
208 PropertyIterator it = node.getProperties(pattern);
209 props: while (it.hasNext()) {
210 Property prop = it.nextProperty();
211 PropertyDefinition pd = prop.getDefinition();
212 if (pd.isMultiple())
213 continue props;
214 int requiredType = pd.getRequiredType();
215 switch (requiredType) {
216 case PropertyType.LONG:
217 res.put(prop.getName(), prop.getLong());
218 break;
219 case PropertyType.DOUBLE:
220 res.put(prop.getName(), prop.getDouble());
221 break;
222 case PropertyType.BOOLEAN:
223 res.put(prop.getName(), prop.getBoolean());
224 break;
225 case PropertyType.DATE:
226 res.put(prop.getName(), prop.getDate());
227 break;
228 case PropertyType.BINARY:
229 byte[] arr = JcrUtils.getBinaryAsBytes(prop);
230 res.put(prop.getName(), arr);
231 break;
232 default:
233 res.put(prop.getName(), prop.getString());
234 }
235 }
236 return res;
237 } catch (RepositoryException e) {
238 throw new JcrFsException("Cannot read attributes of " + path, e);
239 }
240 }
241
242 @Override
243 public void setAttribute(Path path, String attribute, Object value, LinkOption... options) throws IOException {
244 try {
245 Node node = toNode(path);
246 if (value instanceof byte[]) {
247 JcrUtils.setBinaryAsBytes(node, attribute, (byte[]) value);
248 } else if (value instanceof Calendar) {
249 node.setProperty(attribute, (Calendar) value);
250 } else {
251 node.setProperty(attribute, value.toString());
252 }
253 node.getSession().save();
254 } catch (RepositoryException e) {
255 throw new JcrFsException("Cannot set attribute " + attribute + " on " + path, e);
256 }
257 }
258
259 protected Node toNode(Path path) throws RepositoryException {
260 return ((JcrPath) path).getNode();
261 }
262
263 }