View Javadoc
1   /*
2    * Copyright (C) 2003-2011 eXo Platform SAS.
3    *
4    * This program is free software; you can redistribute it and/or
5    * modify it under the terms of the GNU Affero General Public License
6    * as published by the Free Software Foundation; either version 3
7    * of the License, or (at your option) any later version.
8    *
9    * This program is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   * GNU General Public License for more details.
13   *
14   * You should have received a copy of the GNU General Public License
15   * along with this program; if not, see<http://www.gnu.org/licenses/>.
16   */
17  package org.exoplatform.ecm.connector.platform;
18  
19  import org.apache.commons.lang.StringUtils;
20  import org.exoplatform.container.xml.InitParams;
21  import org.exoplatform.ecm.connector.fckeditor.FCKUtils;
22  import org.exoplatform.ecm.utils.text.Text;
23  import org.exoplatform.services.cms.documents.AutoVersionService;
24  import org.exoplatform.services.cms.drives.DriveData;
25  import org.exoplatform.services.cms.drives.ManageDriveService;
26  import org.exoplatform.services.cms.impl.Utils;
27  import org.exoplatform.services.cms.link.LinkManager;
28  import org.exoplatform.services.context.DocumentContext;
29  import org.exoplatform.services.jcr.RepositoryService;
30  import org.exoplatform.services.jcr.access.PermissionType;
31  import org.exoplatform.services.jcr.core.ManageableRepository;
32  import org.exoplatform.services.jcr.ext.common.SessionProvider;
33  import org.exoplatform.services.log.ExoLogger;
34  import org.exoplatform.services.log.Log;
35  import org.exoplatform.services.rest.resource.ResourceContainer;
36  import org.exoplatform.services.security.ConversationState;
37  import org.exoplatform.services.security.MembershipEntry;
38  import org.exoplatform.services.wcm.core.NodetypeConstant;
39  import org.exoplatform.services.wcm.utils.WCMCoreUtils;
40  import org.exoplatform.wcm.connector.FileUploadHandler;
41  import org.w3c.dom.Document;
42  import org.w3c.dom.Element;
43  
44  import javax.annotation.security.RolesAllowed;
45  import javax.jcr.AccessDeniedException;
46  import javax.jcr.Node;
47  import javax.jcr.NodeIterator;
48  import javax.jcr.PathNotFoundException;
49  import javax.jcr.RepositoryException;
50  import javax.jcr.Session;
51  import javax.servlet.http.HttpServletRequest;
52  import javax.ws.rs.DefaultValue;
53  import javax.ws.rs.GET;
54  import javax.ws.rs.POST;
55  import javax.ws.rs.Path;
56  import javax.ws.rs.QueryParam;
57  import javax.ws.rs.core.CacheControl;
58  import javax.ws.rs.core.Context;
59  import javax.ws.rs.core.MediaType;
60  import javax.ws.rs.core.Response;
61  import javax.ws.rs.core.Response.Status;
62  import javax.xml.parsers.DocumentBuilder;
63  import javax.xml.parsers.DocumentBuilderFactory;
64  import javax.xml.parsers.ParserConfigurationException;
65  import javax.xml.transform.dom.DOMSource;
66  import java.text.DateFormat;
67  import java.text.SimpleDateFormat;
68  import java.util.ArrayList;
69  import java.util.Collection;
70  import java.util.Date;
71  import java.util.List;
72  
73  /**
74   * This service is used to perform some actions on a folder or on a file, such as creating,
75   * or deleting a folder/file, or uploading a file.
76   *
77   * @LevelAPI Provisional
78   *
79   * @anchor ManageDocumentService
80   */
81  @Path("/managedocument/")
82  public class ManageDocumentService implements ResourceContainer {
83  
84    /** The Constant IF_MODIFIED_SINCE_DATE_FORMAT. */
85    protected static final String IF_MODIFIED_SINCE_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss z";
86  
87    /** The Constant LAST_MODIFIED_PROPERTY. */
88    protected static final String LAST_MODIFIED_PROPERTY = "Last-Modified";
89  
90    /** The cache control. */
91    private final CacheControl    cc;
92  
93    /** The log. */
94    private static final Log LOG = ExoLogger.getLogger(ManageDocumentService.class.getName());
95    
96    /** Default folder name if the original is null */ 
97    private static final String DEFAULT_NAME = "untitled";
98  
99    private ManageDriveService    manageDriveService;
100 
101   private LinkManager linkManager;
102 
103   /** The file upload handler. */
104   protected FileUploadHandler   fileUploadHandler;
105 
106   private enum DriveType {
107     GENERAL, GROUP, PERSONAL
108   }
109 
110   final static public String   EXO_MUSICFOLDER      = "exo:musicFolder";
111 
112   final static public String   EXO_VIDEOFOLDER      = "exo:videoFolder";
113 
114   final static public String   EXO_PICTUREFOLDER    = "exo:pictureFolder";
115 
116   final static public String   EXO_DOCUMENTFOLDER   = "exo:documentFolder";
117 
118   final static public String   EXO_SEARCHFOLDER     = "exo:searchFolder";
119 
120   final static public String   EXO_SYMLINK          = "exo:symlink";
121 
122   final static public String   EXO_PRIMARYTYPE      = "exo:primaryType";
123 
124   final static public String   EXO_TRASH_FOLDER     = "exo:trashFolder";
125 
126   final static public String   EXO_FAVOURITE_FOLDER = "exo:favoriteFolder";
127 
128   final static public String   NT_UNSTRUCTURED      = "nt:unstructured";
129 
130   final static public String   NT_FOLDER            = "nt:folder";
131 
132   final static public String[] SPECIFIC_FOLDERS = { EXO_MUSICFOLDER,
133     EXO_VIDEOFOLDER, EXO_PICTUREFOLDER, EXO_DOCUMENTFOLDER, EXO_SEARCHFOLDER };
134 
135   private static final String  PRIVATE              = "Private";
136   
137   /** The limit size of uploaded file. */
138   private int limit;
139 
140   /**
141    * Instantiates a document service.
142    *
143    * @param manageDriveService Instantiates a drive manager service.
144    * @param linkManager Instantiates a link manager service.
145    */
146   public ManageDocumentService(ManageDriveService manageDriveService, LinkManager linkManager,
147                                InitParams params) {
148     this.manageDriveService = manageDriveService;
149     this.linkManager = linkManager;
150     fileUploadHandler = new FileUploadHandler();
151     cc = new CacheControl();
152     cc.setNoCache(true);
153     cc.setNoStore(true);
154     limit = Integer.parseInt(params.getValueParam("upload.limit.size").getValue());
155   }
156 
157   /**
158    * Gets all drives by type (General, Group or Personal).
159    *
160    * @param driveType The types of drive (General, Group, or Personal).
161    * @param showPrivate Shows the Private drive or not. The default value is false.
162    * @param showPersonal Shows the Personal drive or not. The default value is false.
163    * @return {@link Document} which contains the drives.
164    * @throws Exception The exception
165    *
166    * @anchor ManageDocumentService.getDrives
167    */
168   @GET
169   @Path("/getDrives/")
170   @RolesAllowed("users")
171   public Response getDrives(@QueryParam("driveType") String driveType,
172                             @DefaultValue("false") @QueryParam("showPrivate") String showPrivate,
173                             @DefaultValue("false") @QueryParam("showPersonal") String showPersonal) throws Exception {
174     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
175     List<String> userRoles = getMemberships();
176     DocumentBuilder builder = factory.newDocumentBuilder();
177     Document document = builder.newDocument();
178 
179     Element rootElement = document.createElement("Folders");
180     document.appendChild(rootElement);
181     String userId = ConversationState.getCurrent().getIdentity().getUserId();
182     List<DriveData> driveList = new ArrayList<DriveData>();
183     if (DriveType.GENERAL.toString().equalsIgnoreCase(driveType)) {
184       driveList = manageDriveService.getMainDrives(userId, userRoles);
185     } else if (DriveType.GROUP.toString().equalsIgnoreCase(driveType)) {
186       driveList = manageDriveService.getGroupDrives(userId, userRoles);
187     } else if (DriveType.PERSONAL.toString().equalsIgnoreCase(driveType)) {
188       driveList = manageDriveService.getPersonalDrives(userId);
189     //remove Private drive
190       String privateDrivePath = "";
191       for (DriveData driveData : driveList) {
192         if (PRIVATE.equals(driveData.getName())) {
193           privateDrivePath = driveData.getHomePath();
194           if (!Boolean.valueOf(showPrivate)) {
195             driveList.remove(driveData);
196             break;
197           }
198         }
199       }
200       //remove Personal Documents drive
201       if (!Boolean.valueOf(showPersonal)) {
202         for (DriveData driveData : driveList) {
203           if (privateDrivePath.equals(driveData.getHomePath())) {
204             driveList.remove(driveData);
205             break;
206           }
207         }
208       }
209     }
210     rootElement.appendChild(buildXMLDriveNodes(document, driveList, driveType));
211     return Response.ok(new DOMSource(document), MediaType.TEXT_XML).cacheControl(cc).build();
212   }
213 
214   /**
215    * Gets all folders and files which can be viewed by the current user.
216    *
217    * @param driveName The drive name.
218    * @param workspaceName The workspace name.
219    * @param currentFolder The path to the folder to achieve its folders and files.
220    * @param showHidden Shows the hidden items or not. The default value is false.
221    * @return {@link Document} which contains the folders and files.
222    *
223    * @anchor ManageDocumentService.getFoldersAndFiles
224    */
225   @GET
226   @Path("/getFoldersAndFiles/")
227   @RolesAllowed("users")
228   public Response getFoldersAndFiles(@QueryParam("driveName") String driveName,
229                                      @QueryParam("workspaceName") String workspaceName,
230                                      @QueryParam("currentFolder") String currentFolder,
231                                      @DefaultValue("false") @QueryParam("showHidden") String showHidden) {
232     try {
233       Node node = getNode(driveName, workspaceName, currentFolder);
234       return buildXMLResponseForChildren(node, driveName, currentFolder, Boolean.valueOf(showHidden));
235     } catch (AccessDeniedException e) {
236       if (LOG.isDebugEnabled()) {
237         LOG.debug("Access is denied when perform get Folders and files: ", e);
238       }
239       return Response.status(Status.UNAUTHORIZED).entity(e.getMessage()).cacheControl(cc).build();
240     }
241     catch (PathNotFoundException e) {
242       if (LOG.isDebugEnabled()) {
243         LOG.debug("Item is not found: ", e);
244       }
245       return Response.status(Status.NOT_FOUND).entity(e.getMessage()).cacheControl(cc).build();
246     } catch (RepositoryException e) {
247       if (LOG.isErrorEnabled()) {
248         LOG.error("Repository is error: ", e);
249       }
250       return Response.status(Status.SERVICE_UNAVAILABLE).entity(e.getMessage()).cacheControl(cc).build();
251 
252     } catch (Exception e) {
253       if (LOG.isErrorEnabled()) {
254         LOG.error("Error when perform get Folders and files: ", e);
255       }
256       return Response.serverError().entity(e.getMessage()).cacheControl(cc).build();
257     }
258   }
259 
260   /**
261    * Deletes a folder/file.
262    *
263    * @param driveName The drive name.
264    * @param workspaceName The workspace name.
265    * @param itemPath The path to the folder/file.
266    * @return {@link Response} Returns the status of an item which has been deleted.
267    *
268    * @anchor ManageDocumentService.deleteFolderOrFile
269    */
270   @GET
271   @Path("/deleteFolderOrFile/")
272   @RolesAllowed("users")
273   public Response deleteFolderOrFile(@QueryParam("driveName") String driveName,
274                                      @QueryParam("workspaceName") String workspaceName,
275                                      @QueryParam("itemPath") String itemPath){
276     try {
277       Node node = getNode(driveName, workspaceName, itemPath);
278       Node parent = node.getParent();
279       node.remove();
280       parent.save();
281       return Response.ok().cacheControl(cc).build();
282     } catch (AccessDeniedException e) {
283       if (LOG.isDebugEnabled()) {
284         LOG.debug("Access is denied when perform delete folder or file: ", e);
285       }
286       return Response.status(Status.UNAUTHORIZED).entity(e.getMessage()).cacheControl(cc).build();
287     }
288     catch (PathNotFoundException e) {
289       if (LOG.isDebugEnabled()) {
290         LOG.debug("Item is not found: ", e);
291       }
292       return Response.status(Status.NOT_FOUND).entity(e.getMessage()).cacheControl(cc).build();
293     } catch (RepositoryException e) {
294       if (LOG.isErrorEnabled()) {
295         LOG.error("Repository is error: ", e);
296       }
297       return Response.status(Status.SERVICE_UNAVAILABLE).entity(e.getMessage()).cacheControl(cc).build();
298 
299     } catch (Exception e) {
300       if (LOG.isErrorEnabled()) {
301         LOG.error("Error when perform delete Folder or file: ", e);
302       }
303       return Response.serverError().entity(e.getMessage()).cacheControl(cc).build();
304     }
305   }
306 
307   /**
308    * Creates a new folder and returns its information.
309    *
310    * @param driveName The drive name.
311    * @param workspaceName The workspace name.
312    * @param currentFolder The path to the folder where a child folder is added.
313    * @param folderName The folder name.
314    * @return {@link Document} which contains the created folder.
315    * @throws Exception The exception
316    *
317    * @anchor ManageDocumentService.createFolder
318    */
319   @GET
320   @Path("/createFolder/")
321   @RolesAllowed("users")
322   public Response createFolder(@QueryParam("driveName") String driveName,
323                                @QueryParam("workspaceName") String workspaceName,
324                                @QueryParam("currentFolder") String currentFolder,
325                                @QueryParam("folderName") String folderName) throws Exception {
326     try {
327       Node node = getNode(driveName, workspaceName, currentFolder);
328       // The name automatically determined from the title according to the current algorithm.
329       String name = Text.escapeIllegalJcrChars(org.exoplatform.services.cms.impl.Utils.cleanString(folderName));
330       // Set default name if new title contain no valid character
331       name = (StringUtils.isEmpty(name)) ? DEFAULT_NAME : name;
332       Node newNode = node.addNode(name,
333                                   NodetypeConstant.NT_UNSTRUCTURED);
334       if (!newNode.hasProperty("exo:title")) {
335         newNode.addMixin("exo:rss-enable");
336       }
337       newNode.setProperty("exo:title", folderName);
338       node.save();
339       Document document = createNewDocument();
340       String childFolder = StringUtils.isEmpty(currentFolder) ? newNode.getName() : currentFolder.concat("/")
341                                                                                                  .concat(newNode.getName());
342       Element folderNode = createFolderElement(document, newNode, workspaceName, driveName, childFolder);
343       document.appendChild(folderNode);
344       return getResponse(document);
345     } catch (AccessDeniedException e) {
346       if (LOG.isDebugEnabled()) {
347         LOG.debug("Access is denied when perform create folder: ", e);
348       }
349       return Response.status(Status.UNAUTHORIZED).entity(e.getMessage()).cacheControl(cc).build();
350     } catch (PathNotFoundException e) {
351       if (LOG.isDebugEnabled()) {
352         LOG.debug("Item is not found: ", e);
353       }
354       return Response.status(Status.NOT_FOUND).entity(e.getMessage()).cacheControl(cc).build();
355     } catch (RepositoryException e) {
356       if (LOG.isErrorEnabled()) {
357         LOG.error("Repository is error: ", e);
358       }
359       return Response.status(Status.SERVICE_UNAVAILABLE)
360                      .entity(e.getMessage())
361                      .cacheControl(cc)
362                      .build();
363 
364     } catch (Exception e) {
365       if (LOG.isErrorEnabled()) {
366         LOG.error("Error when perform create folder: ", e);
367       }
368       return Response.serverError().entity(e.getMessage()).cacheControl(cc).build();
369     }
370   }
371 
372   /**
373    * Uploads a file to the server.
374    *
375    * @param uploadId The Id of the uploaded resource.
376    * @param servletRequest The request.
377    *
378    * @return The response.
379    *
380    * @throws Exception The exception
381    *
382    * @anchor ManageDocumentService.uploadFile
383    */
384   @POST
385   @Path("/uploadFile/upload/")
386   @RolesAllowed("users")
387 //  @InputTransformer(PassthroughInputTransformer.class)
388 //  @OutputTransformer(XMLOutputTransformer.class)
389   public Response uploadFile(@Context HttpServletRequest servletRequest,
390       @QueryParam("uploadId") String uploadId) throws Exception {
391     return fileUploadHandler.upload(servletRequest, uploadId, limit);
392   }
393 
394   /**
395    * Returns information about the upload status of a file, such as the upload percentage, the file name, and more.
396    *
397    * @param workspaceName The workspace name.
398    * @param driveName The drive name.
399    * @param currentFolder The path to the current folder.
400    * @param currentPortal The name of the current site.
401    * @param action The action to perform (saving, processing, and more).
402    * @param language The language of the user.
403    * @param fileName The name of the file.
404    * @param uploadId The Id of the uploaded resource.
405    * @return The response.
406    * @throws Exception The exception
407    *
408    * @anchor ManageDocumentService.processUpload
409    */
410   @GET
411   @Path("/uploadFile/control/")
412   @RolesAllowed("users")
413   public Response processUpload(
414       @QueryParam("workspaceName") String workspaceName,
415       @QueryParam("driveName") String driveName,
416       @QueryParam("currentFolder") String currentFolder,
417       @QueryParam("currentPortal") String currentPortal,
418       @QueryParam("action") String action,
419       @QueryParam("language") String language,
420       @QueryParam("fileName") String fileName,
421       @QueryParam("uploadId") String uploadId,
422       @QueryParam("existenceAction") String existenceAction) throws Exception {
423     try {
424       if ((workspaceName != null) && (driveName != null) && (currentFolder != null)) {
425         Node currentFolderNode = getNode(Text.escapeIllegalJcrChars(driveName),
426                                          Text.escapeIllegalJcrChars(workspaceName),
427                                          Text.escapeIllegalJcrChars(currentFolder));
428         String userId = ConversationState.getCurrent().getIdentity().getUserId();
429         return createProcessUploadResponse(Text.escapeIllegalJcrChars(workspaceName),
430                                            currentFolderNode,
431                                            currentPortal,
432                                            userId,
433                                            action,
434                                            language,
435                                            Text.escapeIllegalJcrChars(fileName),
436                                            uploadId, existenceAction);
437       }
438     } catch (Exception e) {
439       if (LOG.isErrorEnabled()) {
440         LOG.error("Error when perform processUpload: ", e);
441       }
442     }
443 
444     DateFormat dateFormat = new SimpleDateFormat(IF_MODIFIED_SINCE_DATE_FORMAT);
445     return Response.ok().header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date())).build();
446   }
447 
448   private Response buildXMLResponseForChildren(Node node,
449                                                String driveName,
450                                                String currentFolder,
451                                                boolean showHidden
452                                                ) throws Exception {
453     Document document = createNewDocument();
454     Element rootElement = createFolderElement(document,
455                                               node,
456                                               node.getSession().getWorkspace().getName(),
457                                               driveName,
458                                               currentFolder);
459     Element folders = document.createElement("Folders");
460     Element files = document.createElement("Files");
461     Node referParentNode = node;
462     if (node.isNodeType("exo:symlink") && node.hasProperty("exo:uuid") && node.hasProperty("exo:workspace")) {
463       referParentNode = linkManager.getTarget(node);
464     }
465     for (NodeIterator iterator = referParentNode.getNodes(); iterator.hasNext();) {
466       Node sourceNode = null;
467       Node referNode = null;
468       Node child = iterator.nextNode();
469       if (child.isNodeType(FCKUtils.EXO_HIDDENABLE) && !showHidden)
470         continue;
471       if (child.isNodeType("exo:symlink") && child.hasProperty("exo:uuid") && child.hasProperty("exo:workspace")) {
472         sourceNode = linkManager.getTarget(child);
473       }
474       referNode = sourceNode != null ? sourceNode : child;
475 
476       if (isFolder(referNode)) {
477         // Get current folder from folder path to fix same name problem (ECMS-3586)
478         String folderPath = child.getPath();
479         folderPath = folderPath.substring(folderPath.lastIndexOf("/") + 1, folderPath.length());
480         String childFolder = StringUtils.isEmpty(currentFolder) ? folderPath : currentFolder.concat("/")
481                                                                                     .concat(folderPath);
482         Element folder = createFolderElement(document,
483                                              child,
484                                              child.getSession().getWorkspace().getName(),
485                                              driveName,
486                                              childFolder);
487         folders.appendChild(folder);
488       } else   if (isFile(referNode)) {
489         Element file = createFileElement(document, referNode, child,
490                                          referNode.getSession().getWorkspace().getName());
491         files.appendChild(file);
492       } else {
493         continue;
494       }
495     }
496     rootElement.appendChild(folders);
497       rootElement.appendChild(files);
498     document.appendChild(rootElement);
499     return getResponse(document);
500   }
501 
502   private boolean isFolder(Node checkNode) throws RepositoryException {
503     return checkNode.isNodeType(NodetypeConstant.NT_FOLDER)
504         || checkNode.isNodeType(NodetypeConstant.NT_UNSTRUCTURED);
505   }
506 
507   private boolean isFile(Node checkNode) throws RepositoryException {
508     return checkNode.isNodeType(NodetypeConstant.NT_FILE);
509   }
510 
511   private Element createFolderElement(Document document,
512                                       Node child,
513                                       String workspaceName,
514                                       String driveName,
515                                       String currentFolder) throws Exception {
516     Element folder = document.createElement("Folder");
517     boolean hasChild = false;
518     boolean canRemove = true;
519     boolean canAddChild = true;
520     for (NodeIterator iterator = child.getNodes(); iterator.hasNext();) {
521       if (isFolder(iterator.nextNode())) {
522         hasChild = true;
523         break;
524       }
525     }
526     try {
527       getSession(workspaceName).checkPermission(child.getPath(), PermissionType.REMOVE);
528     } catch (Exception e) {
529       canRemove = false;
530     }
531 
532     try {
533       getSession(workspaceName).checkPermission(child.getPath(), PermissionType.ADD_NODE);
534     } catch (Exception e) {
535       canAddChild = false;
536     }
537 
538     folder.setAttribute("name", child.getName());
539     folder.setAttribute("title", Utils.getTitle(child));
540     folder.setAttribute("path", child.getPath());
541     folder.setAttribute("canRemove", String.valueOf(canRemove));
542     folder.setAttribute("canAddChild", String.valueOf(canAddChild));
543     folder.setAttribute("nodeType", getNodeTypeIcon(child));
544     folder.setAttribute("workspaceName", workspaceName);
545     folder.setAttribute("driveName", driveName);
546     folder.setAttribute("currentFolder", currentFolder);
547     folder.setAttribute("hasChild", String.valueOf(hasChild));
548     folder.setAttribute("titlePath", createTitlePath(driveName, workspaceName, currentFolder));
549 
550     return folder;
551   }
552 
553   private Element createFileElement(Document document,
554                                     Node sourceNode,
555                                     Node displayNode,
556                                     String workspaceName) throws Exception {
557     Element file = document.createElement("File");
558     AutoVersionService autoVersionService=WCMCoreUtils.getService(AutoVersionService.class);
559     boolean canRemove = true;
560     file.setAttribute("name", Utils.getTitle(displayNode));
561     file.setAttribute("title", Utils.getTitle(displayNode));
562     file.setAttribute("workspaceName", workspaceName);
563     SimpleDateFormat formatter = (SimpleDateFormat) SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.SHORT,
564                                                                                          SimpleDateFormat.SHORT);
565     file.setAttribute("dateCreated", formatter.format(sourceNode.getProperty("exo:dateCreated")
566                                                                 .getDate()
567                                                                 .getTime()));
568     if (sourceNode.hasProperty("exo:dateModified")) {
569       file.setAttribute("dateModified", formatter.format(sourceNode.getProperty("exo:dateModified")
570                                                                    .getDate()
571                                                                    .getTime()));
572     } else {
573       file.setAttribute("dateModified", null);
574     }
575     file.setAttribute("creator", sourceNode.getProperty("exo:owner").getString());
576     file.setAttribute("path", displayNode.getPath());
577     file.setAttribute("isVersioned", String.valueOf(sourceNode.isNodeType(NodetypeConstant.MIX_VERSIONABLE)));
578     file.setAttribute("isVersionSupport", String.valueOf(autoVersionService.isVersionSupport(sourceNode.getPath(), workspaceName)));
579     if (sourceNode.isNodeType("nt:file")) {
580       Node content = sourceNode.getNode("jcr:content");
581       file.setAttribute("nodeType", content.getProperty("jcr:mimeType").getString());
582     } else {
583       file.setAttribute("nodeType", sourceNode.getPrimaryNodeType().getName());
584     }
585 
586     long size = sourceNode.getNode("jcr:content").getProperty("jcr:data").getLength();
587     file.setAttribute("size", "" + size);
588     try {
589       getSession(workspaceName).checkPermission(sourceNode.getPath(), PermissionType.REMOVE);
590     } catch (Exception e) {
591       canRemove = false;
592     }
593     file.setAttribute("canRemove", String.valueOf(canRemove));
594     return file;
595   }
596 
597   private Node getNode(String driveName, String workspaceName, String currentFolder) throws Exception {
598     Session session = getSession(workspaceName);
599     String driveHomePath = manageDriveService.getDriveByName(Text.escapeIllegalJcrChars(driveName)).getHomePath();
600     String userId = ConversationState.getCurrent().getIdentity().getUserId();
601     String drivePath = Utils.getPersonalDrivePath(driveHomePath, userId);
602     Node node = (Node) session.getItem(Text.escapeIllegalJcrChars(drivePath));
603     if (StringUtils.isEmpty(currentFolder)) {
604       return node;
605     }
606     for (String folder : currentFolder.split("/")) {
607       if (node.hasNode(folder)){
608         node = node.getNode(folder);
609         if (node.isNodeType(NodetypeConstant.EXO_SYMLINK)) node = linkManager.getTarget(node);
610       } else if (node.isNodeType(NodetypeConstant.EXO_SYMLINK)) {
611         node = linkManager.getTarget(node).getNode(folder);
612       } else {
613         return node;
614       }
615     }
616     return node;
617   }
618 
619   private Session getSession(String workspaceName) throws Exception {
620     SessionProvider sessionProvider = WCMCoreUtils.getUserSessionProvider();
621     ManageableRepository manageableRepository = getCurrentRepository();
622     return sessionProvider.getSession(workspaceName, manageableRepository);
623   }
624 
625   private Document createNewDocument() throws ParserConfigurationException {
626     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
627     DocumentBuilder builder = factory.newDocumentBuilder();
628     return builder.newDocument();
629   }
630 
631   private ManageableRepository getCurrentRepository() throws RepositoryException {
632     RepositoryService repositoryService = WCMCoreUtils.getService(RepositoryService.class);
633     return repositoryService.getCurrentRepository();
634   }
635 
636   private Response getResponse(Document document) {
637     DateFormat dateFormat = new SimpleDateFormat(IF_MODIFIED_SINCE_DATE_FORMAT);
638     return Response.ok(new DOMSource(document), MediaType.TEXT_XML)
639                    .cacheControl(cc)
640                    .header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date()))
641                    .build();
642   }
643 
644   /**
645    * Build drive node from drive list.
646    *
647    * @param document the document.
648    * @param drivesList the drives list.
649    * @param driveType the drive type.
650    *
651    * @return the element
652    */
653   private Element buildXMLDriveNodes(Document document, List<DriveData> drivesList, String driveType) throws Exception {
654     Element folders = document.createElement("Folders");
655     folders.setAttribute("name", driveType);
656     for (DriveData drive : drivesList) {
657       Element folder = document.createElement("Folder");
658       folder.setAttribute("name", drive.getName());
659       folder.setAttribute("nodeType", driveType + " " + drive.getName().replaceAll(" ", "_"));
660       folder.setAttribute("workspaceName", drive.getWorkspace());
661       folder.setAttribute("canAddChild", drive.getAllowCreateFolders());
662       folders.appendChild(folder);
663     }
664     return folders;
665   }
666 
667   /**
668    * Gets the memberships.
669    *
670    * @return the memberships
671    *
672    * @throws Exception the exception
673    */
674   private List<String> getMemberships() throws Exception {
675     List<String> userMemberships = new ArrayList<String>();
676     String userId = ConversationState.getCurrent().getIdentity().getUserId();
677     userMemberships.add(userId);
678     Collection<?> memberships = ConversationState.getCurrent().getIdentity().getMemberships();
679     if (memberships == null || memberships.size() < 0)
680       return userMemberships;
681     Object[] objects = memberships.toArray();
682     for (int i = 0; i < objects.length; i++) {
683       MembershipEntry membership = (MembershipEntry) objects[i];
684       String role = membership.getMembershipType() + ":" + membership.getGroup();
685       userMemberships.add(role);
686     }
687     return userMemberships;
688   }
689 
690   public static String getNodeTypeIcon(Node node) throws RepositoryException {
691     StringBuilder str = new StringBuilder();
692     if (node == null)
693       return "";
694     String nodeType = node.getPrimaryNodeType().getName();
695     if (node.isNodeType(EXO_SYMLINK)) {
696       LinkManager linkManager = WCMCoreUtils.getService(LinkManager.class);
697       try {
698         nodeType = node.getProperty(EXO_PRIMARYTYPE).getString();
699         node = linkManager.getTarget(node);
700         if (node == null)
701           return "";
702       } catch (Exception e) {
703         return "";
704       }
705     }
706     if (node.isNodeType(EXO_TRASH_FOLDER)) {
707       nodeType = EXO_TRASH_FOLDER;
708     }
709     if (node.isNodeType(EXO_FAVOURITE_FOLDER))
710       nodeType = EXO_FAVOURITE_FOLDER;
711     if (nodeType.equals(NT_UNSTRUCTURED) || nodeType.equals(NT_FOLDER)) {
712       for (String specificFolder : SPECIFIC_FOLDERS) {
713         if (node.isNodeType(specificFolder)) {
714           nodeType = specificFolder;
715           break;
716         }
717       }
718     }
719     str.append(nodeType);
720     return str.toString();
721   }
722 
723   /**
724    * Creates the process upload response.
725    *
726    * @param workspaceName the workspace name.
727    * @param userId The user Id.
728    * @param action The action.
729    * @param language The language.
730    * @param fileName The file name.
731    * @param uploadId The upload Id.
732    * @param siteName The portal name.
733    * @param currentFolderNode The current folder node.
734    *
735    * @return the response
736    *
737    * @throws Exception the exception
738    */
739   protected Response createProcessUploadResponse(String workspaceName,
740                                                  Node currentFolderNode,
741                                                  String siteName,
742                                                  String userId,
743                                                  String action,
744                                                  String language,
745                                                  String fileName,
746                                                  String uploadId,
747                                                  String existenceAction) throws Exception {
748     if (FileUploadHandler.SAVE_ACTION.equals(action)) {
749       CacheControl cacheControl = new CacheControl();
750       cacheControl.setNoCache(true);
751       DocumentContext.getCurrent().getAttributes().put(DocumentContext.IS_SKIP_RAISE_ACT, true);
752       return fileUploadHandler.saveAsNTFile(currentFolderNode, uploadId, org.exoplatform.services.cms.impl.Utils.cleanName(fileName), language, siteName, userId, existenceAction);
753     }
754     return fileUploadHandler.control(uploadId, action);
755   }
756 
757   private String createTitlePath(String driveName, String workspaceName, String currentFolder) throws Exception {
758     String[] folders = currentFolder.split("/");
759     StringBuilder sb = new StringBuilder();
760     StringBuilder tempFolder = new StringBuilder();
761     Node parentNode = getNode(driveName, workspaceName, "");
762     if (StringUtils.isEmpty(currentFolder)) {
763       return "";
764     }
765     for (int i = 0; i < folders.length; i++) {
766       tempFolder = tempFolder.append(folders[i]);
767       Node node = null;
768       try {
769         node = getNode(driveName, workspaceName, tempFolder.toString());
770       } catch (PathNotFoundException e) {
771         node = parentNode.getNode(folders[i]);
772       }
773       tempFolder = tempFolder.append("/");
774       sb.append(Utils.getTitle(node));
775       if (i != folders.length - 1) {
776         sb.append("/");
777       }
778       parentNode = (node.isNodeType("exo:symlink")? linkManager.getTarget(node) : node);
779     }
780     return sb.toString();
781   }
782 }