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