1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.exoplatform.services.cms.documents.impl;
18
19 import org.exoplatform.commons.utils.CommonsUtils;
20 import org.exoplatform.container.xml.PortalContainerInfo;
21 import org.exoplatform.portal.config.UserPortalConfig;
22 import org.exoplatform.portal.config.UserPortalConfigService;
23 import org.exoplatform.portal.mop.SiteKey;
24 import org.exoplatform.portal.mop.user.UserNavigation;
25 import org.exoplatform.portal.mop.user.UserPortalContext;
26 import org.exoplatform.services.cms.BasePath;
27 import org.exoplatform.services.cms.documents.DocumentService;
28 import org.exoplatform.services.cms.documents.model.Document;
29 import org.exoplatform.services.cms.drives.DriveData;
30 import org.exoplatform.services.cms.drives.ManageDriveService;
31 import org.exoplatform.services.cms.drives.impl.ManageDriveServiceImpl;
32 import org.exoplatform.services.cms.impl.Utils;
33 import org.exoplatform.services.cms.link.LinkManager;
34 import org.exoplatform.services.jcr.RepositoryService;
35 import org.exoplatform.services.jcr.core.ManageableRepository;
36 import org.exoplatform.services.jcr.ext.app.SessionProviderService;
37 import org.exoplatform.services.jcr.ext.common.SessionProvider;
38 import org.exoplatform.services.jcr.ext.hierarchy.NodeHierarchyCreator;
39 import org.exoplatform.services.jcr.impl.core.NodeImpl;
40 import org.exoplatform.services.log.ExoLogger;
41 import org.exoplatform.services.log.Log;
42 import org.exoplatform.services.security.ConversationState;
43 import org.exoplatform.services.wcm.core.NodetypeConstant;
44 import org.exoplatform.services.wcm.utils.WCMCoreUtils;
45 import org.gatein.api.Portal;
46 import org.gatein.api.navigation.Navigation;
47 import org.gatein.api.navigation.Nodes;
48 import org.gatein.api.site.SiteId;
49
50 import javax.jcr.Node;
51 import javax.jcr.NodeIterator;
52 import javax.jcr.RepositoryException;
53 import javax.jcr.Session;
54 import java.net.URLEncoder;
55 import java.util.*;
56
57
58
59
60
61 public class DocumentServiceImpl implements DocumentService {
62
63 public static final String MIX_REFERENCEABLE = "mix:referenceable";
64 public static final String EXO_LAST_MODIFIER_PROP = "exo:lastModifier";
65 public static final String EXO_DATE_CREATED_PROP = "exo:dateCreated";
66 public static final String JCR_LAST_MODIFIED_PROP = "jcr:lastModified";
67 public static final String JCR_CONTENT = "jcr:content";
68 public static final String EXO_OWNER_PROP = "exo:owner";
69 public static final String EXO_TITLE_PROP = "exo:title";
70 public static final String CURRENT_STATE_PROP = "publication:currentState";
71 public static final String DOCUMENTS_APP_NAVIGATION_NODE_NAME = "documents";
72 public static final String DOCUMENT_NOT_FOUND = "?path=doc-not-found";
73 private static final String DOCUMENTS_NODE = "Documents";
74 private static final String SHARED_NODE = "Shared";
75 private static final Log LOG = ExoLogger.getLogger(DocumentServiceImpl.class);
76 private ManageDriveService manageDriveService;
77 private Portal portal;
78 private SessionProviderService sessionProviderService;
79 private RepositoryService repoService;
80 private NodeHierarchyCreator nodeHierarchyCreator;
81 private LinkManager linkManager;
82 private PortalContainerInfo portalContainerInfo;
83
84 public DocumentServiceImpl(ManageDriveService manageDriveService, Portal portal, SessionProviderService sessionProviderService, RepositoryService repoService, NodeHierarchyCreator nodeHierarchyCreator, LinkManager linkManager, PortalContainerInfo portalContainerInfo) {
85 this.manageDriveService = manageDriveService;
86 this.sessionProviderService = sessionProviderService;
87 this.repoService = repoService;
88 this.nodeHierarchyCreator = nodeHierarchyCreator;
89 this.portal = portal;
90 this.linkManager = linkManager;
91 this.portalContainerInfo = portalContainerInfo;
92 }
93
94 @Override
95 public Document findDocById(String documentId) throws RepositoryException {
96 RepositoryService repositoryService = WCMCoreUtils.getService(RepositoryService.class);
97 ManageableRepository manageRepo = repositoryService.getCurrentRepository();
98 SessionProvider sessionProvider = WCMCoreUtils.getUserSessionProvider();
99
100 String ws = documentId.split(":/")[0];
101 String uuid = documentId.split(":/")[1];
102
103 Node node = sessionProvider.getSession(ws, manageRepo).getNodeByUUID(uuid);
104
105 String title = node.hasProperty(EXO_TITLE_PROP) ? node.getProperty(EXO_TITLE_PROP).getString() : "";
106 String id = node.isNodeType(MIX_REFERENCEABLE) ? node.getUUID() : "";
107 String state = node.hasProperty(CURRENT_STATE_PROP) ? node.getProperty(CURRENT_STATE_PROP).getValue().getString() : "";
108 String author = node.hasProperty(EXO_OWNER_PROP) ? node.getProperty(EXO_OWNER_PROP).getString() : "";
109 Calendar lastModified = (node.hasNode(JCR_CONTENT) ? node.getNode(JCR_CONTENT)
110 .getProperty(JCR_LAST_MODIFIED_PROP)
111 .getValue()
112 .getDate() : null);
113 Calendar dateCreated = (node.hasProperty(EXO_DATE_CREATED_PROP) ? node.getProperty(EXO_DATE_CREATED_PROP)
114 .getValue()
115 .getDate()
116 : null);
117 String lastEditor = (node.hasProperty(EXO_LAST_MODIFIER_PROP) ? node.getProperty(EXO_LAST_MODIFIER_PROP)
118 .getValue()
119 .getString()
120 : "");
121 Document doc = new Document(id, node.getName(), title, node.getPath(),
122 ws, state, author, lastEditor, lastModified, dateCreated);
123 return doc;
124 }
125
126
127
128
129
130 public String getDocumentUrlInPersonalDocuments(Node currentNode, String username) throws Exception {
131 Node rootNode = null;
132 try {
133 SessionProvider sessionProvider = sessionProviderService.getSystemSessionProvider(null);
134 ManageableRepository repository = repoService.getCurrentRepository();
135 Session session = sessionProvider.getSession(repository.getConfiguration().getDefaultWorkspaceName(), repository);
136
137 nodeHierarchyCreator.getJcrPath(BasePath.CMS_USERS_PATH);
138 rootNode = (Node) session.getItem(nodeHierarchyCreator.getJcrPath(BasePath.CMS_USERS_PATH) + getPrivatePath(username));
139 String sharedLink = getSharedLink(currentNode, rootNode);
140 return sharedLink;
141 } catch (Exception e) {
142 LOG.error(e.getMessage(), e);
143 return "";
144 }
145 }
146
147
148
149
150
151 public String getDocumentUrlInSpaceDocuments(Node currentNode, String spaceId) throws Exception {
152 Node rootNode = null;
153 try {
154 SessionProvider sessionProvider = sessionProviderService.getSystemSessionProvider(null);
155 ManageableRepository repository = repoService.getCurrentRepository();
156 Session session = sessionProvider.getSession(repository.getConfiguration().getDefaultWorkspaceName(), repository);
157
158 nodeHierarchyCreator.getJcrPath(BasePath.CMS_GROUPS_PATH);
159 rootNode = (Node) session.getItem(nodeHierarchyCreator.getJcrPath(BasePath.CMS_GROUPS_PATH) + spaceId);
160 String sharedLink = getSharedLink(currentNode, rootNode);
161 return sharedLink;
162 } catch (Exception e) {
163 LOG.error(e.getMessage(), e);
164 return "";
165 }
166 }
167
168
169
170
171
172
173
174
175 @Override
176 public String getShortLinkInDocumentsApp(String workspaceName, String nodeId) throws Exception {
177 StringBuilder url = new StringBuilder();
178 String containerName = portalContainerInfo.getContainerName();
179 url.append("/")
180 .append(containerName)
181 .append("/private/")
182 .append(CommonsUtils.getRestContextName())
183 .append("/documents/view/")
184 .append(workspaceName)
185 .append("/")
186 .append(nodeId);
187 return url.toString();
188 }
189
190
191
192
193
194
195
196
197 @Override
198 public String getLinkInDocumentsApp(String nodePath) throws Exception {
199 if(nodePath == null) {
200 return null;
201 }
202
203
204 DriveData drive = this.getDriveOfNode(nodePath);
205
206 return getLinkInDocumentsApp(nodePath, drive);
207 }
208
209
210
211
212
213
214
215
216 @Override
217 public String getLinkInDocumentsApp(String nodePath, DriveData drive) throws Exception {
218 if(nodePath == null) {
219 return null;
220 }
221
222 String containerName = portalContainerInfo.getContainerName();
223 StringBuffer url = new StringBuffer();
224 url.append("/").append(containerName);
225 if (drive == null) {
226 SiteKey siteKey = getDefaultSiteKey();
227 url.append("/").append(siteKey.getName()).append("/").append(DOCUMENTS_APP_NAVIGATION_NODE_NAME)
228 .append(DOCUMENT_NOT_FOUND);
229 return url.toString();
230 }
231
232 String encodedDriveName = URLEncoder.encode(drive.getName(), "UTF-8");
233 String encodedNodePath = URLEncoder.encode(nodePath, "UTF-8");
234 if(drive.getName().equals(ManageDriveServiceImpl.GROUPS_DRIVE_NAME)) {
235
236 String groupId = drive.getParameters().get(ManageDriveServiceImpl.DRIVE_PARAMATER_GROUP_ID);
237 if(groupId != null) {
238 String groupPageName;
239 String[] splitedGroupId = groupId.split("/");
240 if (splitedGroupId != null && splitedGroupId.length == 3 && splitedGroupId[1].equals("spaces")) {
241
242
243
244
245 String rootNavigation = getSpaceRootNavigationNodeURI(groupId);
246
247 groupPageName = rootNavigation + "/" + DOCUMENTS_APP_NAVIGATION_NODE_NAME;
248 } else {
249
250 groupPageName = DOCUMENTS_APP_NAVIGATION_NODE_NAME;
251 }
252 url.append("/g/").append(groupId.replaceAll("/", ":")).append("/").append(groupPageName)
253 .append("?path=").append(encodedDriveName).append(encodedNodePath)
254 .append("&").append(ManageDriveServiceImpl.DRIVE_PARAMATER_GROUP_ID).append("=").append(groupId);
255 } else {
256 throw new Exception("Cannot get group id from node path " + nodePath);
257 }
258 } else if(drive.getName().equals(ManageDriveServiceImpl.USER_DRIVE_NAME)
259 || drive.getName().equals(ManageDriveServiceImpl.PERSONAL_DRIVE_NAME)) {
260
261 SiteKey siteKey = getDefaultSiteKey();
262 url.append("/").append(siteKey.getName()).append("/").append(DOCUMENTS_APP_NAVIGATION_NODE_NAME)
263 .append("?path=" + encodedDriveName + encodedNodePath);
264 String[] splitedNodePath = nodePath.split("/");
265 if(splitedNodePath != null && splitedNodePath.length >= 6) {
266 String userId = splitedNodePath[5];
267 url.append("&").append(ManageDriveServiceImpl.DRIVE_PARAMATER_USER_ID).append("=").append(userId);
268 }
269 } else {
270
271 SiteKey siteKey = getDefaultSiteKey();
272 url.append("/").append(siteKey.getName()).append("/").append(DOCUMENTS_APP_NAVIGATION_NODE_NAME)
273 .append("?path=" + encodedDriveName + encodedNodePath);
274 }
275
276 return url.toString();
277 }
278
279
280
281
282
283
284
285 protected String getSpaceRootNavigationNodeURI(String spaceGroupId) throws Exception {
286 String navigationName = null;
287
288 Navigation spaceNavigation = portal.getNavigation(new SiteId(org.gatein.api.site.SiteType.SPACE, spaceGroupId));
289 if(spaceNavigation != null) {
290 org.gatein.api.navigation.Node navigationRootNode = spaceNavigation.getRootNode(Nodes.visitChildren());
291 if(navigationRootNode != null && navigationRootNode.iterator().hasNext()) {
292
293 org.gatein.api.navigation.Node node = navigationRootNode.iterator().next();
294 navigationName = node.getName();
295 }
296 }
297
298 return navigationName;
299 }
300
301 @Override
302 public DriveData getDriveOfNode(String nodePath) throws Exception {
303 return getDriveOfNode(nodePath, ConversationState.getCurrent().getIdentity().getUserId(), Utils.getMemberships());
304 }
305
306 @Override
307 public DriveData getDriveOfNode(String nodePath, String userId, List<String> memberships) throws Exception {
308 DriveData nodeDrive = null;
309 List<DriveData> drives = manageDriveService.getDriveByUserRoles(userId, memberships);
310
311
312 String[] splitedPath = nodePath.split("/");
313 if (splitedPath != null && splitedPath.length >= 2 && splitedPath.length >= 6
314 && splitedPath[1].equals(ManageDriveServiceImpl.PERSONAL_DRIVE_ROOT_NODE)) {
315 if (splitedPath[5].equals(userId)) {
316 nodeDrive = manageDriveService.getDriveByName(ManageDriveServiceImpl.PERSONAL_DRIVE_NAME);
317 } else {
318 nodeDrive = manageDriveService.getDriveByName(ManageDriveServiceImpl.USER_DRIVE_NAME);
319 }
320 if (nodeDrive != null) {
321 nodeDrive = nodeDrive.clone();
322 nodeDrive.getParameters().put(ManageDriveServiceImpl.DRIVE_PARAMATER_USER_ID,
323 splitedPath[2] + "/" + splitedPath[3] + "/" + splitedPath[4] + "/" + splitedPath[5]);
324 }
325 }
326 if (splitedPath != null && splitedPath.length >= 2 && splitedPath[1].equals(ManageDriveServiceImpl.GROUPS_DRIVE_ROOT_NODE)) {
327 int groupDocumentsRootNodeName = nodePath.indexOf("/Documents");
328 if(groupDocumentsRootNodeName >= 0) {
329
330 String groupId = nodePath.substring(ManageDriveServiceImpl.GROUPS_DRIVE_ROOT_NODE.length() + 1, groupDocumentsRootNodeName);
331 nodeDrive = manageDriveService.getDriveByName(groupId.replaceAll("/", "."));
332 }
333 }
334 if (nodeDrive == null) {
335 for (DriveData drive : drives) {
336 if (nodePath.startsWith(drive.getResolvedHomePath())) {
337 if (nodeDrive == null || nodeDrive.getResolvedHomePath().length() < drive.getResolvedHomePath().length()) {
338 nodeDrive = drive;
339 }
340 }
341 }
342 }
343 return nodeDrive;
344 }
345
346
347 protected UserPortalConfig getDefaultUserPortalConfig() throws Exception {
348 UserPortalConfigService userPortalConfigSer = WCMCoreUtils.getService(UserPortalConfigService.class);
349 UserPortalContext NULL_CONTEXT = new UserPortalContext() {
350 public ResourceBundle getBundle(UserNavigation navigation) {
351 return null;
352 }
353 public Locale getUserLocale() {
354 return Locale.ENGLISH;
355 }
356 };
357 String remoteId = ConversationState.getCurrent().getIdentity().getUserId() ;
358 UserPortalConfig userPortalCfg = userPortalConfigSer.
359 getUserPortalConfig(userPortalConfigSer.getDefaultPortal(), remoteId, NULL_CONTEXT);
360 return userPortalCfg;
361 }
362
363 protected SiteKey getDefaultSiteKey() throws Exception {
364 UserPortalConfig prc = getDefaultUserPortalConfig();
365 if (prc == null) {
366 return null;
367 }
368 SiteKey siteKey = SiteKey.portal(prc.getPortalConfig().getName());
369 return siteKey;
370 }
371
372 private String getPrivatePath(String user) {
373 return "/" + user.substring(0, 1) + "___/" + user.substring(0, 2) + "___/" + user.substring(0, 3) + "___/" + user + "/Private";
374 }
375
376 private String getSharedLink(Node currentNode, Node rootNode) {
377 Node shared = null;
378 Node link = null;
379 try {
380 rootNode = rootNode.getNode(DOCUMENTS_NODE);
381 if (!rootNode.hasNode(SHARED_NODE)) {
382 shared = rootNode.addNode(SHARED_NODE);
383 } else {
384 shared = rootNode.getNode(SHARED_NODE);
385 }
386 if (currentNode.isNodeType(NodetypeConstant.EXO_SYMLINK)) {
387 currentNode = linkManager.getTarget(currentNode);
388 }
389 List<String> path = new ArrayList<>();
390 Node targetNode = null;
391 boolean existingSymlink = false;
392 for (NodeIterator it = shared.getNodes(); it.hasNext(); ) {
393 Node node = it.nextNode();
394 path.add(((NodeImpl) node).getInternalPath().getAsString());
395 if (path.contains(((NodeImpl) shared).getInternalPath().getAsString() + "[]" + currentNode.getName() + ":1")) {
396 existingSymlink = true;
397 targetNode = node;
398 break;
399 }
400 }
401 if (existingSymlink) {
402 link = targetNode;
403 } else {
404 link = linkManager.createLink(shared, currentNode);
405 }
406 return CommonsUtils.getCurrentDomain() + getShortLinkInDocumentsApp(link.getSession().getWorkspace().getName(), ((NodeImpl) link).getInternalIdentifier());
407 } catch (Exception e) {
408 LOG.error(e.getMessage(), e);
409 return "";
410 }
411 }
412
413 }