View Javadoc
1   /*
2    * Copyright (C) 2003-2007 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.services.cms.drives.impl;
18  
19  import org.exoplatform.services.cache.CacheService;
20  import org.exoplatform.services.cache.ExoCache;
21  import org.exoplatform.services.cms.BasePath;
22  import org.exoplatform.services.cms.drives.DriveData;
23  import org.exoplatform.services.cms.drives.ManageDriveService;
24  import org.exoplatform.services.cms.impl.DMSConfiguration;
25  import org.exoplatform.services.cms.impl.DMSRepositoryConfiguration;
26  import org.exoplatform.services.cms.impl.Utils;
27  import org.exoplatform.services.jcr.RepositoryService;
28  import org.exoplatform.services.jcr.core.ManageableRepository;
29  import org.exoplatform.services.jcr.ext.common.SessionProvider;
30  import org.exoplatform.services.jcr.ext.hierarchy.NodeHierarchyCreator;
31  import org.exoplatform.services.log.ExoLogger;
32  import org.exoplatform.services.log.Log;
33  import org.exoplatform.services.organization.Membership;
34  import org.exoplatform.services.organization.OrganizationService;
35  import org.exoplatform.services.security.ConversationState;
36  import org.exoplatform.services.wcm.utils.WCMCoreUtils;
37  import org.picocontainer.Startable;
38  
39  import javax.jcr.Node;
40  import javax.jcr.NodeIterator;
41  import javax.jcr.PathNotFoundException;
42  import javax.jcr.RepositoryException;
43  import javax.jcr.Session;
44  import java.io.Serializable;
45  import java.util.*;
46  import java.util.stream.Collectors;
47  
48  /**
49   * Created by The eXo Platform SARL
50   * Author : Nguyen Quang Hung
51   *          nguyenkequanghung@yahoo.com
52   * Feb 27, 2006
53   */
54  public class ManageDriveServiceImpl implements ManageDriveService, Startable {
55  
56    /**
57     * Name of property WORKSPACE
58     */
59    private static String WORKSPACE = "exo:workspace";
60  
61    private static String ALL_DRIVES_CACHED = "allDrives";
62  
63    private static String ALL_DRIVES_CACHED_WITH_VIRTUAL = "allDrives_withVirtual";
64  
65    private static String ALL_DRIVES_CACHED_BY_ROLES = "_allDrivesByRoles";
66  
67    private static String ALL_MAIN_CACHED_DRIVE = "_mainDrives";
68  
69    private static String ALL_PERSONAL_CACHED_DRIVE = "_personalDrives";
70  
71    private static String ALL_GROUP_CACHED_DRIVES = "_groupDrives";
72    
73    private static String ALL_GROUP_PERMISSION = "*:${groupId}";
74  
75    private static String ALL_USER_PERMISSION = "${userId}";
76    /**
77     * Name of property PERMISSIONS
78     */
79    private static String PERMISSIONS = "exo:accessPermissions" ;
80  
81    /**
82     * Name of property VIEWS
83     */
84    private static String VIEWS = "exo:views" ;
85  
86    /**
87     * Name of property ICON
88     */
89    private static String ICON = "exo:icon" ;
90  
91    /**
92     * Name of property PATH
93     */
94    private static String PATH = "exo:path" ;
95  
96    /**
97     * Name of property VIEW_REFERENCES
98     */
99    private static String VIEW_REFERENCES = "exo:viewPreferences" ;
100 
101   /**
102    * Name of property VIEW_NON_DOCUMENT
103    */
104   private static String VIEW_NON_DOCUMENT = "exo:viewNonDocument" ;
105 
106   /**
107    * Name of property VIEW_SIDEBAR
108    */
109   private static String VIEW_SIDEBAR = "exo:viewSideBar" ;
110 
111   /**
112    * Name of property SHOW_HIDDEN_NODE
113    */
114   private static String SHOW_HIDDEN_NODE = "exo:showHiddenNode" ;
115 
116   /**
117    *  Name of property ALLOW_CREATE_FOLDER
118    */
119   private static String ALLOW_CREATE_FOLDER = "exo:allowCreateFolders" ;
120   private static String ALLOW_NODETYPES_ON_TREE = "exo:allowNodeTypesOnTree";
121   public static final String GROUPS_DRIVE_NAME = "Groups";
122   public static final String GROUPS_DRIVE_ROOT_NODE = "Groups";
123   public static final String PERSONAL_DRIVE_NAME = "Personal Documents";
124   public static final String PERSONAL_DRIVE_PUBLIC_FOLDER_NAME = "Public";
125   public static final String PERSONAL_DRIVE_PRIVATE_FOLDER_NAME = "Private";
126   public static final String USER_DRIVE_NAME = "User Documents";
127   public static final String PERSONAL_DRIVE_ROOT_NODE = "Users";
128   public static final String DRIVE_PARAMATER_USER_ID = "userId";
129   public static final String DRIVE_PARAMATER_GROUP_ID = "groupId";
130 
131   private final static String CACHE_NAME = "ecms.drive";
132 
133   /**
134    * List of ManageDrivePlugin
135    */
136   private List<ManageDrivePlugin> drivePlugins_  = new ArrayList<ManageDrivePlugin> ();
137 
138   /**
139    * RepositoryService object
140    */
141   private RepositoryService repositoryService_ ;
142 
143   /**
144    * OrganizationService object
145    */
146   private OrganizationService organizationService ;
147 
148   /**
149    * Path to drive home directory
150    */
151   private String baseDrivePath_ ;
152 
153   /**
154    * NodeHierarchyCreator object
155    */
156   private NodeHierarchyCreator nodeHierarchyCreator_ ;
157 
158   private DMSConfiguration dmsConfiguration_;
159   private static final Log LOG  = ExoLogger.getLogger(ManageDriveServiceImpl.class.getName());
160   private static final String DELETED_DRIVE_NAMES= "DeletedDriveNames";
161 
162   /**
163    * Keep the drives of repository
164    */
165   private ExoCache<Serializable, Object> drivesCache_ ;
166 
167   private DriveData groupDriveTemplate_ = null ;
168 
169   /**
170    * Keep the state when a new role added
171    */
172   private boolean newRoleUpdated = false;
173 
174   /**
175    * Constructor method
176    * Construcs RepositoryService, NodeHierarchyCreator, baseDrivePath_
177    * @param jcrService
178    * @param nodeHierarchyCreator
179    * @throws Exception
180    */
181   public ManageDriveServiceImpl(RepositoryService jcrService,
182                                 NodeHierarchyCreator nodeHierarchyCreator, DMSConfiguration dmsConfiguration,
183                                 CacheService caService,
184                                 OrganizationService organizationService) throws Exception{
185     repositoryService_ = jcrService ;
186     nodeHierarchyCreator_ = nodeHierarchyCreator ;
187     baseDrivePath_ = nodeHierarchyCreator_.getJcrPath(BasePath.EXO_DRIVES_PATH);
188     dmsConfiguration_ = dmsConfiguration;
189     drivesCache_ = caService.getCacheInstance(CACHE_NAME);
190     this.organizationService = organizationService;
191   }
192 
193   /**
194    * Implemented method from Startable class
195    * init all ManageDrivePlugin
196    */
197   public void start() {
198     try{
199       for(ManageDrivePlugin plugin : drivePlugins_) {
200         plugin.init() ;
201       }
202       getAllDrives(true);
203     }catch(Exception e) {
204       if (LOG.isWarnEnabled()) {
205         LOG.warn(e.getMessage());
206       }
207     }
208   }
209 
210   /**
211    * Implemented method from Startable class
212    */
213   public void stop() { }
214 
215   /**
216    * Init drive node with specified repository
217    */
218   public void init() throws Exception {
219     for(ManageDrivePlugin plugin : drivePlugins_) {
220       plugin.init() ;
221     }
222     getAllDrives();
223   }
224 
225   /**
226    * Add new ManageDrivePlugin to drivePlugins_
227    * @param drivePlugin
228    */
229   public void setManageDrivePlugin(ManageDrivePlugin drivePlugin) {
230     drivePlugins_.add(drivePlugin) ;
231   }
232 
233   /**
234    * {@inheritDoc}
235    */
236   public List<DriveData> getAllDrives() throws Exception {
237     return getAllDrives(false);
238   }
239 
240   /**
241    * {@inheritDoc}
242    */
243   @SuppressWarnings("unchecked")
244   public List<DriveData> getAllDrives(boolean withVirtualDrives) throws Exception {
245     // Try to get from cache
246     List<DriveData> allDrives;
247     if (withVirtualDrives) {
248       allDrives = (List<DriveData>) drivesCache_.get(getRepoName() + "_" + ALL_DRIVES_CACHED_WITH_VIRTUAL);
249     } else {
250       allDrives = (List<DriveData>) drivesCache_.get(getRepoName() + "_" + ALL_DRIVES_CACHED);
251     }
252     if ((allDrives != null) && (allDrives.size() > 0) && (groupDriveTemplate_ != null)) {
253       return cloneArrayList(allDrives);
254     }
255 
256     // Get from jcr
257     Session session = getSession() ;
258     Node driveHome = (Node)session.getItem(baseDrivePath_);
259     NodeIterator itr = driveHome.getNodes() ;
260     List<DriveData> driveList = new ArrayList<DriveData>() ;
261     DriveData data = null;
262     Node drive = null;
263     while(itr.hasNext()) {
264       data = new DriveData() ;
265       drive = itr.nextNode() ;      
266       data.setName(drive.getName()) ;
267       data.setWorkspace(drive.getProperty(WORKSPACE).getString()) ;
268       data.setHomePath(drive.getProperty(PATH).getString()) ;
269       data.setPermissions(drive.getProperty(PERMISSIONS).getString()) ;
270       data.setViews(drive.getProperty(VIEWS).getString()) ;
271       data.setIcon(drive.getProperty(ICON).getString()) ;
272       data.setViewPreferences(Boolean.parseBoolean(drive.getProperty(VIEW_REFERENCES).getString())) ;
273       data.setViewNonDocument(Boolean.parseBoolean(drive.getProperty(VIEW_NON_DOCUMENT).getString())) ;
274       data.setViewSideBar(Boolean.parseBoolean(drive.getProperty(VIEW_SIDEBAR).getString())) ;
275       data.setShowHiddenNode(Boolean.parseBoolean(drive.getProperty(SHOW_HIDDEN_NODE).getString())) ;
276       data.setAllowCreateFolders(drive.getProperty(ALLOW_CREATE_FOLDER).getString()) ;
277       data.setAllowNodeTypesOnTree(drive.getProperty(ALLOW_NODETYPES_ON_TREE).getString());
278       if (GROUPS_DRIVE_NAME.equals(data.getName())) {
279         groupDriveTemplate_ = data.clone();
280         // Include group drive template if necessary
281         if (withVirtualDrives) {
282           driveList.add(data.clone());
283         }
284       } else {
285         driveList.add(data.clone());
286       }
287     }
288 
289     // Put drives to cache
290     if (withVirtualDrives) {
291       drivesCache_.put(getRepoName() + "_" + ALL_DRIVES_CACHED_WITH_VIRTUAL, driveList);
292     } else {
293       drivesCache_.put(getRepoName() + "_" + ALL_DRIVES_CACHED, driveList);
294     }
295     session.logout();
296     return cloneArrayList(driveList);
297   }
298 
299   /**
300    * {@inheritDoc}
301    */
302   public DriveData getDriveByName(String name) throws Exception{
303     if (name.startsWith(".")) {
304       String groupName = name.replace(".", "/");
305       if (groupDriveTemplate_ == null) return null;
306       DriveData drive = groupDriveTemplate_.clone();
307       drive.setHomePath(groupDriveTemplate_.getHomePath().replace("${groupId}", groupName));
308       drive.setName(name);
309       drive.getParameters().put(ManageDriveServiceImpl.DRIVE_PARAMATER_GROUP_ID, name);
310       drive.setPermissions("*:" + groupName);
311       return drive;
312     }
313 
314     Session session = getSession() ;
315     Node driveHome = (Node)session.getItem(baseDrivePath_);
316     if (driveHome.hasNode(name)){
317       Node drive = driveHome.getNode(name) ;
318       DriveData data = new DriveData() ;
319       data.setName(drive.getName()) ;
320       data.setWorkspace(drive.getProperty(WORKSPACE).getString()) ;
321       data.setHomePath(drive.getProperty(PATH).getString()) ;
322       data.setPermissions(drive.getProperty(PERMISSIONS).getString()) ;
323       data.setViews(drive.getProperty(VIEWS).getString()) ;
324       data.setIcon(drive.getProperty(ICON).getString()) ;
325       data.setViewPreferences(Boolean.parseBoolean(drive.getProperty(VIEW_REFERENCES).getString())) ;
326       data.setViewNonDocument(Boolean.parseBoolean(drive.getProperty(VIEW_NON_DOCUMENT).getString())) ;
327       data.setViewSideBar(Boolean.parseBoolean(drive.getProperty(VIEW_SIDEBAR).getString())) ;
328       data.setShowHiddenNode(Boolean.parseBoolean(drive.getProperty(SHOW_HIDDEN_NODE).getString())) ;
329       data.setAllowCreateFolders(drive.getProperty(ALLOW_CREATE_FOLDER).getString()) ;
330       try {
331         data.setAllowNodeTypesOnTree(drive.getProperty(ALLOW_NODETYPES_ON_TREE).getString());
332       } catch(PathNotFoundException e) {
333         data.setAllowNodeTypesOnTree("*");
334       }
335       session.logout();
336       return data ;
337     }
338     session.logout();
339     return null ;
340   }
341 
342   /**
343    * {@inheritDoc}
344    */
345   public void addDrive(String name, String workspace, String permissions, String homePath,
346                        String views, String icon, boolean viewReferences, boolean viewNonDocument,
347                        boolean viewSideBar, boolean showHiddenNode, String allowCreateFolder, String allowNodeTypesOnTree) throws Exception {
348     Session session = getSession();
349     Node driveHome = (Node)session.getItem(baseDrivePath_) ;
350     if (!driveHome.hasNode(name)){
351       Node driveNode = driveHome.addNode(name, "exo:drive");
352       driveNode.setProperty(WORKSPACE, workspace) ;
353       driveNode.setProperty(PERMISSIONS, permissions) ;
354       driveNode.setProperty(PATH, homePath) ;
355       driveNode.setProperty(VIEWS, views) ;
356       driveNode.setProperty(ICON, icon) ;
357       driveNode.setProperty(VIEW_REFERENCES, Boolean.toString(viewReferences)) ;
358       driveNode.setProperty(VIEW_NON_DOCUMENT, Boolean.toString(viewNonDocument)) ;
359       driveNode.setProperty(VIEW_SIDEBAR, Boolean.toString(viewSideBar)) ;
360       driveNode.setProperty(ALLOW_CREATE_FOLDER, allowCreateFolder) ;
361       driveNode.setProperty(SHOW_HIDDEN_NODE, Boolean.toString(showHiddenNode)) ;
362       driveNode.setProperty(ALLOW_NODETYPES_ON_TREE, allowNodeTypesOnTree);
363       driveHome.save() ;
364     } else{
365       Node driveNode = driveHome.getNode(name);
366       driveNode.setProperty(WORKSPACE, workspace) ;
367       driveNode.setProperty(PERMISSIONS, permissions) ;
368       driveNode.setProperty(PATH, homePath) ;
369       driveNode.setProperty(VIEWS, views) ;
370       driveNode.setProperty(ICON, icon) ;
371       driveNode.setProperty(VIEW_REFERENCES, Boolean.toString(viewReferences)) ;
372       driveNode.setProperty(VIEW_NON_DOCUMENT, Boolean.toString(viewNonDocument)) ;
373       driveNode.setProperty(VIEW_SIDEBAR, Boolean.toString(viewSideBar)) ;
374       driveNode.setProperty(ALLOW_CREATE_FOLDER, allowCreateFolder) ;
375       driveNode.setProperty(SHOW_HIDDEN_NODE, Boolean.toString(showHiddenNode)) ;
376       driveNode.setProperty(ALLOW_NODETYPES_ON_TREE, allowNodeTypesOnTree);
377       driveNode.save() ;
378     }
379     drivesCache_.clearCache();
380     session.save() ;
381     session.logout();
382   }
383 
384   /**
385    * {@inheritDoc}
386    */
387   public List<DriveData> getAllDriveByPermission(String permission) throws Exception {
388     List<DriveData> driveByPermission = new ArrayList<DriveData>() ;
389     try{
390       List<DriveData> driveList = getAllDrives();
391       for(DriveData drive : driveList) {
392         if(drive.hasPermission(drive.getAllPermissions(), permission)){
393           driveByPermission.add(drive) ;
394         }
395       }
396     } catch(Exception e) {
397       if (LOG.isErrorEnabled()) {
398         LOG.error("Unexpected error", e);
399       }
400     }
401     return driveByPermission ;
402   }
403 
404   /**
405    * {@inheritDoc}
406    */
407   public void removeDrive(String driveName) throws Exception {
408     Session session = getSession();
409     Node driveHome = (Node)session.getItem(baseDrivePath_) ;
410     if(driveHome.hasNode(driveName)){
411       driveHome.getNode(driveName).remove() ;
412       driveHome.save() ;
413     }
414     drivesCache_.clearCache();
415     session.logout();
416 
417     this.updateDeletedDrivesLog(driveName);
418   }
419 
420   /**
421    * Get session from repository in SystemWorkspace name
422    * @return session
423    * @throws Exception
424    */
425   private Session getSession() throws Exception {
426     ManageableRepository manaRepository = repositoryService_.getCurrentRepository();
427     DMSRepositoryConfiguration dmsRepoConfig = dmsConfiguration_.getConfig();
428     return manaRepository.getSystemSession(dmsRepoConfig.getSystemWorkspace()) ;
429   }
430 
431   /**
432    * Get session from repository in SystemWorkspace name
433    * @return session
434    * @throws Exception
435    */
436   private String getRepoName() {
437     try {
438       String repositoryName = repositoryService_.getCurrentRepository().getConfiguration().getName();
439       if (LOG.isDebugEnabled()) {
440         LOG.debug("The repository name is: " + repositoryName);
441       }
442       return repositoryName;
443     } catch (RepositoryException e) {
444       if (e.getMessage().equalsIgnoreCase("Repository 'null' not found.")) {
445         String repositoryName = System.getProperty("gatein.tenant.repository.name");
446         return repositoryName;
447       }
448       if (LOG.isErrorEnabled()) {
449         LOG.error("Repository exception occurs:", e);
450       }
451       return null;
452     }
453   }
454 
455   /**
456    * {@inheritDoc}
457    */
458   public boolean isUsedView(String viewName) throws Exception {
459     Session session = getSession();
460     Node driveHome = (Node)session.getItem(baseDrivePath_) ;
461     NodeIterator iter = driveHome.getNodes() ;
462     while(iter.hasNext()) {
463       Node drive = iter.nextNode() ;
464       String[] views = drive.getProperty("exo:views").getString().split(",") ;
465       for(String view : views) {
466         if(viewName.equals(view)) {
467           session.logout();
468           return true ;
469         }
470       }
471     }
472     session.logout();
473     return false;
474   }
475 
476   /**
477    * {@inheritDoc}
478    */
479   public List<DriveData> getDriveByUserRoles(String userId, List<String> userRoles) throws Exception {
480     Object drivesByRoles = drivesCache_.get(getRepoName() + "_" + userId + ALL_DRIVES_CACHED_BY_ROLES);
481     if (drivesByRoles != null)
482       return cloneArrayList(drivesByRoles);
483     List<DriveData> driveList = new ArrayList<DriveData>();
484     if (userId != null) {
485       // We will improve ManageDrive service to allow getAllDriveByUser
486       for (DriveData drive : getAllDrives()) {
487         String[] allPermission = drive.getAllPermissions();
488         boolean flag = false;
489         for (String permission : allPermission) {
490           if (permission.equalsIgnoreCase("${userId}")) {
491             if(!driveList.contains(drive)) driveList.add(drive);
492             flag = true;
493             break;
494           }
495           if (permission.equalsIgnoreCase("*")) {
496             if(!driveList.contains(drive)) driveList.add(drive);
497             flag = true;
498             break;
499           }
500           if (flag) continue;
501           for (String rolse : userRoles) {
502             if (drive.hasPermission(allPermission, rolse)) {
503               if(!driveList.contains(drive)) driveList.add(drive);
504               break;
505             }
506           }
507         }
508       }
509       for (DriveData drive : getGroupDrives(userId, userRoles)) {
510         if(!driveList.contains(drive)) driveList.add(drive); 
511       }
512     } else {
513       for (DriveData drive : getAllDrives()) {
514         String[] allPermission = drive.getAllPermissions();
515         for (String permission : allPermission) {
516           if (permission.equalsIgnoreCase("*")) {
517             driveList.add(drive);
518             break;
519           }
520         }
521       }
522     }
523     Collections.sort(driveList);
524     drivesCache_.put(getRepoName() + "_" + userId + ALL_DRIVES_CACHED_BY_ROLES, driveList);
525     return cloneArrayList(driveList);
526   }
527 
528   /**
529    * {@inheritDoc}
530    */
531   public List<DriveData> getGroupDrives(String userId, List<String> userRoles) throws Exception {
532     Object drives = drivesCache_.get(getRepoName() + "_" + userId + ALL_GROUP_CACHED_DRIVES);
533     if (drives != null)
534       return cloneArrayList(drives);
535     List<DriveData> groupDrives = new ArrayList<DriveData>();
536     DriveData groupDrive = getDriveByName(GROUPS_DRIVE_NAME);
537     if(groupDrive == null){
538       return cloneArrayList(groupDrives);
539     }
540 
541     boolean flag = hasPermissionOnDrive(groupDrive, userRoles);
542     if(flag){
543       for (String role : userRoles) {
544         String group = role.substring(role.indexOf(":")+1);
545         if (groupDriveTemplate_ != null && group.charAt(0)=='/') {
546           DriveData drive = groupDriveTemplate_.clone();
547           drive.setHomePath(groupDriveTemplate_.getHomePath().replace("${groupId}", group));
548           drive.setName(group.replace("/", "."));
549           drive.setPermissions("*:"+group);
550           if (!groupDrives.contains(drive))
551             groupDrives.add(drive);
552         }
553       }
554     }  
555     Collections.sort(groupDrives);
556     drivesCache_.put(getRepoName() + "_" + userId + ALL_GROUP_CACHED_DRIVES, groupDrives);
557     return cloneArrayList(groupDrives);
558   }
559 
560   /**
561    * {@inheritDoc}
562    */
563   public DriveData getGroupDriveTemplate() {
564     return groupDriveTemplate_;
565   }
566 
567   /**
568    * {@inheritDoc}
569    */
570   public List<DriveData> getMainDrives(String userId, List<String> userRoles) throws Exception {
571     Object drives = drivesCache_.get(getRepoName() + "_" + userId + ALL_MAIN_CACHED_DRIVE);
572     if(drives != null) return cloneArrayList(drives);
573     List<DriveData> generalDrives = new ArrayList<DriveData>();
574     List<DriveData> groupDrives = this.getGroupDrives(userId, userRoles);
575     List<DriveData> personalDrives = this.getPersonalDrives(userId);
576     for(DriveData drive : getDriveByUserRoles(userId, userRoles)) {
577       if (!groupDrives.contains(drive) && !personalDrives.contains(drive)) {
578         generalDrives.add(drive);
579       }
580     }
581     Collections.sort(generalDrives);
582     drivesCache_.put(getRepoName() + "_" + userId + ALL_MAIN_CACHED_DRIVE, generalDrives);
583     return cloneArrayList(generalDrives);
584   }
585 
586   /**
587    * {@inheritDoc}
588    */
589   public List<DriveData> getPersonalDrives(String userId) throws Exception {
590     SessionProvider sessionProvider = WCMCoreUtils.getSystemSessionProvider();
591     Node userNode = nodeHierarchyCreator_.getUserNode(sessionProvider, userId);
592     Object drives = drivesCache_.get(getRepoName() + "_" + userId + ALL_PERSONAL_CACHED_DRIVE);
593     if(drives != null) return cloneArrayList(drives);
594 
595     String cmsUserPath = nodeHierarchyCreator_.getJcrPath(BasePath.CMS_USERS_PATH);
596     List<String> memberships = getUserMemberships(userId);
597     List<DriveData> personalDrives = new ArrayList<>();
598     String userPath = userNode.getPath();
599     for(DriveData drive : getAllDrives()) {
600       if((drive.getHomePath().startsWith(cmsUserPath + "/${userId}")
601               || drive.getHomePath().startsWith(userPath + "/"))
602               && !USER_DRIVE_NAME.equals(drive.getName())
603               && hasPermissionOnDrive(drive, memberships)) {
604         personalDrives.add(drive);
605       }
606     }
607     Collections.sort(personalDrives);
608     drivesCache_.put(getRepoName() + "_" + userId + ALL_PERSONAL_CACHED_DRIVE, personalDrives);
609     return cloneArrayList(personalDrives);
610   }
611 
612   protected boolean hasPermissionOnDrive(DriveData drive, List<String> userMemberships) {
613     String[] allPermission = drive.getAllPermissions();
614     if(ALL_GROUP_PERMISSION.equals(allPermission[0]) || ALL_USER_PERMISSION.equals(allPermission[0])) {
615       return true;
616     }
617     for (String membership : userMemberships) {
618       if (drive.hasPermission(allPermission, membership)) {
619         return true;
620       }
621     }
622     return false;
623   }
624 
625   protected List<String> getUserMemberships(String userId) throws Exception {
626     List<String> memberships = null;
627     String currentUser = ConversationState.getCurrent().getIdentity().getUserId();
628     if(currentUser.equals(userId)) {
629       memberships = Utils.getMemberships();
630     } else {
631       Collection<Membership> colMemberships = organizationService.getMembershipHandler().findMembershipsByUser(userId);
632       memberships = colMemberships.stream().map(m -> m.getMembershipType() + ":" + m.getGroupId()).collect(Collectors.toList());
633     }
634     return memberships;
635   }
636 
637   /**
638    * {@inheritDoc}
639    */
640   public boolean isVitualDrive(String driveName) {
641     if (groupDriveTemplate_ == null) return false;
642     return groupDriveTemplate_.getName().equals(driveName);
643   }
644 
645   /**
646    * {@inheritDoc}
647    */
648   public void clearAllDrivesCache() {
649     drivesCache_.clearCache();
650   }
651 
652   /**
653    * {@inheritDoc}
654    */
655   public void clearGroupCache(String userId) {
656     drivesCache_.remove(getRepoName() + "_" + userId + ALL_GROUP_CACHED_DRIVES);
657     drivesCache_.remove(getRepoName() + "_" + userId + ALL_DRIVES_CACHED_BY_ROLES);
658   }
659 
660   /**
661    * {@inheritDoc}
662    */
663   public boolean newRoleUpdated() {
664     return newRoleUpdated;
665   }
666 
667   /**
668    * {@inheritDoc}
669    */
670   public void setNewRoleUpdated(boolean newRoleUpdated) {
671     this.newRoleUpdated = newRoleUpdated;
672   }
673 
674   /**
675    * {@inheritDoc}
676    */
677   @Override
678   public String getDriveOfDefaultWorkspace() throws Exception {
679     DriveData collaDrive = getDriveByName(COLLABORATION_DRIVE);
680     if(collaDrive != null && collaDrive.getHomePath().equals("/")) {
681       return COLLABORATION_DRIVE;
682     }
683     List<DriveData> listDrive = getAllDrives();
684     String defautlWsName = repositoryService_.getCurrentRepository().getConfiguration().getDefaultWorkspaceName();
685     for(DriveData drive : listDrive) {
686       if(drive.getWorkspace().equals(defautlWsName) && drive.getHomePath().equals("/")) {
687         return drive.getName();
688       }
689     }
690     return null;
691   }
692 
693   @Override
694   public Set<String> getDeletedDriveNames() throws Exception {
695     return Utils.getAllEditedConfiguredData(this.getClass().getSimpleName(), DELETED_DRIVE_NAMES, true);
696   }
697 
698   /**
699    * Mark deleted drive to log file.
700    *
701    * @param driveName Drive Name
702    * @throws Exception
703    */
704   private void updateDeletedDrivesLog(String driveName) throws Exception {
705     Utils.addEditedConfiguredData(driveName, this.getClass().getSimpleName(), DELETED_DRIVE_NAMES, true);
706   }
707 
708   private List<DriveData> cloneArrayList(Object drivesByRoles) {
709     @SuppressWarnings("unchecked")
710     ArrayList<DriveData> drivesByRolesList = (ArrayList<DriveData>) drivesByRoles;
711     List<DriveData> drivesList = new ArrayList<>();
712     for (DriveData driveData : drivesByRolesList) {
713       drivesList.add(driveData.clone());
714     }
715     return drivesList;
716   }
717 }