001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.documentlibrary.service.impl;
016    
017    import com.liferay.portal.ExpiredLockException;
018    import com.liferay.portal.InvalidLockException;
019    import com.liferay.portal.NoSuchLockException;
020    import com.liferay.portal.NoSuchWorkflowDefinitionLinkException;
021    import com.liferay.portal.kernel.dao.orm.QueryDefinition;
022    import com.liferay.portal.kernel.exception.PortalException;
023    import com.liferay.portal.kernel.exception.SystemException;
024    import com.liferay.portal.kernel.log.Log;
025    import com.liferay.portal.kernel.log.LogFactoryUtil;
026    import com.liferay.portal.kernel.search.Indexable;
027    import com.liferay.portal.kernel.search.IndexableType;
028    import com.liferay.portal.kernel.search.Indexer;
029    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
030    import com.liferay.portal.kernel.systemevent.SystemEvent;
031    import com.liferay.portal.kernel.util.ObjectValuePair;
032    import com.liferay.portal.kernel.util.OrderByComparator;
033    import com.liferay.portal.kernel.util.ParamUtil;
034    import com.liferay.portal.kernel.util.StringPool;
035    import com.liferay.portal.kernel.util.UnicodeProperties;
036    import com.liferay.portal.kernel.util.Validator;
037    import com.liferay.portal.kernel.workflow.WorkflowConstants;
038    import com.liferay.portal.model.Group;
039    import com.liferay.portal.model.Lock;
040    import com.liferay.portal.model.ResourceConstants;
041    import com.liferay.portal.model.SystemEventConstants;
042    import com.liferay.portal.model.User;
043    import com.liferay.portal.model.WorkflowDefinitionLink;
044    import com.liferay.portal.repository.liferayrepository.model.LiferayFolder;
045    import com.liferay.portal.service.ServiceContext;
046    import com.liferay.portlet.asset.util.AssetUtil;
047    import com.liferay.portlet.documentlibrary.DuplicateFileException;
048    import com.liferay.portlet.documentlibrary.DuplicateFolderNameException;
049    import com.liferay.portlet.documentlibrary.FolderNameException;
050    import com.liferay.portlet.documentlibrary.NoSuchDirectoryException;
051    import com.liferay.portlet.documentlibrary.NoSuchFileEntryException;
052    import com.liferay.portlet.documentlibrary.model.DLFileEntryType;
053    import com.liferay.portlet.documentlibrary.model.DLFileEntryTypeConstants;
054    import com.liferay.portlet.documentlibrary.model.DLFolder;
055    import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
056    import com.liferay.portlet.documentlibrary.model.impl.DLFolderImpl;
057    import com.liferay.portlet.documentlibrary.service.base.DLFolderLocalServiceBaseImpl;
058    import com.liferay.portlet.documentlibrary.store.DLStoreUtil;
059    
060    import java.io.Serializable;
061    
062    import java.util.ArrayList;
063    import java.util.Collections;
064    import java.util.Date;
065    import java.util.List;
066    import java.util.Map;
067    
068    /**
069     * @author Brian Wing Shun Chan
070     * @author Alexander Chow
071     */
072    public class DLFolderLocalServiceImpl extends DLFolderLocalServiceBaseImpl {
073    
074            @Override
075            public DLFolder addFolder(
076                            long userId, long groupId, long repositoryId, boolean mountPoint,
077                            long parentFolderId, String name, String description,
078                            boolean hidden, ServiceContext serviceContext)
079                    throws PortalException, SystemException {
080    
081                    // Folder
082    
083                    User user = userPersistence.findByPrimaryKey(userId);
084                    parentFolderId = getParentFolderId(groupId, parentFolderId);
085                    Date now = new Date();
086    
087                    validateFolder(groupId, parentFolderId, name);
088    
089                    long folderId = counterLocalService.increment();
090    
091                    DLFolder dlFolder = dlFolderPersistence.create(folderId);
092    
093                    dlFolder.setUuid(serviceContext.getUuid());
094                    dlFolder.setGroupId(groupId);
095                    dlFolder.setCompanyId(user.getCompanyId());
096                    dlFolder.setUserId(user.getUserId());
097                    dlFolder.setUserName(user.getFullName());
098                    dlFolder.setCreateDate(serviceContext.getCreateDate(now));
099                    dlFolder.setModifiedDate(serviceContext.getModifiedDate(now));
100                    dlFolder.setRepositoryId(repositoryId);
101                    dlFolder.setMountPoint(mountPoint);
102                    dlFolder.setParentFolderId(parentFolderId);
103                    dlFolder.setTreePath(dlFolder.buildTreePath());
104                    dlFolder.setName(name);
105                    dlFolder.setDescription(description);
106                    dlFolder.setLastPostDate(now);
107                    dlFolder.setHidden(hidden);
108                    dlFolder.setOverrideFileEntryTypes(false);
109                    dlFolder.setExpandoBridgeAttributes(serviceContext);
110    
111                    dlFolderPersistence.update(dlFolder);
112    
113                    // Resources
114    
115                    if (serviceContext.isAddGroupPermissions() ||
116                            serviceContext.isAddGuestPermissions()) {
117    
118                            addFolderResources(
119                                    dlFolder, serviceContext.isAddGroupPermissions(),
120                                    serviceContext.isAddGuestPermissions());
121                    }
122                    else {
123                            if (serviceContext.isDeriveDefaultPermissions()) {
124                                    serviceContext.deriveDefaultPermissions(
125                                            repositoryId, DLFolderConstants.getClassName());
126                            }
127    
128                            addFolderResources(
129                                    dlFolder, serviceContext.getGroupPermissions(),
130                                    serviceContext.getGuestPermissions());
131                    }
132    
133                    // Parent folder
134    
135                    if (parentFolderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
136                            DLFolder parentDLFolder = dlFolderPersistence.findByPrimaryKey(
137                                    parentFolderId);
138    
139                            parentDLFolder.setLastPostDate(now);
140    
141                            dlFolderPersistence.update(parentDLFolder);
142                    }
143    
144                    // App helper
145    
146                    dlAppHelperLocalService.addFolder(
147                            userId, new LiferayFolder(dlFolder), serviceContext);
148    
149                    return dlFolder;
150            }
151    
152            /**
153             * @deprecated As of 6.2.0, replaced by more general {@link #addFolder(long,
154             *             long, long, boolean, long, String, String, boolean,
155             *             ServiceContext)}
156             */
157            @Override
158            public DLFolder addFolder(
159                            long userId, long groupId, long repositoryId, boolean mountPoint,
160                            long parentFolderId, String name, String description,
161                            ServiceContext serviceContext)
162                    throws PortalException, SystemException {
163    
164                    return addFolder(
165                            userId, groupId, repositoryId, mountPoint, parentFolderId, name,
166                            description, false, serviceContext);
167            }
168    
169            @Override
170            public void deleteAll(long groupId)
171                    throws PortalException, SystemException {
172    
173                    Group group = groupLocalService.getGroup(groupId);
174    
175                    List<DLFolder> dlFolders = dlFolderPersistence.findByGroupId(groupId);
176    
177                    for (DLFolder dlFolder : dlFolders) {
178                            dlFolderLocalService.deleteFolder(dlFolder);
179                    }
180    
181                    dlFileEntryLocalService.deleteFileEntries(
182                            groupId, DLFolderConstants.DEFAULT_PARENT_FOLDER_ID);
183    
184                    dlFileShortcutLocalService.deleteFileShortcuts(
185                            groupId, DLFolderConstants.DEFAULT_PARENT_FOLDER_ID);
186    
187                    try {
188                            DLStoreUtil.deleteDirectory(
189                                    group.getCompanyId(), groupId, StringPool.BLANK);
190                    }
191                    catch (NoSuchDirectoryException nsde) {
192                            if (_log.isDebugEnabled()) {
193                                    _log.debug(nsde.getMessage());
194                            }
195                    }
196            }
197    
198            @Indexable(type = IndexableType.DELETE)
199            @Override
200            @SystemEvent(
201                    action = SystemEventConstants.ACTION_SKIP,
202                    type = SystemEventConstants.TYPE_DELETE)
203            public DLFolder deleteFolder(DLFolder dlFolder)
204                    throws PortalException, SystemException {
205    
206                    return deleteFolder(dlFolder, true);
207            }
208    
209            @Indexable(type = IndexableType.DELETE)
210            @Override
211            @SystemEvent(
212                    action = SystemEventConstants.ACTION_SKIP,
213                    type = SystemEventConstants.TYPE_DELETE)
214            public DLFolder deleteFolder(
215                            DLFolder dlFolder, boolean includeTrashedEntries)
216                    throws PortalException, SystemException {
217    
218                    // Folders
219    
220                    List<DLFolder> dlFolders = dlFolderPersistence.findByG_P(
221                            dlFolder.getGroupId(), dlFolder.getFolderId());
222    
223                    for (DLFolder curDLFolder : dlFolders) {
224                            if (includeTrashedEntries || !curDLFolder.isInTrash()) {
225                                    dlFolderLocalService.deleteFolder(
226                                            curDLFolder, includeTrashedEntries);
227                            }
228                    }
229    
230                    // Resources
231    
232                    resourceLocalService.deleteResource(
233                            dlFolder.getCompanyId(), DLFolder.class.getName(),
234                            ResourceConstants.SCOPE_INDIVIDUAL, dlFolder.getFolderId());
235    
236                    // WebDAVProps
237    
238                    webDAVPropsLocalService.deleteWebDAVProps(
239                            DLFolder.class.getName(), dlFolder.getFolderId());
240    
241                    // File entries
242    
243                    dlFileEntryLocalService.deleteFileEntries(
244                            dlFolder.getGroupId(), dlFolder.getFolderId(),
245                            includeTrashedEntries);
246    
247                    // File entry types
248    
249                    List<Long> fileEntryTypeIds = new ArrayList<Long>();
250    
251                    for (DLFileEntryType dlFileEntryType :
252                                    dlFileEntryTypeLocalService.getDLFolderDLFileEntryTypes(
253                                            dlFolder.getFolderId())) {
254    
255                            fileEntryTypeIds.add(dlFileEntryType.getFileEntryTypeId());
256                    }
257    
258                    if (fileEntryTypeIds.isEmpty()) {
259                            fileEntryTypeIds.add(
260                                    DLFileEntryTypeConstants.FILE_ENTRY_TYPE_ID_ALL);
261                    }
262    
263                    dlFileEntryTypeLocalService.unsetFolderFileEntryTypes(
264                            dlFolder.getFolderId());
265    
266                    // File shortcuts
267    
268                    dlFileShortcutLocalService.deleteFileShortcuts(
269                            dlFolder.getGroupId(), dlFolder.getFolderId(),
270                            includeTrashedEntries);
271    
272                    // Expando
273    
274                    expandoRowLocalService.deleteRows(dlFolder.getFolderId());
275    
276                    // App helper
277    
278                    dlAppHelperLocalService.deleteFolder(new LiferayFolder(dlFolder));
279    
280                    // Folder
281    
282                    dlFolderPersistence.remove(dlFolder);
283    
284                    // Directory
285    
286                    try {
287                            if (includeTrashedEntries) {
288                                    DLStoreUtil.deleteDirectory(
289                                            dlFolder.getCompanyId(), dlFolder.getFolderId(),
290                                            StringPool.BLANK);
291                            }
292                    }
293                    catch (NoSuchDirectoryException nsde) {
294                            if (_log.isDebugEnabled()) {
295                                    _log.debug(nsde.getMessage());
296                            }
297                    }
298    
299                    // Workflow
300    
301                    for (long fileEntryTypeId : fileEntryTypeIds) {
302                            WorkflowDefinitionLink workflowDefinitionLink = null;
303    
304                            try {
305                                    workflowDefinitionLink =
306                                            workflowDefinitionLinkLocalService.
307                                                    getWorkflowDefinitionLink(
308                                                            dlFolder.getCompanyId(), dlFolder.getGroupId(),
309                                                            DLFolder.class.getName(), dlFolder.getFolderId(),
310                                                            fileEntryTypeId);
311                            }
312                            catch (NoSuchWorkflowDefinitionLinkException nswdle) {
313                                    continue;
314                            }
315    
316                            workflowDefinitionLinkLocalService.deleteWorkflowDefinitionLink(
317                                    workflowDefinitionLink);
318                    }
319    
320                    return dlFolder;
321            }
322    
323            @Indexable(type = IndexableType.DELETE)
324            @Override
325            public DLFolder deleteFolder(long folderId)
326                    throws PortalException, SystemException {
327    
328                    return dlFolderLocalService.deleteFolder(folderId, true);
329            }
330    
331            @Indexable(type = IndexableType.DELETE)
332            @Override
333            public DLFolder deleteFolder(long folderId, boolean includeTrashedEntries)
334                    throws PortalException, SystemException {
335    
336                    DLFolder dlFolder = dlFolderPersistence.findByPrimaryKey(folderId);
337    
338                    return dlFolderLocalService.deleteFolder(
339                            dlFolder, includeTrashedEntries);
340            }
341    
342            @Indexable(type = IndexableType.DELETE)
343            @Override
344            public DLFolder deleteFolder(
345                            long userId, long folderId, boolean includeTrashedEntries)
346                    throws PortalException, SystemException {
347    
348                    boolean hasLock = hasFolderLock(userId, folderId);
349    
350                    Lock lock = null;
351    
352                    if (!hasLock) {
353    
354                            // Lock
355    
356                            lock = lockFolder(
357                                    userId, folderId, null, false,
358                                    DLFolderImpl.LOCK_EXPIRATION_TIME);
359                    }
360    
361                    try {
362                            return deleteFolder(folderId, includeTrashedEntries);
363                    }
364                    finally {
365                            if (!hasLock) {
366    
367                                    // Unlock
368    
369                                    unlockFolder(folderId, lock.getUuid());
370                            }
371                    }
372            }
373    
374            @Override
375            public DLFolder fetchFolder(long folderId) throws SystemException {
376                    return dlFolderPersistence.fetchByPrimaryKey(folderId);
377            }
378    
379            @Override
380            public DLFolder fetchFolder(long groupId, long parentFolderId, String name)
381                    throws SystemException {
382    
383                    return dlFolderPersistence.fetchByG_P_N(groupId, parentFolderId, name);
384            }
385    
386            @Override
387            public List<DLFolder> getCompanyFolders(long companyId, int start, int end)
388                    throws SystemException {
389    
390                    return dlFolderPersistence.findByCompanyId(companyId, start, end);
391            }
392    
393            @Override
394            public int getCompanyFoldersCount(long companyId) throws SystemException {
395                    return dlFolderPersistence.countByCompanyId(companyId);
396            }
397    
398            /**
399             * @deprecated As of 6.2.0, replaced by {@link
400             *             #getFileEntriesAndFileShortcuts(long, long, QueryDefinition)}
401             */
402            @Override
403            public List<Object> getFileEntriesAndFileShortcuts(
404                            long groupId, long folderId, int status, int start, int end)
405                    throws SystemException {
406    
407                    QueryDefinition queryDefinition = new QueryDefinition(
408                            status, start, end, null);
409    
410                    return getFileEntriesAndFileShortcuts(
411                            groupId, folderId, queryDefinition);
412            }
413    
414            @Override
415            public List<Object> getFileEntriesAndFileShortcuts(
416                            long groupId, long folderId, QueryDefinition queryDefinition)
417                    throws SystemException {
418    
419                    return dlFolderFinder.findFE_FS_ByG_F(
420                            groupId, folderId, queryDefinition);
421            }
422    
423            /**
424             * @deprecated As of 6.2.0, replaced by {@link
425             *             #getFileEntriesAndFileShortcutsCount(long, long,
426             *             QueryDefinition)}
427             */
428            @Override
429            public int getFileEntriesAndFileShortcutsCount(
430                            long groupId, long folderId, int status)
431                    throws SystemException {
432    
433                    QueryDefinition queryDefinition = new QueryDefinition(status);
434    
435                    return getFileEntriesAndFileShortcutsCount(
436                            groupId, folderId, queryDefinition);
437            }
438    
439            @Override
440            public int getFileEntriesAndFileShortcutsCount(
441                            long groupId, long folderId, QueryDefinition queryDefinition)
442                    throws SystemException {
443    
444                    return dlFolderFinder.countFE_FS_ByG_F(
445                            groupId, folderId, queryDefinition);
446            }
447    
448            @Override
449            public DLFolder getFolder(long folderId)
450                    throws PortalException, SystemException {
451    
452                    return dlFolderPersistence.findByPrimaryKey(folderId);
453            }
454    
455            @Override
456            public DLFolder getFolder(long groupId, long parentFolderId, String name)
457                    throws PortalException, SystemException {
458    
459                    return dlFolderPersistence.findByG_P_N(groupId, parentFolderId, name);
460            }
461    
462            @Override
463            public long getFolderId(long companyId, long folderId)
464                    throws SystemException {
465    
466                    if (folderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
467    
468                            // Ensure folder exists and belongs to the proper company
469    
470                            DLFolder dlFolder = dlFolderPersistence.fetchByPrimaryKey(folderId);
471    
472                            if ((dlFolder == null) || (companyId != dlFolder.getCompanyId())) {
473                                    folderId = DLFolderConstants.DEFAULT_PARENT_FOLDER_ID;
474                            }
475                    }
476    
477                    return folderId;
478            }
479    
480            @Override
481            public List<DLFolder> getFolders(long groupId, long parentFolderId)
482                    throws SystemException {
483    
484                    return getFolders(groupId, parentFolderId, true);
485            }
486    
487            @Override
488            public List<DLFolder> getFolders(
489                            long groupId, long parentFolderId, boolean includeMountfolders)
490                    throws SystemException {
491    
492                    if (includeMountfolders) {
493                            return dlFolderPersistence.findByG_P(groupId, parentFolderId);
494                    }
495                    else {
496                            return dlFolderPersistence.findByG_M_P_H(
497                                    groupId, false, parentFolderId, false);
498                    }
499            }
500    
501            @Override
502            public List<DLFolder> getFolders(
503                            long groupId, long parentFolderId, boolean includeMountfolders,
504                            int start, int end, OrderByComparator obc)
505                    throws SystemException {
506    
507                    if (includeMountfolders) {
508                            return dlFolderPersistence.findByG_P(
509                                    groupId, parentFolderId, start, end, obc);
510                    }
511                    else {
512                            return dlFolderPersistence.findByG_M_P_H(
513                                    groupId, false, parentFolderId, false, start, end, obc);
514                    }
515            }
516    
517            @Override
518            public List<DLFolder> getFolders(
519                            long groupId, long parentFolderId, int start, int end,
520                            OrderByComparator obc)
521                    throws SystemException {
522    
523                    return getFolders(groupId, parentFolderId, true, start, end, obc);
524            }
525    
526            /**
527             * @deprecated As of 6.2.0, replaced by {@link
528             *             #getFoldersAndFileEntriesAndFileShortcuts(long, long,
529             *             String[], boolean, QueryDefinition)}
530             */
531            @Override
532            public List<Object> getFoldersAndFileEntriesAndFileShortcuts(
533                            long groupId, long folderId, int status,
534                            boolean includeMountFolders, int start, int end,
535                            OrderByComparator obc)
536                    throws SystemException {
537    
538                    QueryDefinition queryDefinition = new QueryDefinition(
539                            status, start, end, obc);
540    
541                    return getFoldersAndFileEntriesAndFileShortcuts(
542                            groupId, folderId, null, includeMountFolders, queryDefinition);
543            }
544    
545            /**
546             * @deprecated As of 6.2.0, replaced by {@link
547             *             #getFoldersAndFileEntriesAndFileShortcutsCount(long, long,
548             *             String[], boolean, QueryDefinition)}
549             */
550            @Override
551            public List<Object> getFoldersAndFileEntriesAndFileShortcuts(
552                            long groupId, long folderId, int status, String[] mimeTypes,
553                            boolean includeMountFolders, int start, int end,
554                            OrderByComparator obc)
555                    throws SystemException {
556    
557                    QueryDefinition queryDefinition = new QueryDefinition(
558                            status, start, end, obc);
559    
560                    return getFoldersAndFileEntriesAndFileShortcuts(
561                            groupId, folderId, mimeTypes, includeMountFolders, queryDefinition);
562            }
563    
564            @Override
565            public List<Object> getFoldersAndFileEntriesAndFileShortcuts(
566                            long groupId, long folderId, String[] mimeTypes,
567                            boolean includeMountFolders, QueryDefinition queryDefinition)
568                    throws SystemException {
569    
570                    return dlFolderFinder.findF_FE_FS_ByG_F_M_M(
571                            groupId, folderId, mimeTypes, includeMountFolders, queryDefinition);
572            }
573    
574            /**
575             * @deprecated As of 6.2.0, replaced by {@link
576             *             #getFoldersAndFileEntriesAndFileShortcutsCount(long, long,
577             *             String[], boolean, QueryDefinition)}
578             */
579            @Override
580            public int getFoldersAndFileEntriesAndFileShortcutsCount(
581                            long groupId, long folderId, int status,
582                            boolean includeMountFolders)
583                    throws SystemException {
584    
585                    QueryDefinition queryDefinition = new QueryDefinition(status);
586    
587                    return getFoldersAndFileEntriesAndFileShortcutsCount(
588                            groupId, folderId, null, includeMountFolders, queryDefinition);
589            }
590    
591            /**
592             * @deprecated As of 6.2.0, replaced by {@link
593             *             #getFoldersAndFileEntriesAndFileShortcutsCount(long, long,
594             *             String[], boolean, QueryDefinition)}
595             */
596            @Override
597            public int getFoldersAndFileEntriesAndFileShortcutsCount(
598                            long groupId, long folderId, int status, String[] mimeTypes,
599                            boolean includeMountFolders)
600                    throws SystemException {
601    
602                    QueryDefinition queryDefinition = new QueryDefinition(status);
603    
604                    return getFoldersAndFileEntriesAndFileShortcutsCount(
605                            groupId, folderId, mimeTypes, includeMountFolders, queryDefinition);
606            }
607    
608            @Override
609            public int getFoldersAndFileEntriesAndFileShortcutsCount(
610                            long groupId, long folderId, String[] mimeTypes,
611                            boolean includeMountFolders, QueryDefinition queryDefinition)
612                    throws SystemException {
613    
614                    return dlFolderFinder.countF_FE_FS_ByG_F_M_M(
615                            groupId, folderId, mimeTypes, includeMountFolders, queryDefinition);
616            }
617    
618            @Override
619            public int getFoldersCount(long groupId, long parentFolderId)
620                    throws SystemException {
621    
622                    return getFoldersCount(groupId, parentFolderId, true);
623            }
624    
625            @Override
626            public int getFoldersCount(
627                            long groupId, long parentFolderId, boolean includeMountfolders)
628                    throws SystemException {
629    
630                    if (includeMountfolders) {
631                            return dlFolderPersistence.countByG_P(groupId, parentFolderId);
632                    }
633                    else {
634                            return dlFolderPersistence.countByG_M_P_H(
635                                    groupId, false, parentFolderId, false);
636                    }
637            }
638    
639            @Override
640            public DLFolder getMountFolder(long repositoryId)
641                    throws PortalException, SystemException {
642    
643                    return dlFolderPersistence.findByRepositoryId(repositoryId);
644            }
645    
646            @Override
647            public List<DLFolder> getMountFolders(
648                            long groupId, long parentFolderId, int start, int end,
649                            OrderByComparator obc)
650                    throws SystemException {
651    
652                    return dlFolderPersistence.findByG_M_P_H(
653                            groupId, true, parentFolderId, false, start, end, obc);
654            }
655    
656            @Override
657            public int getMountFoldersCount(long groupId, long parentFolderId)
658                    throws SystemException {
659    
660                    return dlFolderPersistence.countByG_M_P_H(
661                            groupId, true, parentFolderId, false);
662            }
663    
664            @Override
665            public List<DLFolder> getNoAssetFolders() throws SystemException {
666                    return dlFolderFinder.findF_ByNoAssets();
667            }
668    
669            @Override
670            public void getSubfolderIds(
671                            List<Long> folderIds, long groupId, long folderId)
672                    throws SystemException {
673    
674                    List<DLFolder> dlFolders = dlFolderPersistence.findByG_P(
675                            groupId, folderId);
676    
677                    for (DLFolder dlFolder : dlFolders) {
678                            folderIds.add(dlFolder.getFolderId());
679    
680                            getSubfolderIds(
681                                    folderIds, dlFolder.getGroupId(), dlFolder.getFolderId());
682                    }
683            }
684    
685            @Override
686            public boolean hasFolderLock(long userId, long folderId)
687                    throws SystemException {
688    
689                    return lockLocalService.hasLock(
690                            userId, DLFolder.class.getName(), folderId);
691            }
692    
693            @Override
694            public Lock lockFolder(long userId, long folderId)
695                    throws PortalException, SystemException {
696    
697                    return lockFolder(
698                            userId, folderId, null, false, DLFolderImpl.LOCK_EXPIRATION_TIME);
699            }
700    
701            @Override
702            public Lock lockFolder(
703                            long userId, long folderId, String owner, boolean inheritable,
704                            long expirationTime)
705                    throws PortalException, SystemException {
706    
707                    if ((expirationTime <= 0) ||
708                            (expirationTime > DLFolderImpl.LOCK_EXPIRATION_TIME)) {
709    
710                            expirationTime = DLFolderImpl.LOCK_EXPIRATION_TIME;
711                    }
712    
713                    return lockLocalService.lock(
714                            userId, DLFolder.class.getName(), folderId, owner, inheritable,
715                            expirationTime);
716            }
717    
718            @Indexable(type = IndexableType.REINDEX)
719            @Override
720            public DLFolder moveFolder(
721                            long userId, long folderId, long parentFolderId,
722                            ServiceContext serviceContext)
723                    throws PortalException, SystemException {
724    
725                    boolean hasLock = hasFolderLock(userId, folderId);
726    
727                    Lock lock = null;
728    
729                    if (!hasLock) {
730    
731                            // Lock
732    
733                            lock = lockFolder(userId, folderId);
734                    }
735    
736                    try {
737                            DLFolder dlFolder = dlFolderPersistence.findByPrimaryKey(folderId);
738    
739                            parentFolderId = getParentFolderId(dlFolder, parentFolderId);
740    
741                            validateFolder(
742                                    dlFolder.getFolderId(), dlFolder.getGroupId(), parentFolderId,
743                                    dlFolder.getName());
744    
745                            dlFolder.setModifiedDate(serviceContext.getModifiedDate(null));
746                            dlFolder.setParentFolderId(parentFolderId);
747                            dlFolder.setTreePath(dlFolder.buildTreePath());
748                            dlFolder.setExpandoBridgeAttributes(serviceContext);
749    
750                            dlFolderPersistence.update(dlFolder);
751    
752                            dlAppHelperLocalService.moveFolder(new LiferayFolder(dlFolder));
753    
754                            return dlFolder;
755                    }
756                    finally {
757                            if (!hasLock) {
758    
759                                    // Unlock
760    
761                                    unlockFolder(folderId, lock.getUuid());
762                            }
763                    }
764            }
765    
766            @Override
767            public void rebuildTree(long companyId)
768                    throws PortalException, SystemException {
769    
770                    List<DLFolder> dlFolders = dlFolderPersistence.findByC_NotS(
771                            companyId, WorkflowConstants.STATUS_IN_TRASH);
772    
773                    for (DLFolder dlFolder : dlFolders) {
774                            if (dlFolder.isInTrashContainer()) {
775                                    continue;
776                            }
777    
778                            dlFolder.setTreePath(dlFolder.buildTreePath());
779    
780                            dlFolderPersistence.update(dlFolder);
781                    }
782            }
783    
784            @Override
785            public void unlockFolder(
786                            long groupId, long parentFolderId, String name, String lockUuid)
787                    throws PortalException, SystemException {
788    
789                    DLFolder dlFolder = getFolder(groupId, parentFolderId, name);
790    
791                    unlockFolder(dlFolder.getFolderId(), lockUuid);
792            }
793    
794            @Override
795            public void unlockFolder(long folderId, String lockUuid)
796                    throws PortalException, SystemException {
797    
798                    if (Validator.isNotNull(lockUuid)) {
799                            try {
800                                    Lock lock = lockLocalService.getLock(
801                                            DLFolder.class.getName(), folderId);
802    
803                                    if (!lockUuid.equals(lock.getUuid())) {
804                                            throw new InvalidLockException("UUIDs do not match");
805                                    }
806                            }
807                            catch (PortalException pe) {
808                                    if (pe instanceof ExpiredLockException ||
809                                            pe instanceof NoSuchLockException) {
810                                    }
811                                    else {
812                                            throw pe;
813                                    }
814                            }
815                    }
816    
817                    lockLocalService.unlock(DLFolder.class.getName(), folderId);
818            }
819    
820            @Indexable(type = IndexableType.REINDEX)
821            @Override
822            public DLFolder updateFolder(
823                            long folderId, long parentFolderId, String name, String description,
824                            long defaultFileEntryTypeId, List<Long> fileEntryTypeIds,
825                            boolean overrideFileEntryTypes, ServiceContext serviceContext)
826                    throws PortalException, SystemException {
827    
828                    boolean hasLock = hasFolderLock(serviceContext.getUserId(), folderId);
829    
830                    Lock lock = null;
831    
832                    if (!hasLock) {
833    
834                            // Lock
835    
836                            lock = lockFolder(
837                                    serviceContext.getUserId(), folderId, null, false,
838                                    DLFolderImpl.LOCK_EXPIRATION_TIME);
839                    }
840    
841                    try {
842    
843                            // File entry types
844    
845                            DLFolder dlFolder = null;
846    
847                            if (folderId > DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
848                                    dlFolder = dlFolderLocalService.updateFolderAndFileEntryTypes(
849                                            serviceContext.getUserId(), folderId, parentFolderId, name,
850                                            description, defaultFileEntryTypeId, fileEntryTypeIds,
851                                            overrideFileEntryTypes, serviceContext);
852    
853                                    dlFileEntryTypeLocalService.cascadeFileEntryTypes(
854                                            serviceContext.getUserId(), dlFolder);
855                            }
856    
857                            // Workflow definitions
858    
859                            List<ObjectValuePair<Long, String>> workflowDefinitionOVPs =
860                                    new ArrayList<ObjectValuePair<Long, String>>();
861    
862                            if (fileEntryTypeIds.isEmpty()) {
863                                    fileEntryTypeIds.add(
864                                            DLFileEntryTypeConstants.FILE_ENTRY_TYPE_ID_ALL);
865                            }
866                            else {
867                                    workflowDefinitionOVPs.add(
868                                            new ObjectValuePair<Long, String>(
869                                                    DLFileEntryTypeConstants.FILE_ENTRY_TYPE_ID_ALL,
870                                                    StringPool.BLANK));
871                            }
872    
873                            for (long fileEntryTypeId : fileEntryTypeIds) {
874                                    if (overrideFileEntryTypes) {
875                                            String workflowDefinition = ParamUtil.getString(
876                                                    serviceContext, "workflowDefinition" + fileEntryTypeId);
877    
878                                            workflowDefinitionOVPs.add(
879                                                    new ObjectValuePair<Long, String>(
880                                                            fileEntryTypeId, workflowDefinition));
881                                    }
882                                    else {
883                                            workflowDefinitionOVPs.add(
884                                                    new ObjectValuePair<Long, String>(
885                                                            fileEntryTypeId, StringPool.BLANK));
886                                    }
887                            }
888    
889                            workflowDefinitionLinkLocalService.updateWorkflowDefinitionLinks(
890                                    serviceContext.getUserId(), serviceContext.getCompanyId(),
891                                    serviceContext.getScopeGroupId(), DLFolder.class.getName(),
892                                    folderId, workflowDefinitionOVPs);
893    
894                            return dlFolder;
895                    }
896                    finally {
897                            if (!hasLock) {
898    
899                                    // Unlock
900    
901                                    unlockFolder(folderId, lock.getUuid());
902                            }
903                    }
904            }
905    
906            @Indexable(type = IndexableType.REINDEX)
907            @Override
908            public DLFolder updateFolder(
909                            long folderId, String name, String description,
910                            long defaultFileEntryTypeId, List<Long> fileEntryTypeIds,
911                            boolean overrideFileEntryTypes, ServiceContext serviceContext)
912                    throws PortalException, SystemException {
913    
914                    return updateFolder(
915                            folderId, folderId, name, description, defaultFileEntryTypeId,
916                            fileEntryTypeIds, overrideFileEntryTypes, serviceContext);
917            }
918    
919            @Override
920            public DLFolder updateFolderAndFileEntryTypes(
921                            long userId, long folderId, long parentFolderId, String name,
922                            String description, long defaultFileEntryTypeId,
923                            List<Long> fileEntryTypeIds, boolean overrideFileEntryTypes,
924                            ServiceContext serviceContext)
925                    throws PortalException, SystemException {
926    
927                    boolean hasLock = hasFolderLock(userId, folderId);
928    
929                    Lock lock = null;
930    
931                    if (!hasLock) {
932    
933                            // Lock
934    
935                            lock = lockFolder(
936                                    userId, folderId, null, false,
937                                    DLFolderImpl.LOCK_EXPIRATION_TIME);
938                    }
939    
940                    try {
941    
942                            // Folder
943    
944                            if (!overrideFileEntryTypes) {
945                                    fileEntryTypeIds = Collections.emptyList();
946                            }
947    
948                            DLFolder dlFolder = dlFolderPersistence.findByPrimaryKey(folderId);
949    
950                            parentFolderId = getParentFolderId(dlFolder, parentFolderId);
951    
952                            validateFolder(
953                                    folderId, dlFolder.getGroupId(), parentFolderId, name);
954    
955                            dlFolder.setModifiedDate(serviceContext.getModifiedDate(null));
956                            dlFolder.setParentFolderId(parentFolderId);
957                            dlFolder.setTreePath(dlFolder.buildTreePath());
958                            dlFolder.setName(name);
959                            dlFolder.setDescription(description);
960                            dlFolder.setExpandoBridgeAttributes(serviceContext);
961                            dlFolder.setOverrideFileEntryTypes(overrideFileEntryTypes);
962                            dlFolder.setDefaultFileEntryTypeId(defaultFileEntryTypeId);
963    
964                            dlFolderPersistence.update(dlFolder);
965    
966                            // File entry types
967    
968                            if (fileEntryTypeIds != null) {
969                                    dlFileEntryTypeLocalService.updateFolderFileEntryTypes(
970                                            dlFolder, fileEntryTypeIds, defaultFileEntryTypeId,
971                                            serviceContext);
972                            }
973    
974                            // App helper
975    
976                            dlAppHelperLocalService.updateFolder(
977                                    userId, new LiferayFolder(dlFolder), serviceContext);
978    
979                            return dlFolder;
980                    }
981                    finally {
982                            if (!hasLock) {
983    
984                                    // Unlock
985    
986                                    unlockFolder(folderId, lock.getUuid());
987                            }
988                    }
989            }
990    
991            /**
992             * @deprecated As of 6.2.0
993             */
994            @Override
995            public void updateLastPostDate(long folderId, Date lastPostDate)
996                    throws PortalException, SystemException {
997    
998                    DLFolder dlFolder = dlFolderPersistence.findByPrimaryKey(folderId);
999    
1000                    dlFolder.setLastPostDate(lastPostDate);
1001    
1002                    dlFolderPersistence.update(dlFolder);
1003            }
1004    
1005            @Override
1006            public DLFolder updateStatus(
1007                            long userId, long folderId, int status,
1008                            Map<String, Serializable> workflowContext,
1009                            ServiceContext serviceContext)
1010                    throws PortalException, SystemException {
1011    
1012                    // Folder
1013    
1014                    User user = userPersistence.findByPrimaryKey(userId);
1015    
1016                    DLFolder dlFolder = dlFolderPersistence.findByPrimaryKey(folderId);
1017    
1018                    int oldStatus = dlFolder.getStatus();
1019    
1020                    dlFolder.setStatus(status);
1021                    dlFolder.setStatusByUserId(user.getUserId());
1022                    dlFolder.setStatusByUserName(user.getFullName());
1023                    dlFolder.setStatusDate(new Date());
1024    
1025                    dlFolderPersistence.update(dlFolder);
1026    
1027                    // Folders, file entries, and file shortcuts
1028    
1029                    QueryDefinition queryDefinition = new QueryDefinition(
1030                            WorkflowConstants.STATUS_ANY);
1031    
1032                    List<Object> foldersAndFileEntriesAndFileShortcuts =
1033                            getFoldersAndFileEntriesAndFileShortcuts(
1034                                    dlFolder.getGroupId(), folderId, null, false, queryDefinition);
1035    
1036                    dlAppHelperLocalService.updateDependentStatus(
1037                            user, foldersAndFileEntriesAndFileShortcuts, status);
1038    
1039                    // Asset
1040    
1041                    if (status == WorkflowConstants.STATUS_APPROVED) {
1042                            assetEntryLocalService.updateVisible(
1043                                    DLFolder.class.getName(), dlFolder.getFolderId(), true);
1044                    }
1045                    else if (status == WorkflowConstants.STATUS_IN_TRASH) {
1046                            assetEntryLocalService.updateVisible(
1047                                    DLFolder.class.getName(), dlFolder.getFolderId(), false);
1048                    }
1049    
1050                    // Trash
1051    
1052                    if (status == WorkflowConstants.STATUS_IN_TRASH) {
1053                            UnicodeProperties typeSettingsProperties = new UnicodeProperties();
1054    
1055                            typeSettingsProperties.put("title", dlFolder.getName());
1056    
1057                            trashEntryLocalService.addTrashEntry(
1058                                    userId, dlFolder.getGroupId(), DLFolderConstants.getClassName(),
1059                                    dlFolder.getFolderId(), dlFolder.getUuid(), null,
1060                                    WorkflowConstants.STATUS_APPROVED, null,
1061                                    typeSettingsProperties);
1062                    }
1063                    else {
1064                            trashEntryLocalService.deleteEntry(
1065                                    DLFolderConstants.getClassName(), dlFolder.getFolderId());
1066                    }
1067    
1068                    // Indexer
1069    
1070                    if (((status == WorkflowConstants.STATUS_APPROVED) ||
1071                             (status == WorkflowConstants.STATUS_IN_TRASH) ||
1072                             (oldStatus == WorkflowConstants.STATUS_IN_TRASH)) &&
1073                            ((serviceContext == null) || serviceContext.isIndexingEnabled())) {
1074    
1075                            Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1076                                    DLFolderConstants.getClassName());
1077    
1078                            indexer.reindex(dlFolder);
1079                    }
1080    
1081                    return dlFolder;
1082            }
1083    
1084            protected void addFolderResources(
1085                            DLFolder dlFolder, boolean addGroupPermissions,
1086                            boolean addGuestPermissions)
1087                    throws PortalException, SystemException {
1088    
1089                    resourceLocalService.addResources(
1090                            dlFolder.getCompanyId(), dlFolder.getGroupId(),
1091                            dlFolder.getUserId(), DLFolder.class.getName(),
1092                            dlFolder.getFolderId(), false, addGroupPermissions,
1093                            addGuestPermissions);
1094            }
1095    
1096            protected void addFolderResources(
1097                            DLFolder dlFolder, String[] groupPermissions,
1098                            String[] guestPermissions)
1099                    throws PortalException, SystemException {
1100    
1101                    resourceLocalService.addModelResources(
1102                            dlFolder.getCompanyId(), dlFolder.getGroupId(),
1103                            dlFolder.getUserId(), DLFolder.class.getName(),
1104                            dlFolder.getFolderId(), groupPermissions, guestPermissions);
1105            }
1106    
1107            protected void addFolderResources(
1108                            long folderId, boolean addGroupPermissions,
1109                            boolean addGuestPermissions)
1110                    throws PortalException, SystemException {
1111    
1112                    DLFolder dlFolder = dlFolderPersistence.findByPrimaryKey(folderId);
1113    
1114                    addFolderResources(dlFolder, addGroupPermissions, addGuestPermissions);
1115            }
1116    
1117            protected void addFolderResources(
1118                            long folderId, String[] groupPermissions, String[] guestPermissions)
1119                    throws PortalException, SystemException {
1120    
1121                    DLFolder dlFolder = dlFolderPersistence.findByPrimaryKey(folderId);
1122    
1123                    addFolderResources(dlFolder, groupPermissions, guestPermissions);
1124            }
1125    
1126            protected long getParentFolderId(DLFolder dlFolder, long parentFolderId)
1127                    throws SystemException {
1128    
1129                    if (parentFolderId == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
1130                            return parentFolderId;
1131                    }
1132    
1133                    if (dlFolder.getFolderId() == parentFolderId) {
1134                            return dlFolder.getParentFolderId();
1135                    }
1136    
1137                    DLFolder parentDLFolder = dlFolderPersistence.fetchByPrimaryKey(
1138                            parentFolderId);
1139    
1140                    if ((parentDLFolder == null) ||
1141                            (dlFolder.getGroupId() != parentDLFolder.getGroupId())) {
1142    
1143                            return dlFolder.getParentFolderId();
1144                    }
1145    
1146                    List<Long> subfolderIds = new ArrayList<Long>();
1147    
1148                    getSubfolderIds(
1149                            subfolderIds, dlFolder.getGroupId(), dlFolder.getFolderId());
1150    
1151                    if (subfolderIds.contains(parentFolderId)) {
1152                            return dlFolder.getParentFolderId();
1153                    }
1154    
1155                    return parentFolderId;
1156            }
1157    
1158            protected long getParentFolderId(long groupId, long parentFolderId)
1159                    throws SystemException {
1160    
1161                    if (parentFolderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
1162                            DLFolder parentDLFolder = dlFolderPersistence.fetchByPrimaryKey(
1163                                    parentFolderId);
1164    
1165                            if ((parentDLFolder == null) ||
1166                                    (groupId != parentDLFolder.getGroupId())) {
1167    
1168                                    parentFolderId = DLFolderConstants.DEFAULT_PARENT_FOLDER_ID;
1169                            }
1170                    }
1171    
1172                    return parentFolderId;
1173            }
1174    
1175            protected void validateFolder(
1176                            long folderId, long groupId, long parentFolderId, String name)
1177                    throws PortalException, SystemException {
1178    
1179                    validateFolderName(name);
1180    
1181                    try {
1182                            dlFileEntryLocalService.getFileEntry(groupId, parentFolderId, name);
1183    
1184                            throw new DuplicateFileException(name);
1185                    }
1186                    catch (NoSuchFileEntryException nsfee) {
1187                    }
1188    
1189                    DLFolder dlFolder = dlFolderPersistence.fetchByG_P_N(
1190                            groupId, parentFolderId, name);
1191    
1192                    if ((dlFolder != null) && (dlFolder.getFolderId() != folderId)) {
1193                            throw new DuplicateFolderNameException(name);
1194                    }
1195            }
1196    
1197            protected void validateFolder(
1198                            long groupId, long parentFolderId, String name)
1199                    throws PortalException, SystemException {
1200    
1201                    long folderId = 0;
1202    
1203                    validateFolder(folderId, groupId, parentFolderId, name);
1204            }
1205    
1206            protected void validateFolderName(String name) throws PortalException {
1207                    if (!AssetUtil.isValidWord(name)) {
1208                            throw new FolderNameException();
1209                    }
1210            }
1211    
1212            private static Log _log = LogFactoryUtil.getLog(
1213                    DLFolderLocalServiceImpl.class);
1214    
1215    }