View Javadoc
1   package org.argeo.documents.core;
2   
3   import java.io.IOException;
4   import java.net.URI;
5   import java.net.URISyntaxException;
6   import java.nio.file.FileSystem;
7   import java.nio.file.Path;
8   import java.nio.file.spi.FileSystemProvider;
9   import java.util.ArrayList;
10  import java.util.List;
11  
12  import javax.jcr.Node;
13  import javax.jcr.NodeIterator;
14  import javax.jcr.Property;
15  import javax.jcr.Repository;
16  import javax.jcr.RepositoryException;
17  import javax.jcr.Session;
18  import javax.jcr.nodetype.NodeType;
19  import javax.jcr.query.Query;
20  import javax.jcr.query.QueryManager;
21  import javax.naming.ldap.LdapName;
22  
23  import org.argeo.cms.auth.CurrentUser;
24  import org.argeo.connect.ConnectConstants;
25  import org.argeo.connect.core.AbstractAppService;
26  import org.argeo.connect.util.ConnectJcrUtils;
27  import org.argeo.documents.DocumentsConstants;
28  import org.argeo.documents.DocumentsException;
29  import org.argeo.documents.DocumentsNames;
30  import org.argeo.documents.DocumentsService;
31  import org.argeo.documents.DocumentsTypes;
32  import org.argeo.jcr.JcrUtils;
33  import org.argeo.node.NodeConstants;
34  import org.argeo.node.NodeUtils;
35  
36  /** Default backend for the Documents App */
37  public class DocumentsServiceImpl extends AbstractAppService implements DocumentsService {
38  	// private final static String NODE_PREFIX = "node://";
39  
40  	@Override
41  	public Node publishEntity(Node parent, String nodeType, Node srcNode, boolean removeSrcNode)
42  			throws RepositoryException {
43  		return null;
44  	}
45  
46  	@Override
47  	public String getAppBaseName() {
48  		return DocumentsConstants.DOCUMENTS_APP_LBL;
49  	}
50  
51  	@Override
52  	public String getDefaultRelPath(Node entity) throws RepositoryException {
53  		throw new DocumentsException("No default relpath is defined for the Documents App");
54  	}
55  
56  	@Override
57  	public String getDefaultRelPath(Session session, String nodeType, String id) {
58  		throw new DocumentsException("No default relpath is defined for the Documents App");
59  	}
60  
61  	@Override
62  	public boolean isKnownType(Node entity) {
63  		if (ConnectJcrUtils.isNodeType(entity, NodeType.NT_FILE)
64  				|| ConnectJcrUtils.isNodeType(entity, NodeType.NT_FOLDER))
65  			return true;
66  		else
67  			return false;
68  	}
69  
70  	@Override
71  	public boolean isKnownType(String nodeType) {
72  		if (NodeType.NT_FILE.equals(nodeType) || NodeType.NT_FOLDER.equals(nodeType))
73  			return true;
74  		else
75  			return false;
76  	}
77  
78  	/* DOCUMENTS APP SPECIFIC METHODS */
79  
80  	public Path[] getMyDocumentsPath(FileSystemProvider nodeFileSystemProvider, Session session) {
81  		Node home = NodeUtils.getUserHome(session);
82  		Path[] paths = { getPath(nodeFileSystemProvider, ConnectJcrUtils.getPath(home)) };
83  		// Insure the parent node is there.
84  //		Node documents = JcrUtils.mkdirs(home, getAppBaseName(), NodeType.NT_FOLDER);
85  //		ConnectJcrUtils.saveIfNecessary(documents);
86  //		Path[] paths = { getPath(nodeFileSystemProvider, ConnectJcrUtils.getPath(documents)) };
87  		return paths;
88  	}
89  
90  	public Path[] getMyGroupsFilesPath(FileSystemProvider nodeFileSystemProvider, Session session) {
91  		try {
92  			List<Path> paths = new ArrayList<>();
93  			for (String dn : CurrentUser.roles()) {
94  				LdapName ln = new LdapName(dn);
95  				String cn = (String) ln.getRdn(ln.size() - 1).getValue();
96  				Node workgroupHome = NodeUtils.getGroupHome(session, cn);
97  				if (workgroupHome != null) {
98  					paths.add(getPath(nodeFileSystemProvider, ConnectJcrUtils.getPath(workgroupHome)));
99  //					Node documents = JcrUtils.mkdirs(workgroupHome, getAppBaseName(), NodeType.NT_FOLDER);
100 //					documents.addMixin(NodeType.MIX_TITLE);
101 //					if (session.hasPendingChanges()) {
102 //						documents.setProperty(Property.JCR_TITLE, cn);
103 //						session.save();
104 //					}
105 //					// Insure the correct subNode is there
106 //					paths.add(getPath(nodeFileSystemProvider, ConnectJcrUtils.getPath(documents)));
107 				}
108 			}
109 			return paths.toArray(new Path[0]);
110 		} catch (Exception e) {
111 			throw new DocumentsException("Cannot retrieve work group home paths", e);
112 		}
113 	}
114 
115 	public Path[] getMyBookmarks(FileSystemProvider nodeFileSystemProvider, Session session) {
116 		try {
117 			Node bookmarkParent = getMyBookmarksParent(session);
118 			List<Path> bookmarks = new ArrayList<>();
119 			NodeIterator nit = bookmarkParent.getNodes();
120 			while (nit.hasNext()) {
121 				Node currBookmark = nit.nextNode();
122 				String uriStr = ConnectJcrUtils.get(currBookmark, DocumentsNames.DOCUMENTS_URI);
123 				URI uri = new URI(uriStr);
124 				bookmarks.add(getPath(nodeFileSystemProvider, uri));
125 			}
126 			return bookmarks.toArray(new Path[0]);
127 		} catch (URISyntaxException | RepositoryException e) {
128 			throw new DocumentsException("Cannot retrieve CurrentUser bookmarks", e);
129 		}
130 	}
131 
132 	public Node[] getMyBookmarks(Session session) {
133 		try {
134 			Node bookmarkParent = getMyBookmarksParent(session);
135 			List<Node> bookmarks = new ArrayList<>();
136 			NodeIterator nit = bookmarkParent.getNodes();
137 			while (nit.hasNext()) {
138 				Node currBookmark = nit.nextNode();
139 				if (currBookmark.isNodeType(DocumentsTypes.DOCUMENTS_BOOKMARK)) {
140 					bookmarks.add(currBookmark);
141 				}
142 			}
143 			return bookmarks.toArray(new Node[0]);
144 		} catch (RepositoryException e) {
145 			throw new DocumentsException("Cannot retrieve CurrentUser bookmarks", e);
146 		}
147 	}
148 
149 	public Node getMyBookmarksParent(Session session) {
150 		try {
151 			// tryAs is compulsory when not calling from the workbench
152 			// Repository repo = callingSession.getRepository();
153 			// session = CurrentUser.tryAs(() -> repo.login());
154 			// Node home = NodeUtils.getUserHome(session);
155 			//
156 			// // Insure the parent node is there.
157 			// String relPath = DocumentsConstants.SUITE_HOME_SYS_RELPATH + "/"
158 			// + DocumentsConstants.FS_BASE_NAME + "/"
159 			// + DocumentsConstants.FS_BOOKMARKS;
160 
161 			// Insure the parent node is there.
162 			if (session.hasPendingChanges())
163 				throw new DocumentsException("Session must be clean to retrieve bookmarks");
164 			Node home = NodeUtils.getUserHome(session);
165 			String relPath = ConnectConstants.HOME_APP_SYS_RELPARPATH + "/" + DocumentsConstants.DOCUMENTS_APP_BASE_NAME
166 					+ "/" + DocumentsConstants.DOCUMENTS_BOOKMARKS;
167 			Node bookmarkParent = JcrUtils.mkdirs(home, relPath);
168 			if (session.hasPendingChanges())
169 				session.save();
170 			return bookmarkParent;
171 		} catch (RepositoryException e) {
172 			throw new DocumentsException("Cannot retrieve bookmark parent for session " + session, e);
173 		}
174 	}
175 
176 	// private String getCurrentHomePath(Session callingSession) {
177 	// Session session = null;
178 	// try {
179 	// // tryAs is compulsory when not calling from the workbench
180 	// Repository repo = callingSession.getRepository();
181 	// session = CurrentUser.tryAs(() -> repo.login());
182 	// String homepath = NodeUtils.getUserHome(session).getPath();
183 	// return homepath;
184 	// } catch (Exception e) {
185 	// throw new DocumentsException("Cannot retrieve Current User Home Path",
186 	// e);
187 	// } finally {
188 	// JcrUtils.logoutQuietly(session);
189 	// }
190 	// }
191 
192 	public Path getPath(FileSystemProvider nodeFileSystemProvider, String nodePath) {
193 		// try {
194 		// URI uri = new URI(NODE_PREFIX + nodePath);
195 		URI uri = nodePathToURI(nodePath);
196 		return getPath(nodeFileSystemProvider, uri);
197 
198 		// FileSystem fileSystem = nodeFileSystemProvider.getFileSystem(uri);
199 		// if (fileSystem == null)
200 		// fileSystem = nodeFileSystemProvider.newFileSystem(uri, null);
201 		// FileSystem fileSystem = nodeFileSystemProvider.getFileSystem(uri);
202 		// if (fileSystem == null)
203 		// FileSystem fileSystem = nodeFileSystemProvider.newFileSystem(uri, null);
204 		// Note that tryAs() is compulsory in the CMS.
205 		// fileSystem = CurrentUser.tryAs(() ->
206 		// nodeFileSystemProvider.newFileSystem(uri, null));
207 		// return fileSystem.getPath(nodePath);
208 		// } catch (IOException e) {
209 		// throw new RuntimeException("Unable to initialise file system for " +
210 		// nodePath, e);
211 		// }
212 	}
213 
214 	public NodeIterator getLastUpdatedDocuments(Session session) {
215 		try {
216 			String qStr = "//element(*, " + ConnectJcrUtils.getLocalJcrItemName(NodeType.NT_FILE) + ")";
217 			qStr += " order by @" + ConnectJcrUtils.getLocalJcrItemName(Property.JCR_LAST_MODIFIED) + " descending";
218 			QueryManager queryManager = session.getWorkspace().getQueryManager();
219 			Query xpathQuery = queryManager.createQuery(qStr, ConnectConstants.QUERY_XPATH);
220 			xpathQuery.setLimit(8);
221 			NodeIterator nit = xpathQuery.execute().getNodes();
222 			return nit;
223 		} catch (RepositoryException e) {
224 			throw new DocumentsException("Unable to retrieve last updated documents", e);
225 		}
226 	}
227 
228 	public Path getPath(FileSystemProvider nodeFileSystemProvider, URI uri) {
229 		try {
230 			FileSystem fileSystem = nodeFileSystemProvider.getFileSystem(uri);
231 			if (fileSystem == null)
232 				fileSystem = nodeFileSystemProvider.newFileSystem(uri, null);
233 			// TODO clean this
234 			// String path = uri.toString().substring(NODE_PREFIX.length());
235 			String path = uri.getPath();
236 			return fileSystem.getPath(path);
237 		} catch (IOException e) {
238 			throw new DocumentsException("Unable to initialise file system for " + uri, e);
239 		}
240 	}
241 
242 	public Node createFolderBookmark(Path path, String name, Repository repository) {
243 		Session session = null;
244 		try {
245 			session = repository.login();
246 			Node bookmarkParent = getMyBookmarksParent(session);
247 			// String uriStr = NODE_PREFIX + path.toString();
248 			// uriStr = uriStr.replaceAll(" ", "%20");
249 			String nodeName = path.getFileName().toString();
250 			Node bookmark = bookmarkParent.addNode(nodeName);
251 			bookmark.addMixin(DocumentsTypes.DOCUMENTS_BOOKMARK);
252 			bookmark.setProperty(DocumentsNames.DOCUMENTS_URI, nodePathToURI(path.toString()).toString());
253 			bookmark.setProperty(Property.JCR_TITLE, name);
254 			session.save();
255 			return bookmark;
256 		} catch (RepositoryException e) {
257 			throw new DocumentsException("Cannot create bookmark for " + path + " with name " + name, e);
258 		} finally {
259 			JcrUtils.logoutQuietly(session);
260 		}
261 	}
262 
263 	private static URI nodePathToURI(String nodePath) {
264 		try {
265 			return new URI(NodeConstants.SCHEME_NODE, null, nodePath, null);
266 		} catch (URISyntaxException e) {
267 			throw new DocumentsException("Badly formatted path " + nodePath, e);
268 		}
269 	}
270 }