001    /**
002     * Copyright (c) 2000-present 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.InvalidRepositoryException;
018    import com.liferay.portal.NoSuchGroupException;
019    import com.liferay.portal.kernel.dao.orm.QueryUtil;
020    import com.liferay.portal.kernel.exception.PortalException;
021    import com.liferay.portal.kernel.exception.SystemException;
022    import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayInputStream;
023    import com.liferay.portal.kernel.log.Log;
024    import com.liferay.portal.kernel.log.LogFactoryUtil;
025    import com.liferay.portal.kernel.repository.InvalidRepositoryIdException;
026    import com.liferay.portal.kernel.repository.Repository;
027    import com.liferay.portal.kernel.repository.RepositoryException;
028    import com.liferay.portal.kernel.repository.capabilities.TrashCapability;
029    import com.liferay.portal.kernel.repository.model.FileEntry;
030    import com.liferay.portal.kernel.repository.model.FileVersion;
031    import com.liferay.portal.kernel.repository.model.Folder;
032    import com.liferay.portal.kernel.search.Hits;
033    import com.liferay.portal.kernel.search.Query;
034    import com.liferay.portal.kernel.search.SearchContext;
035    import com.liferay.portal.kernel.search.SearchException;
036    import com.liferay.portal.kernel.transaction.TransactionCommitCallbackRegistryUtil;
037    import com.liferay.portal.kernel.util.ArrayUtil;
038    import com.liferay.portal.kernel.util.ContentTypes;
039    import com.liferay.portal.kernel.util.FileUtil;
040    import com.liferay.portal.kernel.util.GetterUtil;
041    import com.liferay.portal.kernel.util.MimeTypesUtil;
042    import com.liferay.portal.kernel.util.OrderByComparator;
043    import com.liferay.portal.kernel.util.StringBundler;
044    import com.liferay.portal.kernel.util.StringPool;
045    import com.liferay.portal.kernel.util.TempFileEntryUtil;
046    import com.liferay.portal.kernel.util.Validator;
047    import com.liferay.portal.kernel.workflow.WorkflowConstants;
048    import com.liferay.portal.model.Lock;
049    import com.liferay.portal.security.permission.ActionKeys;
050    import com.liferay.portal.service.ServiceContext;
051    import com.liferay.portlet.documentlibrary.NoSuchFileEntryException;
052    import com.liferay.portlet.documentlibrary.NoSuchFileVersionException;
053    import com.liferay.portlet.documentlibrary.NoSuchFolderException;
054    import com.liferay.portlet.documentlibrary.model.DLFileShortcut;
055    import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
056    import com.liferay.portlet.documentlibrary.service.base.DLAppServiceBaseImpl;
057    import com.liferay.portlet.documentlibrary.service.permission.DLFileEntryPermission;
058    import com.liferay.portlet.documentlibrary.service.permission.DLFileShortcutPermission;
059    import com.liferay.portlet.documentlibrary.service.permission.DLFolderPermission;
060    import com.liferay.portlet.documentlibrary.service.permission.DLPermission;
061    import com.liferay.portlet.documentlibrary.util.DLAppUtil;
062    import com.liferay.portlet.documentlibrary.util.DLProcessorRegistryUtil;
063    import com.liferay.portlet.documentlibrary.util.comparator.RepositoryModelModifiedDateComparator;
064    
065    import java.io.File;
066    import java.io.IOException;
067    import java.io.InputStream;
068    
069    import java.util.ArrayList;
070    import java.util.LinkedList;
071    import java.util.List;
072    import java.util.Queue;
073    import java.util.concurrent.Callable;
074    
075    /**
076     * Provides the remote service for accessing, adding, checking in/out, deleting,
077     * locking/unlocking, moving, subscription handling of, trash handling of,
078     * updating, and verifying document library file entries and folders. Its
079     * methods include permission checks. All portlets should interact with the
080     * document library through this class or through DLAppLocalService, rather than
081     * through the individual document library service classes.
082     *
083     * <p>
084     * This class provides a unified interface to all Liferay and third party
085     * repositories. While the method signatures are universal for all repositories.
086     * Additional implementation-specific parameters may be specified in the
087     * serviceContext.
088     * </p>
089     *
090     * <p>
091     * The <code>repositoryId</code> parameter used by most of the methods is the
092     * primary key of the specific repository. If the repository is a default
093     * Liferay repository, the <code>repositoryId</code> is the <code>groupId</code>
094     * or <code>scopeGroupId</code>. Otherwise, the <code>repositoryId</code> will
095     * correspond to values obtained from {@link
096     * com.liferay.portal.service.RepositoryServiceUtil}.
097     * </p>
098     *
099     * @author Alexander Chow
100     * @author Mika Koivisto
101     * @author Shuyang Zhou
102     * @see    DLAppLocalServiceImpl
103     */
104    public class DLAppServiceImpl extends DLAppServiceBaseImpl {
105    
106            /**
107             * Adds a file entry and associated metadata. It is created based on a byte
108             * array.
109             *
110             * <p>
111             * This method takes two file names, the <code>sourceFileName</code> and the
112             * <code>title</code>. The <code>sourceFileName</code> corresponds to the
113             * name of the actual file being uploaded. The <code>title</code>
114             * corresponds to a name the client wishes to assign this file after it has
115             * been uploaded to the portal. If it is <code>null</code>, the <code>
116             * sourceFileName</code> will be used.
117             * </p>
118             *
119             * @param  repositoryId the primary key of the repository
120             * @param  folderId the primary key of the file entry's parent folder
121             * @param  sourceFileName the original file's name
122             * @param  mimeType the file's MIME type
123             * @param  title the name to be assigned to the file (optionally <code>null
124             *         </code>)
125             * @param  description the file's description
126             * @param  changeLog the file's version change log
127             * @param  bytes the file's data (optionally <code>null</code>)
128             * @param  serviceContext the service context to be applied. Can set the
129             *         asset category IDs, asset tag names, and expando bridge
130             *         attributes for the file entry. In a Liferay repository, it may
131             *         include:  <ul> <li> fileEntryTypeId - ID for a custom file entry
132             *         type </li> <li> fieldsMap - mapping for fields associated with a
133             *         custom file entry type </li> </ul>
134             * @return the file entry
135             * @throws PortalException if the parent folder could not be found or if the
136             *         file entry's information was invalid
137             */
138            @Override
139            public FileEntry addFileEntry(
140                            long repositoryId, long folderId, String sourceFileName,
141                            String mimeType, String title, String description, String changeLog,
142                            byte[] bytes, ServiceContext serviceContext)
143                    throws PortalException {
144    
145                    File file = null;
146    
147                    try {
148                            if (ArrayUtil.isNotEmpty(bytes)) {
149                                    file = FileUtil.createTempFile(bytes);
150                            }
151    
152                            return addFileEntry(
153                                    repositoryId, folderId, sourceFileName, mimeType, title,
154                                    description, changeLog, file, serviceContext);
155                    }
156                    catch (IOException ioe) {
157                            throw new SystemException("Unable to write temporary file", ioe);
158                    }
159                    finally {
160                            FileUtil.delete(file);
161                    }
162            }
163    
164            /**
165             * Adds a file entry and associated metadata. It is created based on a
166             * {@link java.io.File} object.
167             *
168             * <p>
169             * This method takes two file names, the <code>sourceFileName</code> and the
170             * <code>title</code>. The <code>sourceFileName</code> corresponds to the
171             * name of the actual file being uploaded. The <code>title</code>
172             * corresponds to a name the client wishes to assign this file after it has
173             * been uploaded to the portal. If it is <code>null</code>, the <code>
174             * sourceFileName</code> will be used.
175             * </p>
176             *
177             * @param  repositoryId the primary key of the repository
178             * @param  folderId the primary key of the file entry's parent folder
179             * @param  sourceFileName the original file's name
180             * @param  mimeType the file's MIME type
181             * @param  title the name to be assigned to the file (optionally <code>null
182             *         </code>)
183             * @param  description the file's description
184             * @param  changeLog the file's version change log
185             * @param  file the file's data (optionally <code>null</code>)
186             * @param  serviceContext the service context to be applied. Can set the
187             *         asset category IDs, asset tag names, and expando bridge
188             *         attributes for the file entry. In a Liferay repository, it may
189             *         include:  <ul> <li> fileEntryTypeId - ID for a custom file entry
190             *         type </li> <li> fieldsMap - mapping for fields associated with a
191             *         custom file entry type </li> </ul>
192             * @return the file entry
193             * @throws PortalException if the parent folder could not be found or if the
194             *         file entry's information was invalid
195             */
196            @Override
197            public FileEntry addFileEntry(
198                            long repositoryId, long folderId, String sourceFileName,
199                            String mimeType, String title, String description, String changeLog,
200                            File file, ServiceContext serviceContext)
201                    throws PortalException {
202    
203                    if ((file == null) || !file.exists() || (file.length() == 0)) {
204                            return addFileEntry(
205                                    repositoryId, folderId, sourceFileName, mimeType, title,
206                                    description, changeLog, null, 0, serviceContext);
207                    }
208    
209                    mimeType = DLAppUtil.getMimeType(sourceFileName, mimeType, title, file);
210    
211                    Repository repository = getRepository(repositoryId);
212    
213                    FileEntry fileEntry = repository.addFileEntry(
214                            getUserId(), folderId, sourceFileName, mimeType, title, description,
215                            changeLog, file, serviceContext);
216    
217                    dlAppHelperLocalService.addFileEntry(
218                            getUserId(), fileEntry, fileEntry.getFileVersion(), serviceContext);
219    
220                    return fileEntry;
221            }
222    
223            /**
224             * Adds a file entry and associated metadata. It is created based on a
225             * {@link InputStream} object.
226             *
227             * <p>
228             * This method takes two file names, the <code>sourceFileName</code> and the
229             * <code>title</code>. The <code>sourceFileName</code> corresponds to the
230             * name of the actual file being uploaded. The <code>title</code>
231             * corresponds to a name the client wishes to assign this file after it has
232             * been uploaded to the portal. If it is <code>null</code>, the <code>
233             * sourceFileName</code> will be used.
234             * </p>
235             *
236             * @param  repositoryId the primary key of the repository
237             * @param  folderId the primary key of the file entry's parent folder
238             * @param  sourceFileName the original file's name
239             * @param  mimeType the file's MIME type
240             * @param  title the name to be assigned to the file (optionally <code>null
241             *         </code>)
242             * @param  description the file's description
243             * @param  changeLog the file's version change log
244             * @param  is the file's data (optionally <code>null</code>)
245             * @param  size the file's size (optionally <code>0</code>)
246             * @param  serviceContext the service context to be applied. Can set the
247             *         asset category IDs, asset tag names, and expando bridge
248             *         attributes for the file entry. In a Liferay repository, it may
249             *         include:  <ul> <li> fileEntryTypeId - ID for a custom file entry
250             *         type </li> <li> fieldsMap - mapping for fields associated with a
251             *         custom file entry type </li> </ul>
252             * @return the file entry
253             * @throws PortalException if the parent folder could not be found or if the
254             *         file entry's information was invalid
255             */
256            @Override
257            public FileEntry addFileEntry(
258                            long repositoryId, long folderId, String sourceFileName,
259                            String mimeType, String title, String description, String changeLog,
260                            InputStream is, long size, ServiceContext serviceContext)
261                    throws PortalException {
262    
263                    if (is == null) {
264                            is = new UnsyncByteArrayInputStream(new byte[0]);
265                            size = 0;
266                    }
267    
268                    if (Validator.isNull(mimeType) ||
269                            mimeType.equals(ContentTypes.APPLICATION_OCTET_STREAM)) {
270    
271                            String extension = DLAppUtil.getExtension(title, sourceFileName);
272    
273                            if (size == 0) {
274                                    mimeType = MimeTypesUtil.getExtensionContentType(extension);
275                            }
276                            else {
277                                    File file = null;
278    
279                                    try {
280                                            file = FileUtil.createTempFile(is);
281    
282                                            return addFileEntry(
283                                                    repositoryId, folderId, sourceFileName, mimeType, title,
284                                                    description, changeLog, file, serviceContext);
285                                    }
286                                    catch (IOException ioe) {
287                                            throw new SystemException(
288                                                    "Unable to write temporary file", ioe);
289                                    }
290                                    finally {
291                                            FileUtil.delete(file);
292                                    }
293                            }
294                    }
295    
296                    Repository repository = getRepository(repositoryId);
297    
298                    FileEntry fileEntry = repository.addFileEntry(
299                            getUserId(), folderId, sourceFileName, mimeType, title, description,
300                            changeLog, is, size, serviceContext);
301    
302                    dlAppHelperLocalService.addFileEntry(
303                            getUserId(), fileEntry, fileEntry.getFileVersion(), serviceContext);
304    
305                    return fileEntry;
306            }
307    
308            /**
309             * Adds a file shortcut to the existing file entry. This method is only
310             * supported by the Liferay repository.
311             *
312             * @param  repositoryId the primary key of the repository
313             * @param  folderId the primary key of the file shortcut's parent folder
314             * @param  toFileEntryId the primary key of the file shortcut's file entry
315             * @param  serviceContext the service context to be applied. Can set the
316             *         asset category IDs, asset tag names, and expando bridge
317             *         attributes for the file entry.
318             * @return the file shortcut
319             * @throws PortalException if the parent folder or file entry could not be
320             *         found, or if the file shortcut's information was invalid
321             */
322            @Override
323            public DLFileShortcut addFileShortcut(
324                            long repositoryId, long folderId, long toFileEntryId,
325                            ServiceContext serviceContext)
326                    throws PortalException {
327    
328                    return dlFileShortcutService.addFileShortcut(
329                            repositoryId, folderId, toFileEntryId, serviceContext);
330            }
331    
332            /**
333             * Adds a folder.
334             *
335             * @param  repositoryId the primary key of the repository
336             * @param  parentFolderId the primary key of the folder's parent folder
337             * @param  name the folder's name
338             * @param  description the folder's description
339             * @param  serviceContext the service context to be applied. In a Liferay
340             *         repository, it may include boolean mountPoint specifying whether
341             *         folder is a facade for mounting a third-party repository
342             * @return the folder
343             * @throws PortalException if the parent folder could not be found or if the
344             *         new folder's information was invalid
345             */
346            @Override
347            public Folder addFolder(
348                            long repositoryId, long parentFolderId, String name,
349                            String description, ServiceContext serviceContext)
350                    throws PortalException {
351    
352                    Repository repository = getRepository(repositoryId);
353    
354                    Folder folder = repository.addFolder(
355                            getUserId(), parentFolderId, name, description, serviceContext);
356    
357                    dlAppHelperLocalService.addFolder(getUserId(), folder, serviceContext);
358    
359                    return folder;
360            }
361    
362            /**
363             * Adds a temporary file entry.
364             *
365             * <p>
366             * This allows a client to upload a file into a temporary location and
367             * manipulate its metadata prior to making it available for public usage.
368             * This is different from checking in and checking out a file entry.
369             * </p>
370             *
371             * @param  groupId the primary key of the group
372             * @param  folderId the primary key of the folder where the file entry will
373             *         eventually reside
374             * @param  folderName the temporary folder's name
375             * @param  fileName the file's original name
376             * @param  file the file's data (optionally <code>null</code>)
377             * @param  mimeType the file's MIME type
378             * @return the temporary file entry
379             * @throws PortalException if the file name was invalid
380             * @see    com.liferay.portal.kernel.util.TempFileEntryUtil
381             */
382            @Override
383            public FileEntry addTempFileEntry(
384                            long groupId, long folderId, String folderName, String fileName,
385                            File file, String mimeType)
386                    throws PortalException {
387    
388                    DLFolderPermission.check(
389                            getPermissionChecker(), groupId, folderId, ActionKeys.ADD_DOCUMENT);
390    
391                    return TempFileEntryUtil.addTempFileEntry(
392                            groupId, getUserId(), folderName, fileName, file, mimeType);
393            }
394    
395            /**
396             * Adds a temporary file entry. It is created based on the {@link
397             * InputStream} object.
398             *
399             * <p>
400             * This allows a client to upload a file into a temporary location and
401             * manipulate its metadata prior to making it available for public usage.
402             * This is different from checking in and checking out a file entry.
403             * </p>
404             *
405             * @param  groupId the primary key of the group
406             * @param  folderId the primary key of the folder where the file entry will
407             *         eventually reside
408             * @param  folderName the temporary folder's name
409             * @param  fileName the file's original name
410             * @param  inputStream the file's data
411             * @param  mimeType the file's MIME type
412             * @return the temporary file entry
413             * @throws PortalException if the file name was invalid or if a portal
414             *         exception occurred
415             * @see    com.liferay.portal.kernel.util.TempFileEntryUtil
416             */
417            @Override
418            public FileEntry addTempFileEntry(
419                            long groupId, long folderId, String folderName, String fileName,
420                            InputStream inputStream, String mimeType)
421                    throws PortalException {
422    
423                    DLFolderPermission.check(
424                            getPermissionChecker(), groupId, folderId, ActionKeys.ADD_DOCUMENT);
425    
426                    return TempFileEntryUtil.addTempFileEntry(
427                            groupId, getUserId(), folderName, fileName, inputStream, mimeType);
428            }
429    
430            /**
431             * Cancels the check out of the file entry. If a user has not checked out
432             * the specified file entry, invoking this method will result in no changes.
433             *
434             * <p>
435             * When a file entry is checked out, a PWC (private working copy) is created
436             * and the original file entry is locked. A client can make as many changes
437             * to the PWC as he desires without those changes being visible to other
438             * users. If the user is satisfied with the changes, he may elect to check
439             * in his changes, resulting in a new file version based on the PWC; the PWC
440             * will be removed and the file entry will be unlocked. If the user is not
441             * satisfied with the changes, he may elect to cancel his check out; this
442             * results in the deletion of the PWC and unlocking of the file entry.
443             * </p>
444             *
445             * @param  fileEntryId the primary key of the file entry to cancel the
446             *         checkout
447             * @throws PortalException if the file entry could not be found
448             * @see    #checkInFileEntry(long, boolean, String, ServiceContext)
449             * @see    #checkOutFileEntry(long, ServiceContext)
450             */
451            @Override
452            public void cancelCheckOut(long fileEntryId) throws PortalException {
453                    Repository repository = getFileEntryRepository(fileEntryId);
454    
455                    FileEntry fileEntry = repository.getFileEntry(fileEntryId);
456    
457                    DLProcessorRegistryUtil.cleanUp(fileEntry.getLatestFileVersion());
458    
459                    FileVersion draftFileVersion = repository.cancelCheckOut(fileEntryId);
460    
461                    ServiceContext serviceContext = new ServiceContext();
462    
463                    serviceContext.setWorkflowAction(WorkflowConstants.ACTION_PUBLISH);
464    
465                    dlAppHelperLocalService.cancelCheckOut(
466                            getUserId(), fileEntry, null, fileEntry.getFileVersion(),
467                            draftFileVersion, serviceContext);
468            }
469    
470            /**
471             * Checks in the file entry. If a user has not checked out the specified
472             * file entry, invoking this method will result in no changes.
473             *
474             * <p>
475             * When a file entry is checked out, a PWC (private working copy) is created
476             * and the original file entry is locked. A client can make as many changes
477             * to the PWC as he desires without those changes being visible to other
478             * users. If the user is satisfied with the changes, he may elect to check
479             * in his changes, resulting in a new file version based on the PWC; the PWC
480             * will be removed and the file entry will be unlocked. If the user is not
481             * satisfied with the changes, he may elect to cancel his check out; this
482             * results in the deletion of the PWC and unlocking of the file entry.
483             * </p>
484             *
485             * @param  fileEntryId the primary key of the file entry to check in
486             * @param  majorVersion whether the new file version is a major version
487             * @param  changeLog the file's version change log
488             * @param  serviceContext the service context to be applied
489             * @throws PortalException if the file entry could not be found
490             * @see    #cancelCheckOut(long)
491             * @see    #checkOutFileEntry(long, ServiceContext)
492             */
493            @Override
494            public void checkInFileEntry(
495                            long fileEntryId, boolean majorVersion, String changeLog,
496                            ServiceContext serviceContext)
497                    throws PortalException {
498    
499                    Repository repository = getFileEntryRepository(fileEntryId);
500    
501                    FileEntry oldFileEntry = repository.getFileEntry(fileEntryId);
502    
503                    FileVersion oldFileVersion = oldFileEntry.getFileVersion();
504    
505                    repository.checkInFileEntry(
506                            getUserId(), fileEntryId, majorVersion, changeLog, serviceContext);
507    
508                    FileEntry fileEntry = getFileEntry(fileEntryId);
509    
510                    FileVersion fileVersion = fileEntry.getLatestFileVersion();
511    
512                    dlAppHelperLocalService.updateFileEntry(
513                            getUserId(), fileEntry, oldFileVersion, fileVersion,
514                            fileVersion.getFileVersionId());
515            }
516    
517            /**
518             * @deprecated As of 6.2.0, replaced by {@link #checkInFileEntry(long,
519             *             String, ServiceContext)}
520             */
521            @Deprecated
522            @Override
523            public void checkInFileEntry(long fileEntryId, String lockUuid)
524                    throws PortalException {
525    
526                    checkInFileEntry(fileEntryId, lockUuid, new ServiceContext());
527            }
528    
529            /**
530             * Checks in the file entry using the lock's UUID. If a user has not checked
531             * out the specified file entry, invoking this method will result in no
532             * changes. This method is primarily used by WebDAV.
533             *
534             * <p>
535             * When a file entry is checked out, a PWC (private working copy) is created
536             * and the original file entry is locked. A client can make as many changes
537             * to the PWC as he desires without those changes being visible to other
538             * users. If the user is satisfied with the changes, he may elect to check
539             * in his changes, resulting in a new file version based on the PWC; the PWC
540             * will be removed and the file entry will be unlocked. If the user is not
541             * satisfied with the changes, he may elect to cancel his check out; this
542             * results in the deletion of the PWC and unlocking of the file entry.
543             * </p>
544             *
545             * @param  fileEntryId the primary key of the file entry to check in
546             * @param  lockUuid the lock's UUID
547             * @param  serviceContext the service context to be applied
548             * @throws PortalException if the file entry could not be found
549             * @see    #cancelCheckOut(long)
550             * @see    #checkOutFileEntry(long, String, long, ServiceContext)
551             */
552            @Override
553            public void checkInFileEntry(
554                            long fileEntryId, String lockUuid, ServiceContext serviceContext)
555                    throws PortalException {
556    
557                    Repository repository = getFileEntryRepository(fileEntryId);
558    
559                    FileEntry oldFileEntry = repository.getFileEntry(fileEntryId);
560    
561                    FileVersion oldFileVersion = oldFileEntry.getFileVersion();
562    
563                    repository.checkInFileEntry(
564                            getUserId(), fileEntryId, lockUuid, serviceContext);
565    
566                    FileEntry fileEntry = getFileEntry(fileEntryId);
567    
568                    FileVersion fileVersion = fileEntry.getLatestFileVersion();
569    
570                    dlAppHelperLocalService.updateFileEntry(
571                            getUserId(), fileEntry, oldFileVersion, fileVersion,
572                            fileVersion.getFileVersionId());
573            }
574    
575            /**
576             * Check out a file entry.
577             *
578             * <p>
579             * When a file entry is checked out, a PWC (private working copy) is created
580             * and the original file entry is locked. A client can make as many changes
581             * to the PWC as he desires without those changes being visible to other
582             * users. If the user is satisfied with the changes, he may elect to check
583             * in his changes, resulting in a new file version based on the PWC; the PWC
584             * will be removed and the file entry will be unlocked. If the user is not
585             * satisfied with the changes, he may elect to cancel his check out; this
586             * results in the deletion of the PWC and unlocking of the file entry.
587             * </p>
588             *
589             * @param  fileEntryId the file entry to check out
590             * @param  serviceContext the service context to be applied
591             * @throws PortalException if the file entry could not be found
592             * @see    #cancelCheckOut(long)
593             * @see    #checkInFileEntry(long, boolean, String, ServiceContext)
594             */
595            @Override
596            public void checkOutFileEntry(
597                            long fileEntryId, ServiceContext serviceContext)
598                    throws PortalException {
599    
600                    Repository repository = getFileEntryRepository(fileEntryId);
601    
602                    FileEntry oldFileEntry = repository.getFileEntry(fileEntryId);
603    
604                    FileVersion oldFileVersion = oldFileEntry.getFileVersion();
605    
606                    FileEntry fileEntry = repository.checkOutFileEntry(
607                            fileEntryId, serviceContext);
608    
609                    FileVersion fileVersion = fileEntry.getLatestFileVersion();
610    
611                    dlAppHelperLocalService.updateFileEntry(
612                            getUserId(), fileEntry, oldFileVersion, fileVersion, fileEntryId);
613            }
614    
615            /**
616             * Checks out the file entry. This method is primarily used by WebDAV.
617             *
618             * <p>
619             * When a file entry is checked out, a PWC (private working copy) is created
620             * and the original file entry is locked. A client can make as many changes
621             * to the PWC as he desires without those changes being visible to other
622             * users. If the user is satisfied with the changes, he may elect to check
623             * in his changes, resulting in a new file version based on the PWC; the PWC
624             * will be removed and the file entry will be unlocked. If the user is not
625             * satisfied with the changes, he may elect to cancel his check out; this
626             * results in the deletion of the PWC and unlocking of the file entry.
627             * </p>
628             *
629             * @param  fileEntryId the file entry to check out
630             * @param  owner the owner string for the checkout (optionally
631             *         <code>null</code>)
632             * @param  expirationTime the time in milliseconds before the lock expires.
633             *         If the value is <code>0</code>, the default expiration time will
634             *         be used from <code>portal.properties>.
635             * @param  serviceContext the service context to be applied
636             * @return the file entry
637             * @throws PortalException if the file entry could not be found
638             * @see    #cancelCheckOut(long)
639             * @see    #checkInFileEntry(long, String)
640             */
641            @Override
642            public FileEntry checkOutFileEntry(
643                            long fileEntryId, String owner, long expirationTime,
644                            ServiceContext serviceContext)
645                    throws PortalException {
646    
647                    Repository repository = getFileEntryRepository(fileEntryId);
648    
649                    FileEntry oldFileEntry = repository.getFileEntry(fileEntryId);
650    
651                    FileVersion oldFileVersion = oldFileEntry.getFileVersion();
652    
653                    FileEntry fileEntry = repository.checkOutFileEntry(
654                            fileEntryId, owner, expirationTime, serviceContext);
655    
656                    FileVersion fileVersion = fileEntry.getLatestFileVersion();
657    
658                    dlAppHelperLocalService.updateFileEntry(
659                            getUserId(), fileEntry, oldFileVersion, fileVersion, fileEntryId);
660    
661                    return fileEntry;
662            }
663    
664            /**
665             * Performs a deep copy of the folder.
666             *
667             * @param  repositoryId the primary key of the repository
668             * @param  sourceFolderId the primary key of the folder to copy
669             * @param  parentFolderId the primary key of the new folder's parent folder
670             * @param  name the new folder's name
671             * @param  description the new folder's description
672             * @param  serviceContext the service context to be applied
673             * @return the folder
674             * @throws PortalException if the source folder or the new parent folder
675             *         could not be found or if the new folder's information was invalid
676             */
677            @Override
678            public Folder copyFolder(
679                            long repositoryId, long sourceFolderId, long parentFolderId,
680                            String name, String description, ServiceContext serviceContext)
681                    throws PortalException {
682    
683                    Repository repository = getRepository(repositoryId);
684    
685                    Folder srcFolder = repository.getFolder(sourceFolderId);
686    
687                    Folder destFolder = repository.addFolder(
688                            getUserId(), parentFolderId, name, description, serviceContext);
689    
690                    dlAppHelperLocalService.addFolder(
691                            getUserId(), destFolder, serviceContext);
692    
693                    copyFolder(repository, srcFolder, destFolder, serviceContext);
694    
695                    return destFolder;
696            }
697    
698            /**
699             * Deletes the file entry with the primary key.
700             *
701             * @param  fileEntryId the primary key of the file entry
702             * @throws PortalException if the file entry could not be found
703             */
704            @Override
705            public void deleteFileEntry(long fileEntryId) throws PortalException {
706                    Repository repository = getFileEntryRepository(fileEntryId);
707    
708                    FileEntry fileEntry = repository.getFileEntry(fileEntryId);
709    
710                    dlAppHelperLocalService.deleteFileEntry(fileEntry);
711    
712                    repository.deleteFileEntry(fileEntryId);
713            }
714    
715            /**
716             * Deletes the file entry with the title in the folder.
717             *
718             * @param  repositoryId the primary key of the repository
719             * @param  folderId the primary key of the file entry's parent folder
720             * @param  title the file entry's title
721             * @throws PortalException if the file entry could not be found
722             */
723            @Override
724            public void deleteFileEntryByTitle(
725                            long repositoryId, long folderId, String title)
726                    throws PortalException {
727    
728                    Repository repository = getRepository(repositoryId);
729    
730                    FileEntry fileEntry = repository.getFileEntry(folderId, title);
731    
732                    dlAppHelperLocalService.deleteFileEntry(fileEntry);
733    
734                    repository.deleteFileEntry(folderId, title);
735            }
736    
737            /**
738             * Deletes the file shortcut with the primary key. This method is only
739             * supported by the Liferay repository.
740             *
741             * @param  fileShortcutId the primary key of the file shortcut
742             * @throws PortalException if the file shortcut could not be found
743             */
744            @Override
745            public void deleteFileShortcut(long fileShortcutId) throws PortalException {
746                    dlFileShortcutService.deleteFileShortcut(fileShortcutId);
747            }
748    
749            /**
750             * Deletes the file version. File versions can only be deleted if it is
751             * approved and there are other approved file versions available. This
752             * method is only supported by the Liferay repository.
753             *
754             * @param  fileEntryId the primary key of the file entry
755             * @param  version the version label of the file version
756             * @throws PortalException if the file version could not be found or invalid
757             */
758            @Override
759            public void deleteFileVersion(long fileEntryId, String version)
760                    throws PortalException {
761    
762                    Repository repository = getFileEntryRepository(fileEntryId);
763    
764                    repository.deleteFileVersion(fileEntryId, version);
765            }
766    
767            /**
768             * Deletes the folder with the primary key and all of its subfolders and
769             * file entries.
770             *
771             * @param  folderId the primary key of the folder
772             * @throws PortalException if the folder could not be found
773             */
774            @Override
775            public void deleteFolder(long folderId) throws PortalException {
776                    Repository repository = getFolderRepository(folderId);
777    
778                    Folder folder = repository.getFolder(folderId);
779    
780                    if (repository.isCapabilityProvided(TrashCapability.class)) {
781                            TrashCapability trashCapability = repository.getCapability(
782                                    TrashCapability.class);
783    
784                            if (trashCapability.isInTrash(folder)) {
785                                    trashCapability.deleteFolder(folder);
786    
787                                    return;
788                            }
789                    }
790    
791                    List<FileEntry> fileEntries = repository.getRepositoryFileEntries(
792                            0, folderId, QueryUtil.ALL_POS, QueryUtil.ALL_POS, null);
793    
794                    for (FileEntry fileEntry : fileEntries) {
795                            dlAppHelperLocalService.deleteFileEntry(fileEntry);
796                    }
797    
798                    repository.deleteFolder(folderId);
799    
800                    dlAppHelperLocalService.deleteFolder(folder);
801            }
802    
803            /**
804             * Deletes the folder with the name in the parent folder and all of its
805             * subfolders and file entries.
806             *
807             * @param  repositoryId the primary key of the repository
808             * @param  parentFolderId the primary key of the folder's parent folder
809             * @param  name the folder's name
810             * @throws PortalException if the folder could not be found
811             */
812            @Override
813            public void deleteFolder(
814                            long repositoryId, long parentFolderId, String name)
815                    throws PortalException {
816    
817                    Repository repository = getRepository(repositoryId);
818    
819                    Folder folder = repository.getFolder(parentFolderId, name);
820    
821                    if (repository.isCapabilityProvided(TrashCapability.class)) {
822                            TrashCapability trashCapability = repository.getCapability(
823                                    TrashCapability.class);
824    
825                            if (trashCapability.isInTrash(folder)) {
826                                    trashCapability.deleteFolder(folder);
827    
828                                    return;
829                            }
830                    }
831    
832                    repository.deleteFolder(parentFolderId, name);
833            }
834    
835            /**
836             * Deletes the temporary file entry.
837             *
838             * @param  groupId the primary key of the group
839             * @param  folderId the primary key of the folder where the file entry was
840             *         eventually to reside
841             * @param  folderName the temporary folder's name
842             * @param  fileName the file's original name
843             * @throws PortalException if the file name was invalid
844             * @see    com.liferay.portal.kernel.util.TempFileEntryUtil
845             */
846            @Override
847            public void deleteTempFileEntry(
848                            long groupId, long folderId, String folderName, String fileName)
849                    throws PortalException {
850    
851                    DLFolderPermission.check(
852                            getPermissionChecker(), groupId, folderId, ActionKeys.ADD_DOCUMENT);
853    
854                    TempFileEntryUtil.deleteTempFileEntry(
855                            groupId, getUserId(), folderName, fileName);
856            }
857    
858            /**
859             * Returns all the file entries in the folder.
860             *
861             * @param  repositoryId the primary key of the file entry's repository
862             * @param  folderId the primary key of the file entry's folder
863             * @return the file entries in the folder
864             * @throws PortalException if the folder could not be found
865             */
866            @Override
867            public List<FileEntry> getFileEntries(long repositoryId, long folderId)
868                    throws PortalException {
869    
870                    return getFileEntries(
871                            repositoryId, folderId, QueryUtil.ALL_POS, QueryUtil.ALL_POS);
872            }
873    
874            /**
875             * Returns a range of all the file entries in the folder.
876             *
877             * <p>
878             * Useful when paginating results. Returns a maximum of <code>end -
879             * start</code> instances. <code>start</code> and <code>end</code> are not
880             * primary keys, they are indexes in the result set. Thus, <code>0</code>
881             * refers to the first result in the set. Setting both <code>start</code>
882             * and <code>end</code> to {@link
883             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
884             * result set.
885             * </p>
886             *
887             * @param  repositoryId the primary key of the file entry's repository
888             * @param  folderId the primary key of the file entry's folder
889             * @param  start the lower bound of the range of results
890             * @param  end the upper bound of the range of results (not inclusive)
891             * @return the range of file entries in the folder
892             * @throws PortalException if the folder could not be found
893             */
894            @Override
895            public List<FileEntry> getFileEntries(
896                            long repositoryId, long folderId, int start, int end)
897                    throws PortalException {
898    
899                    return getFileEntries(repositoryId, folderId, start, end, null);
900            }
901    
902            /**
903             * Returns an ordered range of all the file entries in the folder.
904             *
905             * <p>
906             * Useful when paginating results. Returns a maximum of <code>end -
907             * start</code> instances. <code>start</code> and <code>end</code> are not
908             * primary keys, they are indexes in the result set. Thus, <code>0</code>
909             * refers to the first result in the set. Setting both <code>start</code>
910             * and <code>end</code> to {@link
911             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
912             * result set.
913             * </p>
914             *
915             * @param  repositoryId the primary key of the file entry's repository
916             * @param  folderId the primary key of the file entry's folder
917             * @param  start the lower bound of the range of results
918             * @param  end the upper bound of the range of results (not inclusive)
919             * @param  obc the comparator to order the file entries (optionally
920             *         <code>null</code>)
921             * @return the range of file entries in the folder ordered by comparator
922             *         <code>obc</code>
923             * @throws PortalException if the folder could not be found
924             */
925            @Override
926            public List<FileEntry> getFileEntries(
927                            long repositoryId, long folderId, int start, int end,
928                            OrderByComparator<FileEntry> obc)
929                    throws PortalException {
930    
931                    Repository repository = getRepository(repositoryId);
932    
933                    return repository.getFileEntries(folderId, start, end, obc);
934            }
935    
936            /**
937             * Returns the file entries with the file entry type in the folder.
938             *
939             * @param  repositoryId the primary key of the file entry's repository
940             * @param  folderId the primary key of the file entry's folder
941             * @param  fileEntryTypeId the primary key of the file entry type
942             * @return the file entries with the file entry type in the folder
943             * @throws PortalException if the folder could not be found
944             */
945            @Override
946            public List<FileEntry> getFileEntries(
947                            long repositoryId, long folderId, long fileEntryTypeId)
948                    throws PortalException {
949    
950                    return getFileEntries(
951                            repositoryId, folderId, fileEntryTypeId, QueryUtil.ALL_POS,
952                            QueryUtil.ALL_POS);
953            }
954    
955            /**
956             * Returns a range of all the file entries with the file entry type in the
957             * folder.
958             *
959             * @param  repositoryId the primary key of the file entry's repository
960             * @param  folderId the primary key of the file entry's folder
961             * @param  fileEntryTypeId the primary key of the file entry type
962             * @param  start the lower bound of the range of results
963             * @param  end the upper bound of the range of results (not inclusive)
964             * @return the file entries in the folder
965             * @throws PortalException if the folder could not be found
966             */
967            @Override
968            public List<FileEntry> getFileEntries(
969                            long repositoryId, long folderId, long fileEntryTypeId, int start,
970                            int end)
971                    throws PortalException {
972    
973                    return getFileEntries(
974                            repositoryId, folderId, fileEntryTypeId, start, end, null);
975            }
976    
977            /**
978             * Returns an ordered range of all the file entries with the file entry type
979             * in the folder.
980             *
981             * @param  repositoryId the primary key of the repository
982             * @param  folderId the primary key of the folder
983             * @param  fileEntryTypeId the primary key of the file entry type
984             * @param  start the lower bound of the range of results
985             * @param  end the upper bound of the range of results (not inclusive)
986             * @param  obc the comparator to order the results by (optionally
987             *         <code>null</code>)
988             * @return the range of file entries with the file entry type in the folder
989             *         ordered by <code>null</code>
990             * @throws PortalException if the folder could not be found
991             */
992            @Override
993            public List<FileEntry> getFileEntries(
994                            long repositoryId, long folderId, long fileEntryTypeId, int start,
995                            int end, OrderByComparator<FileEntry> obc)
996                    throws PortalException {
997    
998                    Repository repository = getRepository(repositoryId);
999    
1000                    return repository.getFileEntries(
1001                            folderId, fileEntryTypeId, start, end, obc);
1002            }
1003    
1004            @Override
1005            public List<FileEntry> getFileEntries(
1006                            long repositoryId, long folderId, String[] mimeTypes)
1007                    throws PortalException {
1008    
1009                    return getFileEntries(
1010                            repositoryId, folderId, mimeTypes, QueryUtil.ALL_POS,
1011                            QueryUtil.ALL_POS, null);
1012            }
1013    
1014            @Override
1015            public List<FileEntry> getFileEntries(
1016                            long repositoryId, long folderId, String[] mimeTypes, int start,
1017                            int end, OrderByComparator<FileEntry> obc)
1018                    throws PortalException {
1019    
1020                    Repository repository = getRepository(repositoryId);
1021    
1022                    return repository.getFileEntries(folderId, mimeTypes, start, end, obc);
1023            }
1024    
1025            /**
1026             * Returns a range of all the file entries and shortcuts in the folder.
1027             *
1028             * <p>
1029             * Useful when paginating results. Returns a maximum of <code>end -
1030             * start</code> instances. <code>start</code> and <code>end</code> are not
1031             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1032             * refers to the first result in the set. Setting both <code>start</code>
1033             * and <code>end</code> to {@link
1034             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1035             * result set.
1036             * </p>
1037             *
1038             * @param  repositoryId the primary key of the repository
1039             * @param  folderId the primary key of the folder
1040             * @param  status the workflow status
1041             * @param  start the lower bound of the range of results
1042             * @param  end the upper bound of the range of results (not inclusive)
1043             * @return the range of file entries and shortcuts in the folder
1044             * @throws PortalException if the folder could not be found
1045             */
1046            @Override
1047            public List<Object> getFileEntriesAndFileShortcuts(
1048                            long repositoryId, long folderId, int status, int start, int end)
1049                    throws PortalException {
1050    
1051                    Repository repository = getRepository(repositoryId);
1052    
1053                    return repository.getFileEntriesAndFileShortcuts(
1054                            folderId, status, start, end);
1055            }
1056    
1057            /**
1058             * Returns the number of file entries and shortcuts in the folder.
1059             *
1060             * @param  repositoryId the primary key of the repository
1061             * @param  folderId the primary key of the folder
1062             * @param  status the workflow status
1063             * @return the number of file entries and shortcuts in the folder
1064             * @throws PortalException if the folder ould not be found
1065             */
1066            @Override
1067            public int getFileEntriesAndFileShortcutsCount(
1068                            long repositoryId, long folderId, int status)
1069                    throws PortalException {
1070    
1071                    Repository repository = getRepository(repositoryId);
1072    
1073                    return repository.getFileEntriesAndFileShortcutsCount(folderId, status);
1074            }
1075    
1076            /**
1077             * Returns the number of file entries and shortcuts in the folder.
1078             *
1079             * @param  repositoryId the primary key of the repository
1080             * @param  folderId the primary key of the folder
1081             * @param  status the workflow status
1082             * @param  mimeTypes allowed media types
1083             * @return the number of file entries and shortcuts in the folder
1084             * @throws PortalException if the folder ould not be found
1085             */
1086            @Override
1087            public int getFileEntriesAndFileShortcutsCount(
1088                            long repositoryId, long folderId, int status, String[] mimeTypes)
1089                    throws PortalException {
1090    
1091                    Repository repository = getRepository(repositoryId);
1092    
1093                    return repository.getFileEntriesAndFileShortcutsCount(
1094                            folderId, status, mimeTypes);
1095            }
1096    
1097            /**
1098             * Returns the number of file entries in the folder.
1099             *
1100             * @param  repositoryId the primary key of the file entry's repository
1101             * @param  folderId the primary key of the file entry's folder
1102             * @return the number of file entries in the folder
1103             * @throws PortalException if the folder could not be found
1104             */
1105            @Override
1106            public int getFileEntriesCount(long repositoryId, long folderId)
1107                    throws PortalException {
1108    
1109                    Repository repository = getRepository(repositoryId);
1110    
1111                    return repository.getFileEntriesCount(folderId);
1112            }
1113    
1114            /**
1115             * Returns the number of file entries with the file entry type in the
1116             * folder.
1117             *
1118             * @param  repositoryId the primary key of the file entry's repository
1119             * @param  folderId the primary key of the file entry's folder
1120             * @param  fileEntryTypeId the primary key of the file entry type
1121             * @return the number of file entries with the file entry type in the folder
1122             * @throws PortalException if the folder could not be found
1123             */
1124            @Override
1125            public int getFileEntriesCount(
1126                            long repositoryId, long folderId, long fileEntryTypeId)
1127                    throws PortalException {
1128    
1129                    Repository repository = getRepository(repositoryId);
1130    
1131                    return repository.getFileEntriesCount(folderId, fileEntryTypeId);
1132            }
1133    
1134            @Override
1135            public int getFileEntriesCount(
1136                            long repositoryId, long folderId, String[] mimeTypes)
1137                    throws PortalException {
1138    
1139                    Repository repository = getRepository(repositoryId);
1140    
1141                    return repository.getFileEntriesCount(folderId, mimeTypes);
1142            }
1143    
1144            /**
1145             * Returns the file entry with the primary key.
1146             *
1147             * @param  fileEntryId the primary key of the file entry
1148             * @return the file entry with the primary key
1149             * @throws PortalException if the file entry could not be found
1150             */
1151            @Override
1152            public FileEntry getFileEntry(long fileEntryId) throws PortalException {
1153                    Repository repository = getFileEntryRepository(fileEntryId);
1154    
1155                    return repository.getFileEntry(fileEntryId);
1156            }
1157    
1158            /**
1159             * Returns the file entry with the title in the folder.
1160             *
1161             * @param  groupId the primary key of the file entry's group
1162             * @param  folderId the primary key of the file entry's folder
1163             * @param  title the file entry's title
1164             * @return the file entry with the title in the folder
1165             * @throws PortalException if the file entry could not be found
1166             */
1167            @Override
1168            public FileEntry getFileEntry(long groupId, long folderId, String title)
1169                    throws PortalException {
1170    
1171                    try {
1172                            Repository repository = getRepository(groupId);
1173    
1174                            return repository.getFileEntry(folderId, title);
1175                    }
1176                    catch (NoSuchFileEntryException nsfee) {
1177                            if (folderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
1178                                    Repository repository = getFolderRepository(folderId);
1179    
1180                                    return repository.getFileEntry(folderId, title);
1181                            }
1182                            else {
1183                                    throw nsfee;
1184                            }
1185                    }
1186            }
1187    
1188            /**
1189             * Returns the file entry with the UUID and group.
1190             *
1191             * @param  uuid the file entry's UUID
1192             * @param  groupId the primary key of the file entry's group
1193             * @return the file entry with the UUID and group
1194             * @throws PortalException if the file entry could not be found
1195             */
1196            @Override
1197            public FileEntry getFileEntryByUuidAndGroupId(String uuid, long groupId)
1198                    throws PortalException {
1199    
1200                    FileEntry fileEntry = fetchFileEntryByUuidAndRepositoryId(
1201                            uuid, groupId);
1202    
1203                    if (fileEntry != null) {
1204                            return fileEntry;
1205                    }
1206    
1207                    List<com.liferay.portal.model.Repository> repositories =
1208                            repositoryPersistence.findByGroupId(groupId);
1209    
1210                    for (com.liferay.portal.model.Repository repository : repositories) {
1211                            fileEntry = fetchFileEntryByUuidAndRepositoryId(
1212                                    uuid, repository.getRepositoryId());
1213    
1214                            if (fileEntry != null) {
1215                                    return fileEntry;
1216                            }
1217                    }
1218    
1219                    StringBundler msg = new StringBundler(6);
1220    
1221                    msg.append("No DLFileEntry exists with the key {");
1222                    msg.append("uuid=");
1223                    msg.append(uuid);
1224                    msg.append(", groupId=");
1225                    msg.append(groupId);
1226                    msg.append(StringPool.CLOSE_CURLY_BRACE);
1227    
1228                    throw new NoSuchFileEntryException(msg.toString());
1229            }
1230    
1231            /**
1232             * Returns the file shortcut with the primary key. This method is only
1233             * supported by the Liferay repository.
1234             *
1235             * @param  fileShortcutId the primary key of the file shortcut
1236             * @return the file shortcut with the primary key
1237             * @throws PortalException if the file shortcut could not be found
1238             */
1239            @Override
1240            public DLFileShortcut getFileShortcut(long fileShortcutId)
1241                    throws PortalException {
1242    
1243                    return dlFileShortcutService.getFileShortcut(fileShortcutId);
1244            }
1245    
1246            /**
1247             * Returns the file version with the primary key.
1248             *
1249             * @param  fileVersionId the primary key of the file version
1250             * @return the file version with the primary key
1251             * @throws PortalException if the file version could not be found
1252             */
1253            @Override
1254            public FileVersion getFileVersion(long fileVersionId)
1255                    throws PortalException {
1256    
1257                    Repository repository = getFileVersionRepository(fileVersionId);
1258    
1259                    return repository.getFileVersion(fileVersionId);
1260            }
1261    
1262            /**
1263             * Returns the folder with the primary key.
1264             *
1265             * @param  folderId the primary key of the folder
1266             * @return the folder with the primary key
1267             * @throws PortalException if the folder could not be found
1268             */
1269            @Override
1270            public Folder getFolder(long folderId) throws PortalException {
1271                    Repository repository = getFolderRepository(folderId);
1272    
1273                    return repository.getFolder(folderId);
1274            }
1275    
1276            /**
1277             * Returns the folder with the name in the parent folder.
1278             *
1279             * @param  repositoryId the primary key of the folder's repository
1280             * @param  parentFolderId the primary key of the folder's parent folder
1281             * @param  name the folder's name
1282             * @return the folder with the name in the parent folder
1283             * @throws PortalException if the folder could not be found
1284             */
1285            @Override
1286            public Folder getFolder(long repositoryId, long parentFolderId, String name)
1287                    throws PortalException {
1288    
1289                    Repository repository = getRepository(repositoryId);
1290    
1291                    return repository.getFolder(parentFolderId, name);
1292            }
1293    
1294            /**
1295             * Returns all immediate subfolders of the parent folder.
1296             *
1297             * @param  repositoryId the primary key of the folder's repository
1298             * @param  parentFolderId the primary key of the folder's parent folder
1299             * @return the immediate subfolders of the parent folder
1300             * @throws PortalException if the parent folder could not be found
1301             */
1302            @Override
1303            public List<Folder> getFolders(long repositoryId, long parentFolderId)
1304                    throws PortalException {
1305    
1306                    return getFolders(
1307                            repositoryId, parentFolderId, QueryUtil.ALL_POS, QueryUtil.ALL_POS);
1308            }
1309    
1310            /**
1311             * Returns all immediate subfolders of the parent folder, optionally
1312             * including mount folders for third-party repositories.
1313             *
1314             * @param  repositoryId the primary key of the folder's repository
1315             * @param  parentFolderId the primary key of the folder's parent folder
1316             * @param  includeMountFolders whether to include mount folders for
1317             *         third-party repositories
1318             * @return the immediate subfolders of the parent folder
1319             * @throws PortalException if the parent folder could not be found
1320             */
1321            @Override
1322            public List<Folder> getFolders(
1323                            long repositoryId, long parentFolderId, boolean includeMountFolders)
1324                    throws PortalException {
1325    
1326                    return getFolders(
1327                            repositoryId, parentFolderId, includeMountFolders,
1328                            QueryUtil.ALL_POS, QueryUtil.ALL_POS);
1329            }
1330    
1331            /**
1332             * Returns a range of all the immediate subfolders of the parent folder,
1333             * optionally including mount folders for third-party repositories.
1334             *
1335             * <p>
1336             * Useful when paginating results. Returns a maximum of <code>end -
1337             * start</code> instances. <code>start</code> and <code>end</code> are not
1338             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1339             * refers to the first result in the set. Setting both <code>start</code>
1340             * and <code>end</code> to {@link
1341             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1342             * result set.
1343             * </p>
1344             *
1345             * @param  repositoryId the primary key of the folder's repository
1346             * @param  parentFolderId the primary key of the folder's parent folder
1347             * @param  includeMountFolders whether to include mount folders for
1348             *         third-party repositories
1349             * @param  start the lower bound of the range of results
1350             * @param  end the upper bound of the range of results (not inclusive)
1351             * @return the range of immediate subfolders of the parent folder
1352             * @throws PortalException if the parent folder could not be found
1353             */
1354            @Override
1355            public List<Folder> getFolders(
1356                            long repositoryId, long parentFolderId, boolean includeMountFolders,
1357                            int start, int end)
1358                    throws PortalException {
1359    
1360                    return getFolders(
1361                            repositoryId, parentFolderId, includeMountFolders, start, end,
1362                            null);
1363            }
1364    
1365            /**
1366             * Returns an ordered range of all the immediate subfolders of the parent
1367             * folder.
1368             *
1369             * <p>
1370             * Useful when paginating results. Returns a maximum of <code>end -
1371             * start</code> instances. <code>start</code> and <code>end</code> are not
1372             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1373             * refers to the first result in the set. Setting both <code>start</code>
1374             * and <code>end</code> to {@link
1375             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1376             * result set.
1377             * </p>
1378             *
1379             * @param  repositoryId the primary key of the folder's repository
1380             * @param  parentFolderId the primary key of the folder's parent folder
1381             * @param  includeMountFolders whether to include mount folders for
1382             *         third-party repositories
1383             * @param  start the lower bound of the range of results
1384             * @param  end the upper bound of the range of results (not inclusive)
1385             * @param  obc the comparator to order the folders (optionally
1386             *         <code>null</code>)
1387             * @return the range of immediate subfolders of the parent folder ordered by
1388             *         comparator <code>obc</code>
1389             * @throws PortalException if the parent folder could not be found
1390             */
1391            @Override
1392            public List<Folder> getFolders(
1393                            long repositoryId, long parentFolderId, boolean includeMountFolders,
1394                            int start, int end, OrderByComparator<Folder> obc)
1395                    throws PortalException {
1396    
1397                    Repository repository = getRepository(repositoryId);
1398    
1399                    return repository.getFolders(
1400                            parentFolderId, includeMountFolders, start, end, obc);
1401            }
1402    
1403            /**
1404             * Returns an ordered range of all the immediate subfolders of the parent
1405             * folder.
1406             *
1407             * <p>
1408             * Useful when paginating results. Returns a maximum of <code>end -
1409             * start</code> instances. <code>start</code> and <code>end</code> are not
1410             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1411             * refers to the first result in the set. Setting both <code>start</code>
1412             * and <code>end</code> to {@link
1413             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1414             * result set.
1415             * </p>
1416             *
1417             * @param  repositoryId the primary key of the folder's repository
1418             * @param  parentFolderId the primary key of the folder's parent folder
1419             * @param  status the workflow status
1420             * @param  includeMountFolders whether to include mount folders for
1421             *         third-party repositories
1422             * @param  start the lower bound of the range of results
1423             * @param  end the upper bound of the range of results (not inclusive)
1424             * @param  obc the comparator to order the folders (optionally
1425             *         <code>null</code>)
1426             * @return the range of immediate subfolders of the parent folder ordered by
1427             *         comparator <code>obc</code>
1428             * @throws PortalException if the parent folder could not be found
1429             */
1430            @Override
1431            public List<Folder> getFolders(
1432                            long repositoryId, long parentFolderId, int status,
1433                            boolean includeMountFolders, int start, int end,
1434                            OrderByComparator<Folder> obc)
1435                    throws PortalException {
1436    
1437                    Repository repository = getRepository(repositoryId);
1438    
1439                    return repository.getFolders(
1440                            parentFolderId, status, includeMountFolders, start, end, obc);
1441            }
1442    
1443            /**
1444             * Returns a range of all the immediate subfolders of the parent folder.
1445             *
1446             * <p>
1447             * Useful when paginating results. Returns a maximum of <code>end -
1448             * start</code> instances. <code>start</code> and <code>end</code> are not
1449             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1450             * refers to the first result in the set. Setting both <code>start</code>
1451             * and <code>end</code> to {@link
1452             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1453             * result set.
1454             * </p>
1455             *
1456             * @param  repositoryId the primary key of the folder's repository
1457             * @param  parentFolderId the primary key of the folder's parent folder
1458             * @param  start the lower bound of the range of results
1459             * @param  end the upper bound of the range of results (not inclusive)
1460             * @return the range of immediate subfolders of the parent folder
1461             * @throws PortalException if the parent folder could not be found
1462             */
1463            @Override
1464            public List<Folder> getFolders(
1465                            long repositoryId, long parentFolderId, int start, int end)
1466                    throws PortalException {
1467    
1468                    return getFolders(repositoryId, parentFolderId, start, end, null);
1469            }
1470    
1471            /**
1472             * Returns an ordered range of all the immediate subfolders of the parent
1473             * folder.
1474             *
1475             * <p>
1476             * Useful when paginating results. Returns a maximum of <code>end -
1477             * start</code> instances. <code>start</code> and <code>end</code> are not
1478             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1479             * refers to the first result in the set. Setting both <code>start</code>
1480             * and <code>end</code> to {@link
1481             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1482             * result set.
1483             * </p>
1484             *
1485             * @param  repositoryId the primary key of the folder's repository
1486             * @param  parentFolderId the primary key of the folder's parent folder
1487             * @param  start the lower bound of the range of results
1488             * @param  end the upper bound of the range of results (not inclusive)
1489             * @param  obc the comparator to order the folders (optionally
1490             *         <code>null</code>)
1491             * @return the range of immediate subfolders of the parent folder ordered by
1492             *         comparator <code>obc</code>
1493             * @throws PortalException if the parent folder could not be found
1494             */
1495            @Override
1496            public List<Folder> getFolders(
1497                            long repositoryId, long parentFolderId, int start, int end,
1498                            OrderByComparator<Folder> obc)
1499                    throws PortalException {
1500    
1501                    Repository repository = getRepository(repositoryId);
1502    
1503                    return repository.getFolders(parentFolderId, true, start, end, obc);
1504            }
1505    
1506            /**
1507             * Returns a range of all the immediate subfolders, file entries, and file
1508             * shortcuts in the parent folder.
1509             *
1510             * <p>
1511             * Useful when paginating results. Returns a maximum of <code>end -
1512             * start</code> instances. <code>start</code> and <code>end</code> are not
1513             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1514             * refers to the first result in the set. Setting both <code>start</code>
1515             * and <code>end</code> to {@link
1516             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1517             * result set.
1518             * </p>
1519             *
1520             * @param  repositoryId the primary key of the repository
1521             * @param  folderId the primary key of the parent folder
1522             * @param  status the workflow status
1523             * @param  includeMountFolders whether to include mount folders for
1524             *         third-party repositories
1525             * @param  start the lower bound of the range of results
1526             * @param  end the upper bound of the range of results (not inclusive)
1527             * @return the range of immediate subfolders, file entries, and file
1528             *         shortcuts in the parent folder ordered by comparator
1529             *         <code>obc</code>
1530             * @throws PortalException if the parent folder could not be found
1531             */
1532            @Override
1533            public List<Object> getFoldersAndFileEntriesAndFileShortcuts(
1534                            long repositoryId, long folderId, int status,
1535                            boolean includeMountFolders, int start, int end)
1536                    throws PortalException {
1537    
1538                    return getFoldersAndFileEntriesAndFileShortcuts(
1539                            repositoryId, folderId, status, includeMountFolders, start, end,
1540                            null);
1541            }
1542    
1543            /**
1544             * Returns an ordered range of all the immediate subfolders, file entries,
1545             * and file shortcuts in the parent folder.
1546             *
1547             * <p>
1548             * Useful when paginating results. Returns a maximum of <code>end -
1549             * start</code> instances. <code>start</code> and <code>end</code> are not
1550             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1551             * refers to the first result in the set. Setting both <code>start</code>
1552             * and <code>end</code> to {@link
1553             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1554             * result set.
1555             * </p>
1556             *
1557             * @param  repositoryId the primary key of the repository
1558             * @param  folderId the primary key of the parent folder
1559             * @param  status the workflow status
1560             * @param  includeMountFolders whether to include mount folders for
1561             *         third-party repositories
1562             * @param  start the lower bound of the range of results
1563             * @param  end the upper bound of the range of results (not inclusive)
1564             * @param  obc the comparator to order the results (optionally
1565             *         <code>null</code>)
1566             * @return the range of immediate subfolders, file entries, and file
1567             *         shortcuts in the parent folder ordered by comparator
1568             *         <code>obc</code>
1569             * @throws PortalException if the parent folder could not be found
1570             */
1571            @Override
1572            public List<Object> getFoldersAndFileEntriesAndFileShortcuts(
1573                            long repositoryId, long folderId, int status,
1574                            boolean includeMountFolders, int start, int end,
1575                            OrderByComparator<?> obc)
1576                    throws PortalException {
1577    
1578                    return getFoldersAndFileEntriesAndFileShortcuts(
1579                            repositoryId, folderId, status, null, includeMountFolders, start,
1580                            end, obc);
1581            }
1582    
1583            @Override
1584            public List<Object> getFoldersAndFileEntriesAndFileShortcuts(
1585                            long repositoryId, long folderId, int status, String[] mimeTypes,
1586                            boolean includeMountFolders, int start, int end,
1587                            OrderByComparator<?> obc)
1588                    throws PortalException {
1589    
1590                    Repository repository = getRepository(repositoryId);
1591    
1592                    return repository.getFoldersAndFileEntriesAndFileShortcuts(
1593                            folderId, status, mimeTypes, includeMountFolders, start, end, obc);
1594            }
1595    
1596            /**
1597             * Returns the number of immediate subfolders, file entries, and file
1598             * shortcuts in the parent folder.
1599             *
1600             * @param  repositoryId the primary key of the repository
1601             * @param  folderId the primary key of the parent folder
1602             * @param  status the workflow status
1603             * @param  includeMountFolders whether to include mount folders for
1604             *         third-party repositories
1605             * @return the number of immediate subfolders, file entries, and file
1606             *         shortcuts in the parent folder
1607             * @throws PortalException if the folder could not be found
1608             */
1609            @Override
1610            public int getFoldersAndFileEntriesAndFileShortcutsCount(
1611                            long repositoryId, long folderId, int status,
1612                            boolean includeMountFolders)
1613                    throws PortalException {
1614    
1615                    return getFoldersAndFileEntriesAndFileShortcutsCount(
1616                            repositoryId, folderId, status, null, includeMountFolders);
1617            }
1618    
1619            @Override
1620            public int getFoldersAndFileEntriesAndFileShortcutsCount(
1621                            long repositoryId, long folderId, int status, String[] mimeTypes,
1622                            boolean includeMountFolders)
1623                    throws PortalException {
1624    
1625                    Repository repository = getRepository(repositoryId);
1626    
1627                    return repository.getFoldersAndFileEntriesAndFileShortcutsCount(
1628                            folderId, status, mimeTypes, includeMountFolders);
1629            }
1630    
1631            /**
1632             * Returns the number of immediate subfolders of the parent folder.
1633             *
1634             * @param  repositoryId the primary key of the folder's repository
1635             * @param  parentFolderId the primary key of the folder's parent folder
1636             * @return the number of immediate subfolders of the parent folder
1637             * @throws PortalException if the parent folder could not be found
1638             */
1639            @Override
1640            public int getFoldersCount(long repositoryId, long parentFolderId)
1641                    throws PortalException {
1642    
1643                    return getFoldersCount(repositoryId, parentFolderId, true);
1644            }
1645    
1646            /**
1647             * Returns the number of immediate subfolders of the parent folder,
1648             * optionally including mount folders for third-party repositories.
1649             *
1650             * @param  repositoryId the primary key of the folder's repository
1651             * @param  parentFolderId the primary key of the folder's parent folder
1652             * @param  includeMountFolders whether to include mount folders for
1653             *         third-party repositories
1654             * @return the number of immediate subfolders of the parent folder
1655             * @throws PortalException if the parent folder could not be found
1656             */
1657            @Override
1658            public int getFoldersCount(
1659                            long repositoryId, long parentFolderId, boolean includeMountFolders)
1660                    throws PortalException {
1661    
1662                    Repository repository = getRepository(repositoryId);
1663    
1664                    return repository.getFoldersCount(parentFolderId, includeMountFolders);
1665            }
1666    
1667            /**
1668             * Returns the number of immediate subfolders of the parent folder,
1669             * optionally including mount folders for third-party repositories.
1670             *
1671             * @param  repositoryId the primary key of the folder's repository
1672             * @param  parentFolderId the primary key of the folder's parent folder
1673             * @param  status the workflow status
1674             * @param  includeMountFolders whether to include mount folders for
1675             *         third-party repositories
1676             * @return the number of immediate subfolders of the parent folder
1677             * @throws PortalException if the parent folder could not be found
1678             */
1679            @Override
1680            public int getFoldersCount(
1681                            long repositoryId, long parentFolderId, int status,
1682                            boolean includeMountFolders)
1683                    throws PortalException {
1684    
1685                    Repository repository = getRepository(repositoryId);
1686    
1687                    return repository.getFoldersCount(
1688                            parentFolderId, status, includeMountFolders);
1689            }
1690    
1691            /**
1692             * Returns the number of immediate subfolders and file entries across the
1693             * folders.
1694             *
1695             * @param  repositoryId the primary key of the repository
1696             * @param  folderIds the primary keys of folders from which to count
1697             *         immediate subfolders and file entries
1698             * @param  status the workflow status
1699             * @return the number of immediate subfolders and file entries across the
1700             *         folders
1701             * @throws PortalException if the repository could not be found
1702             */
1703            @Override
1704            public int getFoldersFileEntriesCount(
1705                            long repositoryId, List<Long> folderIds, int status)
1706                    throws PortalException {
1707    
1708                    Repository repository = getRepository(repositoryId);
1709    
1710                    return repository.getFoldersFileEntriesCount(folderIds, status);
1711            }
1712    
1713            /**
1714             * Returns an ordered range of all the file entries in the group starting at
1715             * the repository default parent folder that are stored within the Liferay
1716             * repository. This method is primarily used to search for recently modified
1717             * file entries. It can be limited to the file entries modified by a given
1718             * user.
1719             *
1720             * <p>
1721             * Useful when paginating results. Returns a maximum of <code>end -
1722             * start</code> instances. <code>start</code> and <code>end</code> are not
1723             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1724             * refers to the first result in the set. Setting both <code>start</code>
1725             * and <code>end</code> to {@link
1726             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1727             * result set.
1728             * </p>
1729             *
1730             * @param  groupId the primary key of the group
1731             * @param  userId the primary key of the user who created the file
1732             *         (optionally <code>0</code>)
1733             * @param  start the lower bound of the range of results
1734             * @param  end the upper bound of the range of results (not inclusive)
1735             * @return the range of matching file entries ordered by date modified
1736             * @throws PortalException if the group could not be found
1737             */
1738            @Override
1739            public List<FileEntry> getGroupFileEntries(
1740                            long groupId, long userId, int start, int end)
1741                    throws PortalException {
1742    
1743                    return getGroupFileEntries(
1744                            groupId, userId, DLFolderConstants.DEFAULT_PARENT_FOLDER_ID, start,
1745                            end, new RepositoryModelModifiedDateComparator<FileEntry>());
1746            }
1747    
1748            /**
1749             * Returns an ordered range of all the file entries in the group that are
1750             * stored within the Liferay repository. This method is primarily used to
1751             * search for recently modified file entries. It can be limited to the file
1752             * entries modified by a given user.
1753             *
1754             * <p>
1755             * Useful when paginating results. Returns a maximum of <code>end -
1756             * start</code> instances. <code>start</code> and <code>end</code> are not
1757             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1758             * refers to the first result in the set. Setting both <code>start</code>
1759             * and <code>end</code> to {@link
1760             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1761             * result set.
1762             * </p>
1763             *
1764             * @param  groupId the primary key of the group
1765             * @param  userId the primary key of the user who created the file
1766             *         (optionally <code>0</code>)
1767             * @param  start the lower bound of the range of results
1768             * @param  end the upper bound of the range of results (not inclusive)
1769             * @param  obc the comparator to order the file entries (optionally
1770             *         <code>null</code>)
1771             * @return the range of matching file entries ordered by comparator
1772             *         <code>obc</code>
1773             * @throws PortalException if the group could not be found
1774             */
1775            @Override
1776            public List<FileEntry> getGroupFileEntries(
1777                            long groupId, long userId, int start, int end,
1778                            OrderByComparator<FileEntry> obc)
1779                    throws PortalException {
1780    
1781                    return getGroupFileEntries(
1782                            groupId, userId, DLFolderConstants.DEFAULT_PARENT_FOLDER_ID, start,
1783                            end, obc);
1784            }
1785    
1786            /**
1787             * Returns an ordered range of all the file entries in the group starting at
1788             * the root folder that are stored within the Liferay repository. This
1789             * method is primarily used to search for recently modified file entries. It
1790             * can be limited to the file entries modified by a given user.
1791             *
1792             * <p>
1793             * Useful when paginating results. Returns a maximum of <code>end -
1794             * start</code> instances. <code>start</code> and <code>end</code> are not
1795             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1796             * refers to the first result in the set. Setting both <code>start</code>
1797             * and <code>end</code> to {@link
1798             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1799             * result set.
1800             * </p>
1801             *
1802             * @param  groupId the primary key of the group
1803             * @param  userId the primary key of the user who created the file
1804             *         (optionally <code>0</code>)
1805             * @param  rootFolderId the primary key of the root folder to begin the
1806             *         search
1807             * @param  start the lower bound of the range of results
1808             * @param  end the upper bound of the range of results (not inclusive)
1809             * @return the range of matching file entries ordered by date modified
1810             * @throws PortalException if the group could not be found
1811             */
1812            @Override
1813            public List<FileEntry> getGroupFileEntries(
1814                            long groupId, long userId, long rootFolderId, int start, int end)
1815                    throws PortalException {
1816    
1817                    return getGroupFileEntries(
1818                            groupId, userId, rootFolderId, start, end,
1819                            new RepositoryModelModifiedDateComparator<FileEntry>());
1820            }
1821    
1822            /**
1823             * Returns an ordered range of all the file entries in the group starting at
1824             * the root folder that are stored within the Liferay repository. This
1825             * method is primarily used to search for recently modified file entries. It
1826             * can be limited to the file entries modified by a given user.
1827             *
1828             * <p>
1829             * Useful when paginating results. Returns a maximum of <code>end -
1830             * start</code> instances. <code>start</code> and <code>end</code> are not
1831             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1832             * refers to the first result in the set. Setting both <code>start</code>
1833             * and <code>end</code> to {@link
1834             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1835             * result set.
1836             * </p>
1837             *
1838             * @param  groupId the primary key of the group
1839             * @param  userId the primary key of the user who created the file
1840             *         (optionally <code>0</code>)
1841             * @param  rootFolderId the primary key of the root folder to begin the
1842             *         search
1843             * @param  start the lower bound of the range of results
1844             * @param  end the upper bound of the range of results (not inclusive)
1845             * @param  obc the comparator to order the file entries (optionally
1846             *         <code>null</code>)
1847             * @return the range of matching file entries ordered by comparator
1848             *         <code>obc</code>
1849             * @throws PortalException if the group could not be found
1850             */
1851            @Override
1852            public List<FileEntry> getGroupFileEntries(
1853                            long groupId, long userId, long rootFolderId, int start, int end,
1854                            OrderByComparator<FileEntry> obc)
1855                    throws PortalException {
1856    
1857                    Repository repository = getRepository(groupId);
1858    
1859                    return repository.getRepositoryFileEntries(
1860                            userId, rootFolderId, start, end, obc);
1861            }
1862    
1863            @Override
1864            public List<FileEntry> getGroupFileEntries(
1865                            long groupId, long userId, long rootFolderId, String[] mimeTypes,
1866                            int status, int start, int end, OrderByComparator<FileEntry> obc)
1867                    throws PortalException {
1868    
1869                    Repository repository = getRepository(groupId);
1870    
1871                    return repository.getRepositoryFileEntries(
1872                            userId, rootFolderId, mimeTypes, status, start, end, obc);
1873            }
1874    
1875            /**
1876             * Returns the number of file entries in a group starting at the repository
1877             * default parent folder that are stored within the Liferay repository. This
1878             * method is primarily used to search for recently modified file entries. It
1879             * can be limited to the file entries modified by a given user.
1880             *
1881             * @param  groupId the primary key of the group
1882             * @param  userId the primary key of the user who created the file
1883             *         (optionally <code>0</code>)
1884             * @return the number of matching file entries
1885             * @throws PortalException if the group could not be found
1886             */
1887            @Override
1888            public int getGroupFileEntriesCount(long groupId, long userId)
1889                    throws PortalException {
1890    
1891                    return getGroupFileEntriesCount(
1892                            groupId, userId, DLFolderConstants.DEFAULT_PARENT_FOLDER_ID);
1893            }
1894    
1895            /**
1896             * Returns the number of file entries in a group starting at the root folder
1897             * that are stored within the Liferay repository. This method is primarily
1898             * used to search for recently modified file entries. It can be limited to
1899             * the file entries modified by a given user.
1900             *
1901             * @param  groupId the primary key of the group
1902             * @param  userId the primary key of the user who created the file
1903             *         (optionally <code>0</code>)
1904             * @param  rootFolderId the primary key of the root folder to begin the
1905             *         search
1906             * @return the number of matching file entries
1907             * @throws PortalException if the group could not be found
1908             */
1909            @Override
1910            public int getGroupFileEntriesCount(
1911                            long groupId, long userId, long rootFolderId)
1912                    throws PortalException {
1913    
1914                    Repository repository = getRepository(groupId);
1915    
1916                    return repository.getRepositoryFileEntriesCount(userId, rootFolderId);
1917            }
1918    
1919            @Override
1920            public int getGroupFileEntriesCount(
1921                            long groupId, long userId, long rootFolderId, String[] mimeTypes,
1922                            int status)
1923                    throws PortalException {
1924    
1925                    Repository repository = getRepository(groupId);
1926    
1927                    return repository.getRepositoryFileEntriesCount(
1928                            userId, rootFolderId, mimeTypes, status);
1929            }
1930    
1931            /**
1932             * Returns all immediate subfolders of the parent folder that are used for
1933             * mounting third-party repositories. This method is only supported by the
1934             * Liferay repository.
1935             *
1936             * @param  repositoryId the primary key of the folder's repository
1937             * @param  parentFolderId the primary key of the folder's parent folder
1938             * @return the immediate subfolders of the parent folder that are used for
1939             *         mounting third-party repositories
1940             * @throws PortalException if the repository or parent folder could not be
1941             *         found
1942             */
1943            @Override
1944            public List<Folder> getMountFolders(long repositoryId, long parentFolderId)
1945                    throws PortalException {
1946    
1947                    return getMountFolders(
1948                            repositoryId, parentFolderId, QueryUtil.ALL_POS, QueryUtil.ALL_POS);
1949            }
1950    
1951            /**
1952             * Returns a range of all the immediate subfolders of the parent folder that
1953             * are used for mounting third-party repositories. This method is only
1954             * supported by the Liferay repository.
1955             *
1956             * <p>
1957             * Useful when paginating results. Returns a maximum of <code>end -
1958             * start</code> instances. <code>start</code> and <code>end</code> are not
1959             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1960             * refers to the first result in the set. Setting both <code>start</code>
1961             * and <code>end</code> to {@link
1962             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1963             * result set.
1964             * </p>
1965             *
1966             * @param  repositoryId the primary key of the repository
1967             * @param  parentFolderId the primary key of the parent folder
1968             * @param  start the lower bound of the range of results
1969             * @param  end the upper bound of the range of results (not inclusive)
1970             * @return the range of immediate subfolders of the parent folder that are
1971             *         used for mounting third-party repositories
1972             * @throws PortalException if the repository or parent folder could not be
1973             *         found
1974             */
1975            @Override
1976            public List<Folder> getMountFolders(
1977                            long repositoryId, long parentFolderId, int start, int end)
1978                    throws PortalException {
1979    
1980                    return getMountFolders(repositoryId, parentFolderId, start, end, null);
1981            }
1982    
1983            /**
1984             * Returns an ordered range of all the immediate subfolders of the parent
1985             * folder that are used for mounting third-party repositories. This method
1986             * is only supported by the Liferay repository.
1987             *
1988             * <p>
1989             * Useful when paginating results. Returns a maximum of <code>end -
1990             * start</code> instances. <code>start</code> and <code>end</code> are not
1991             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1992             * refers to the first result in the set. Setting both <code>start</code>
1993             * and <code>end</code> to {@link
1994             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1995             * result set.
1996             * </p>
1997             *
1998             * @param  repositoryId the primary key of the folder's repository
1999             * @param  parentFolderId the primary key of the folder's parent folder
2000             * @param  start the lower bound of the range of results
2001             * @param  end the upper bound of the range of results (not inclusive)
2002             * @param  obc the comparator to order the folders (optionally
2003             *         <code>null</code>)
2004             * @return the range of immediate subfolders of the parent folder that are
2005             *         used for mounting third-party repositories ordered by comparator
2006             *         <code>obc</code>
2007             * @throws PortalException if the repository or parent folder could not be
2008             *         found
2009             */
2010            @Override
2011            public List<Folder> getMountFolders(
2012                            long repositoryId, long parentFolderId, int start, int end,
2013                            OrderByComparator<Folder> obc)
2014                    throws PortalException {
2015    
2016                    Repository repository = getRepository(repositoryId);
2017    
2018                    return repository.getMountFolders(parentFolderId, start, end, obc);
2019            }
2020    
2021            /**
2022             * Returns the number of immediate subfolders of the parent folder that are
2023             * used for mounting third-party repositories. This method is only supported
2024             * by the Liferay repository.
2025             *
2026             * @param  repositoryId the primary key of the repository
2027             * @param  parentFolderId the primary key of the parent folder
2028             * @return the number of folders of the parent folder that are used for
2029             *         mounting third-party repositories
2030             * @throws PortalException if the repository or parent folder could not be
2031             *         found
2032             */
2033            @Override
2034            public int getMountFoldersCount(long repositoryId, long parentFolderId)
2035                    throws PortalException {
2036    
2037                    Repository repository = getRepository(repositoryId);
2038    
2039                    return repository.getMountFoldersCount(parentFolderId);
2040            }
2041    
2042            @Override
2043            public void getSubfolderIds(
2044                            long repositoryId, List<Long> folderIds, long folderId)
2045                    throws PortalException {
2046    
2047                    Repository repository = getRepository(repositoryId);
2048    
2049                    repository.getSubfolderIds(folderIds, folderId);
2050            }
2051    
2052            /**
2053             * Returns all the descendant folders of the folder with the primary key.
2054             *
2055             * @param  repositoryId the primary key of the repository
2056             * @param  folderId the primary key of the folder
2057             * @return the descendant folders of the folder with the primary key
2058             * @throws PortalException if the repository or parent folder could not be
2059             *         found
2060             */
2061            @Override
2062            public List<Long> getSubfolderIds(long repositoryId, long folderId)
2063                    throws PortalException {
2064    
2065                    return getSubfolderIds(repositoryId, folderId, true);
2066            }
2067    
2068            /**
2069             * Returns descendant folders of the folder with the primary key, optionally
2070             * limiting to one level deep.
2071             *
2072             * @param  repositoryId the primary key of the repository
2073             * @param  folderId the primary key of the folder
2074             * @param  recurse whether to recurse through each subfolder
2075             * @return the descendant folders of the folder with the primary key
2076             * @throws PortalException if the repository or parent folder could not be
2077             *         found
2078             */
2079            @Override
2080            public List<Long> getSubfolderIds(
2081                            long repositoryId, long folderId, boolean recurse)
2082                    throws PortalException {
2083    
2084                    Repository repository = getRepository(repositoryId);
2085    
2086                    return repository.getSubfolderIds(folderId, recurse);
2087            }
2088    
2089            /**
2090             * Returns all the temporary file entry names.
2091             *
2092             * @param  groupId the primary key of the group
2093             * @param  folderId the primary key of the folder where the file entry will
2094             *         eventually reside
2095             * @param  folderName the temporary folder's name
2096             * @return the temporary file entry names
2097             * @throws PortalException if the folder was invalid
2098             * @see    #addTempFileEntry(long, long, String, String, File, String)
2099             * @see    com.liferay.portal.kernel.util.TempFileEntryUtil
2100             */
2101            @Override
2102            public String[] getTempFileNames(
2103                            long groupId, long folderId, String folderName)
2104                    throws PortalException {
2105    
2106                    DLFolderPermission.check(
2107                            getPermissionChecker(), groupId, folderId, ActionKeys.ADD_DOCUMENT);
2108    
2109                    return TempFileEntryUtil.getTempFileNames(
2110                            groupId, getUserId(), folderName);
2111            }
2112    
2113            /**
2114             * @deprecated As of 6.2.0, replaced by {@link #checkOutFileEntry(long,
2115             *             ServiceContext)}
2116             */
2117            @Deprecated
2118            @Override
2119            public Lock lockFileEntry(long fileEntryId) throws PortalException {
2120                    checkOutFileEntry(fileEntryId, new ServiceContext());
2121    
2122                    FileEntry fileEntry = getFileEntry(fileEntryId);
2123    
2124                    return fileEntry.getLock();
2125            }
2126    
2127            /**
2128             * @deprecated As of 6.2.0, replaced by {@link #checkOutFileEntry(long,
2129             *             String, long, ServiceContext)}
2130             */
2131            @Deprecated
2132            @Override
2133            public Lock lockFileEntry(
2134                            long fileEntryId, String owner, long expirationTime)
2135                    throws PortalException {
2136    
2137                    FileEntry fileEntry = checkOutFileEntry(
2138                            fileEntryId, owner, expirationTime, new ServiceContext());
2139    
2140                    return fileEntry.getLock();
2141            }
2142    
2143            /**
2144             * Locks the folder. This method is primarily used by WebDAV.
2145             *
2146             * @param  repositoryId the primary key of the repository
2147             * @param  folderId the primary key of the folder
2148             * @return the lock object
2149             * @throws PortalException if the repository or folder could not be found
2150             */
2151            @Override
2152            public Lock lockFolder(long repositoryId, long folderId)
2153                    throws PortalException {
2154    
2155                    Repository repository = getRepository(repositoryId);
2156    
2157                    return repository.lockFolder(folderId);
2158            }
2159    
2160            /**
2161             * Locks the folder. This method is primarily used by WebDAV.
2162             *
2163             * @param  repositoryId the primary key of the repository
2164             * @param  folderId the primary key of the folder
2165             * @param  owner the owner string for the checkout (optionally
2166             *         <code>null</code>)
2167             * @param  inheritable whether the lock must propagate to descendants
2168             * @param  expirationTime the time in milliseconds before the lock expires.
2169             *         If the value is <code>0</code>, the default expiration time will
2170             *         be used from <code>portal.properties>.
2171             * @return the lock object
2172             * @throws PortalException if the repository or folder could not be found
2173             */
2174            @Override
2175            public Lock lockFolder(
2176                            long repositoryId, long folderId, String owner, boolean inheritable,
2177                            long expirationTime)
2178                    throws PortalException {
2179    
2180                    Repository repository = getRepository(repositoryId);
2181    
2182                    return repository.lockFolder(
2183                            folderId, owner, inheritable, expirationTime);
2184            }
2185    
2186            /**
2187             * Moves the file entry to the new folder.
2188             *
2189             * @param  fileEntryId the primary key of the file entry
2190             * @param  newFolderId the primary key of the new folder
2191             * @param  serviceContext the service context to be applied
2192             * @return the file entry
2193             * @throws PortalException if the file entry or the new folder could not be
2194             *         found
2195             */
2196            @Override
2197            public FileEntry moveFileEntry(
2198                            long fileEntryId, long newFolderId, ServiceContext serviceContext)
2199                    throws PortalException {
2200    
2201                    Repository fromRepository = getFileEntryRepository(fileEntryId);
2202                    Repository toRepository = getFolderRepository(
2203                            newFolderId, serviceContext.getScopeGroupId());
2204    
2205                    if (newFolderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
2206                            Folder toFolder = toRepository.getFolder(newFolderId);
2207    
2208                            if (toFolder.isMountPoint()) {
2209                                    toRepository = getRepository(toFolder.getRepositoryId());
2210                            }
2211                    }
2212    
2213                    if (fromRepository.getRepositoryId() ==
2214                                    toRepository.getRepositoryId()) {
2215    
2216                            // Move file entries within repository
2217    
2218                            return fromRepository.moveFileEntry(
2219                                    getUserId(), fileEntryId, newFolderId, serviceContext);
2220                    }
2221    
2222                    // Move file entries between repositories
2223    
2224                    return moveFileEntries(
2225                            fileEntryId, newFolderId, fromRepository, toRepository,
2226                            serviceContext);
2227            }
2228    
2229            /**
2230             * Moves the file entry from a trashed folder to the new folder.
2231             *
2232             * @param  fileEntryId the primary key of the file entry
2233             * @param  newFolderId the primary key of the new folder
2234             * @param  serviceContext the service context to be applied
2235             * @return the file entry
2236             * @throws PortalException if the file entry or the new folder could not be
2237             *         found
2238             */
2239            @Override
2240            public FileEntry moveFileEntryFromTrash(
2241                            long fileEntryId, long newFolderId, ServiceContext serviceContext)
2242                    throws PortalException {
2243    
2244                    Repository repository = getFileEntryRepository(fileEntryId);
2245    
2246                    if (!repository.isCapabilityProvided(TrashCapability.class)) {
2247                            throw new InvalidRepositoryException(
2248                                    "Repository " + repository.getRepositoryId() +
2249                                            " does not support trash operations");
2250                    }
2251    
2252                    FileEntry fileEntry = repository.getFileEntry(fileEntryId);
2253    
2254                    DLFileEntryPermission.check(
2255                            getPermissionChecker(), fileEntry, ActionKeys.UPDATE);
2256    
2257                    TrashCapability trashCapability = repository.getCapability(
2258                            TrashCapability.class);
2259    
2260                    Folder destinationFolder = repository.getFolder(newFolderId);
2261    
2262                    return trashCapability.moveFileEntryFromTrash(
2263                            getUserId(), fileEntry, destinationFolder, serviceContext);
2264            }
2265    
2266            /**
2267             * Moves the file entry with the primary key to the trash portlet.
2268             *
2269             * @param  fileEntryId the primary key of the file entry
2270             * @return the file entry
2271             * @throws PortalException if the file entry could not be found
2272             */
2273            @Override
2274            public FileEntry moveFileEntryToTrash(long fileEntryId)
2275                    throws PortalException {
2276    
2277                    Repository repository = getFileEntryRepository(fileEntryId);
2278    
2279                    if (!repository.isCapabilityProvided(TrashCapability.class)) {
2280                            throw new InvalidRepositoryException(
2281                                    "Repository " + repository.getRepositoryId() +
2282                                            " does not support trash operations");
2283                    }
2284    
2285                    FileEntry fileEntry = repository.getFileEntry(fileEntryId);
2286    
2287                    DLFileEntryPermission.check(
2288                            getPermissionChecker(), fileEntry, ActionKeys.DELETE);
2289    
2290                    TrashCapability trashCapability = repository.getCapability(
2291                            TrashCapability.class);
2292    
2293                    return trashCapability.moveFileEntryToTrash(getUserId(), fileEntry);
2294            }
2295    
2296            /**
2297             * Moves the file shortcut from a trashed folder to the new folder.
2298             *
2299             * @param  fileShortcutId the primary key of the file shortcut
2300             * @param  newFolderId the primary key of the new folder
2301             * @param  serviceContext the service context to be applied
2302             * @return the file shortcut
2303             * @throws PortalException if the file entry or the new folder could not be
2304             *         found
2305             */
2306            @Override
2307            public DLFileShortcut moveFileShortcutFromTrash(
2308                            long fileShortcutId, long newFolderId,
2309                            ServiceContext serviceContext)
2310                    throws PortalException {
2311    
2312                    DLFileShortcut fileShortcut = getFileShortcut(fileShortcutId);
2313    
2314                    DLFileShortcutPermission.check(
2315                            getPermissionChecker(), fileShortcut, ActionKeys.UPDATE);
2316    
2317                    return dlAppHelperLocalService.moveFileShortcutFromTrash(
2318                            getUserId(), fileShortcut, newFolderId, serviceContext);
2319            }
2320    
2321            /**
2322             * Moves the file shortcut with the primary key to the trash portlet.
2323             *
2324             * @param  fileShortcutId the primary key of the file shortcut
2325             * @return the file shortcut
2326             * @throws PortalException if the file shortcut could not be found
2327             */
2328            @Override
2329            public DLFileShortcut moveFileShortcutToTrash(long fileShortcutId)
2330                    throws PortalException {
2331    
2332                    DLFileShortcut fileShortcut = getFileShortcut(fileShortcutId);
2333    
2334                    DLFileShortcutPermission.check(
2335                            getPermissionChecker(), fileShortcut, ActionKeys.DELETE);
2336    
2337                    return dlAppHelperLocalService.moveFileShortcutToTrash(
2338                            getUserId(), fileShortcut);
2339            }
2340    
2341            /**
2342             * Moves the folder to the new parent folder with the primary key.
2343             *
2344             * @param  folderId the primary key of the folder
2345             * @param  parentFolderId the primary key of the new parent folder
2346             * @param  serviceContext the service context to be applied
2347             * @return the file entry
2348             * @throws PortalException if the folder could not be found
2349             */
2350            @Override
2351            public Folder moveFolder(
2352                            long folderId, long parentFolderId, ServiceContext serviceContext)
2353                    throws PortalException {
2354    
2355                    Repository fromRepository = getFolderRepository(folderId);
2356                    Repository toRepository = getFolderRepository(
2357                            parentFolderId, serviceContext.getScopeGroupId());
2358    
2359                    if (parentFolderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
2360                            Folder toFolder = toRepository.getFolder(parentFolderId);
2361    
2362                            if (toFolder.isMountPoint()) {
2363                                    toRepository = getRepository(toFolder.getRepositoryId());
2364                            }
2365                    }
2366    
2367                    if (fromRepository.getRepositoryId() ==
2368                                    toRepository.getRepositoryId()) {
2369    
2370                            // Move file entries within repository
2371    
2372                            return fromRepository.moveFolder(
2373                                    getUserId(), folderId, parentFolderId, serviceContext);
2374                    }
2375    
2376                    // Move file entries between repositories
2377    
2378                    return moveFolders(
2379                            folderId, parentFolderId, fromRepository, toRepository,
2380                            serviceContext);
2381            }
2382    
2383            /**
2384             * Moves the folder with the primary key from the trash portlet to the new
2385             * parent folder with the primary key.
2386             *
2387             * @param  folderId the primary key of the folder
2388             * @param  parentFolderId the primary key of the new parent folder
2389             * @param  serviceContext the service context to be applied
2390             * @return the file entry
2391             * @throws PortalException if the folder could not be found
2392             */
2393            @Override
2394            public Folder moveFolderFromTrash(
2395                            long folderId, long parentFolderId, ServiceContext serviceContext)
2396                    throws PortalException {
2397    
2398                    Repository repository = getFolderRepository(folderId);
2399    
2400                    if (!repository.isCapabilityProvided(TrashCapability.class)) {
2401                            throw new InvalidRepositoryException(
2402                                    "Repository " + repository.getRepositoryId() +
2403                                            " does not support trash operations");
2404                    }
2405    
2406                    Folder folder = repository.getFolder(folderId);
2407    
2408                    DLFolderPermission.check(
2409                            getPermissionChecker(), folder, ActionKeys.UPDATE);
2410    
2411                    TrashCapability trashCapability = repository.getCapability(
2412                            TrashCapability.class);
2413    
2414                    Folder destinationFolder = null;
2415    
2416                    if (parentFolderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
2417                            destinationFolder = repository.getFolder(parentFolderId);
2418                    }
2419    
2420                    return trashCapability.moveFolderFromTrash(
2421                            getUserId(), folder, destinationFolder, serviceContext);
2422            }
2423    
2424            /**
2425             * Moves the folder with the primary key to the trash portlet.
2426             *
2427             * @param  folderId the primary key of the folder
2428             * @return the file entry
2429             * @throws PortalException if the folder could not be found
2430             */
2431            @Override
2432            public Folder moveFolderToTrash(long folderId) throws PortalException {
2433                    Repository repository = getFolderRepository(folderId);
2434    
2435                    if (!repository.isCapabilityProvided(TrashCapability.class)) {
2436                            throw new InvalidRepositoryException(
2437                                    "Repository " + repository.getRepositoryId() +
2438                                            " does not support trash operations");
2439                    }
2440    
2441                    Folder folder = repository.getFolder(folderId);
2442    
2443                    DLFolderPermission.check(
2444                            getPermissionChecker(), folder, ActionKeys.DELETE);
2445    
2446                    TrashCapability trashCapability = repository.getCapability(
2447                            TrashCapability.class);
2448    
2449                    return trashCapability.moveFolderToTrash(getUserId(), folder);
2450            }
2451    
2452            /**
2453             * Refreshes the lock for the file entry. This method is primarily used by
2454             * WebDAV.
2455             *
2456             * @param  lockUuid the lock's UUID
2457             * @param  companyId the primary key of the file entry's company
2458             * @param  expirationTime the time in milliseconds before the lock expires.
2459             *         If the value is <code>0</code>, the default expiration time will
2460             *         be used from <code>portal.properties>.
2461             * @return the lock object
2462             * @throws PortalException if the file entry or lock could not be found
2463             */
2464            @Override
2465            public Lock refreshFileEntryLock(
2466                            String lockUuid, long companyId, long expirationTime)
2467                    throws PortalException {
2468    
2469                    Lock lock = lockLocalService.getLockByUuidAndCompanyId(
2470                            lockUuid, companyId);
2471    
2472                    long fileEntryId = GetterUtil.getLong(lock.getKey());
2473    
2474                    Repository repository = getFileEntryRepository(fileEntryId);
2475    
2476                    return repository.refreshFileEntryLock(
2477                            lockUuid, companyId, expirationTime);
2478            }
2479    
2480            /**
2481             * Refreshes the lock for the folder. This method is primarily used by
2482             * WebDAV.
2483             *
2484             * @param  lockUuid the lock's UUID
2485             * @param  companyId the primary key of the file entry's company
2486             * @param  expirationTime the time in milliseconds before the lock expires.
2487             *         If the value is <code>0</code>, the default expiration time will
2488             *         be used from <code>portal.properties>.
2489             * @return the lock object
2490             * @throws PortalException if the folder or lock could not be found
2491             */
2492            @Override
2493            public Lock refreshFolderLock(
2494                            String lockUuid, long companyId, long expirationTime)
2495                    throws PortalException {
2496    
2497                    Lock lock = lockLocalService.getLockByUuidAndCompanyId(
2498                            lockUuid, companyId);
2499    
2500                    long folderId = GetterUtil.getLong(lock.getKey());
2501    
2502                    Repository repository = getFolderRepository(folderId);
2503    
2504                    return repository.refreshFolderLock(
2505                            lockUuid, companyId, expirationTime);
2506            }
2507    
2508            /**
2509             * Restores the file entry with the primary key from the trash portlet.
2510             *
2511             * @param  fileEntryId the primary key of the file entry
2512             * @throws PortalException if the file entry could not be found
2513             */
2514            @Override
2515            public void restoreFileEntryFromTrash(long fileEntryId)
2516                    throws PortalException {
2517    
2518                    Repository repository = getFileEntryRepository(fileEntryId);
2519    
2520                    if (!repository.isCapabilityProvided(TrashCapability.class)) {
2521                            throw new InvalidRepositoryException(
2522                                    "Repository " + repository.getRepositoryId() +
2523                                            " does not support trash operations");
2524                    }
2525    
2526                    FileEntry fileEntry = repository.getFileEntry(fileEntryId);
2527    
2528                    DLFileEntryPermission.check(
2529                            getPermissionChecker(), fileEntry, ActionKeys.DELETE);
2530    
2531                    TrashCapability trashCapability = repository.getCapability(
2532                            TrashCapability.class);
2533    
2534                    trashCapability.restoreFileEntryFromTrash(getUserId(), fileEntry);
2535            }
2536    
2537            /**
2538             * Restores the file shortcut with the primary key from the trash portlet.
2539             *
2540             * @param  fileShortcutId the primary key of the file shortcut
2541             * @throws PortalException if the file shortcut could not be found
2542             */
2543            @Override
2544            public void restoreFileShortcutFromTrash(long fileShortcutId)
2545                    throws PortalException {
2546    
2547                    DLFileShortcut fileShortcut = getFileShortcut(fileShortcutId);
2548    
2549                    DLFileShortcutPermission.check(
2550                            getPermissionChecker(), fileShortcut, ActionKeys.DELETE);
2551    
2552                    dlAppHelperLocalService.restoreFileShortcutFromTrash(
2553                            getUserId(), fileShortcut);
2554            }
2555    
2556            /**
2557             * Restores the folder with the primary key from the trash portlet.
2558             *
2559             * @param  folderId the primary key of the folder
2560             * @throws PortalException if the folder could not be found
2561             */
2562            @Override
2563            public void restoreFolderFromTrash(long folderId) throws PortalException {
2564                    Repository repository = getFolderRepository(folderId);
2565    
2566                    if (!repository.isCapabilityProvided(TrashCapability.class)) {
2567                            throw new InvalidRepositoryException(
2568                                    "Repository " + repository.getRepositoryId() +
2569                                            " does not support trash operations");
2570                    }
2571    
2572                    Folder folder = repository.getFolder(folderId);
2573    
2574                    DLFolderPermission.check(
2575                            getPermissionChecker(), folder, ActionKeys.DELETE);
2576    
2577                    TrashCapability trashCapability = repository.getCapability(
2578                            TrashCapability.class);
2579    
2580                    trashCapability.restoreFolderFromTrash(getUserId(), folder);
2581            }
2582    
2583            /**
2584             * Reverts the file entry to a previous version. A new version will be
2585             * created based on the previous version and metadata.
2586             *
2587             * @param  fileEntryId the primary key of the file entry
2588             * @param  version the version to revert back to
2589             * @param  serviceContext the service context to be applied
2590             * @throws PortalException if the file entry or version could not be found
2591             */
2592            @Override
2593            public void revertFileEntry(
2594                            long fileEntryId, String version, ServiceContext serviceContext)
2595                    throws PortalException {
2596    
2597                    Repository repository = getFileEntryRepository(fileEntryId);
2598    
2599                    repository.revertFileEntry(
2600                            getUserId(), fileEntryId, version, serviceContext);
2601    
2602                    FileEntry fileEntry = getFileEntry(fileEntryId);
2603    
2604                    dlAppHelperLocalService.updateFileEntry(
2605                            getUserId(), fileEntry, fileEntry.getFileVersion(version),
2606                            fileEntry.getFileVersion(), serviceContext);
2607            }
2608    
2609            @Override
2610            public Hits search(
2611                            long repositoryId, long creatorUserId, int status, int start,
2612                            int end)
2613                    throws PortalException {
2614    
2615                    Repository repository = getRepository(repositoryId);
2616    
2617                    return repository.search(creatorUserId, status, start, end);
2618            }
2619    
2620            @Override
2621            public Hits search(
2622                            long repositoryId, long creatorUserId, long folderId,
2623                            String[] mimeTypes, int status, int start, int end)
2624                    throws PortalException {
2625    
2626                    Repository repository = getRepository(repositoryId);
2627    
2628                    return repository.search(
2629                            creatorUserId, folderId, mimeTypes, status, start, end);
2630            }
2631    
2632            @Override
2633            public Hits search(long repositoryId, SearchContext searchContext)
2634                    throws SearchException {
2635    
2636                    try {
2637                            Repository repository = getRepository(repositoryId);
2638    
2639                            return repository.search(searchContext);
2640                    }
2641                    catch (Exception e) {
2642                            throw new SearchException(e);
2643                    }
2644            }
2645    
2646            @Override
2647            public Hits search(
2648                            long repositoryId, SearchContext searchContext, Query query)
2649                    throws SearchException {
2650    
2651                    try {
2652                            Repository repository = getRepository(repositoryId);
2653    
2654                            return repository.search(searchContext, query);
2655                    }
2656                    catch (Exception e) {
2657                            throw new SearchException(e);
2658                    }
2659            }
2660    
2661            /**
2662             * Subscribe the user to changes in documents of the file entry type. This
2663             * method is only supported by the Liferay repository.
2664             *
2665             * @param  groupId the primary key of the file entry type's group
2666             * @param  fileEntryTypeId the primary key of the file entry type
2667             * @throws PortalException if the user or group could not be found, or if
2668             *         subscribing was not permissible
2669             */
2670            @Override
2671            public void subscribeFileEntryType(long groupId, long fileEntryTypeId)
2672                    throws PortalException {
2673    
2674                    DLPermission.check(
2675                            getPermissionChecker(), groupId, ActionKeys.SUBSCRIBE);
2676    
2677                    dlAppLocalService.subscribeFileEntryType(
2678                            getUserId(), groupId, fileEntryTypeId);
2679            }
2680    
2681            /**
2682             * Subscribe the user to document changes in the folder. This method is only
2683             * supported by the Liferay repository.
2684             *
2685             * @param  groupId the primary key of the folder's group
2686             * @param  folderId the primary key of the folder
2687             * @throws PortalException if the user or group could not be found, or if
2688             *         subscribing was not permissible
2689             */
2690            @Override
2691            public void subscribeFolder(long groupId, long folderId)
2692                    throws PortalException {
2693    
2694                    DLFolderPermission.check(
2695                            getPermissionChecker(), groupId, folderId, ActionKeys.SUBSCRIBE);
2696    
2697                    dlAppLocalService.subscribeFolder(getUserId(), groupId, folderId);
2698            }
2699    
2700            /**
2701             * @deprecated As of 6.2.0, replaced by {@link #checkInFileEntry(long,
2702             *             boolean, String, ServiceContext)}.
2703             */
2704            @Deprecated
2705            @Override
2706            public void unlockFileEntry(long fileEntryId) throws PortalException {
2707                    checkInFileEntry(
2708                            fileEntryId, false, StringPool.BLANK, new ServiceContext());
2709            }
2710    
2711            /**
2712             * @deprecated As of 6.2.0, replaced by {@link #checkInFileEntry(long,
2713             *             String)}.
2714             */
2715            @Deprecated
2716            @Override
2717            public void unlockFileEntry(long fileEntryId, String lockUuid)
2718                    throws PortalException {
2719    
2720                    checkInFileEntry(fileEntryId, lockUuid);
2721            }
2722    
2723            /**
2724             * Unlocks the folder. This method is primarily used by WebDAV.
2725             *
2726             * @param  repositoryId the primary key of the repository
2727             * @param  folderId the primary key of the folder
2728             * @param  lockUuid the lock's UUID
2729             * @throws PortalException if the repository or folder could not be found
2730             */
2731            @Override
2732            public void unlockFolder(long repositoryId, long folderId, String lockUuid)
2733                    throws PortalException {
2734    
2735                    Repository repository = getRepository(repositoryId);
2736    
2737                    repository.unlockFolder(folderId, lockUuid);
2738            }
2739    
2740            /**
2741             * Unlocks the folder. This method is primarily used by WebDAV.
2742             *
2743             * @param  repositoryId the primary key of the repository
2744             * @param  parentFolderId the primary key of the parent folder
2745             * @param  name the folder's name
2746             * @param  lockUuid the lock's UUID
2747             * @throws PortalException if the repository or folder could not be found
2748             */
2749            @Override
2750            public void unlockFolder(
2751                            long repositoryId, long parentFolderId, String name,
2752                            String lockUuid)
2753                    throws PortalException {
2754    
2755                    Repository repository = getRepository(repositoryId);
2756    
2757                    repository.unlockFolder(parentFolderId, name, lockUuid);
2758            }
2759    
2760            /**
2761             * Unsubscribe the user from changes in documents of the file entry type.
2762             * This method is only supported by the Liferay repository.
2763             *
2764             * @param  groupId the primary key of the file entry type's group
2765             * @param  fileEntryTypeId the primary key of the file entry type
2766             * @throws PortalException if the user or group could not be found, or if
2767             *         unsubscribing was not permissible
2768             */
2769            @Override
2770            public void unsubscribeFileEntryType(long groupId, long fileEntryTypeId)
2771                    throws PortalException {
2772    
2773                    DLPermission.check(
2774                            getPermissionChecker(), groupId, ActionKeys.SUBSCRIBE);
2775    
2776                    dlAppLocalService.unsubscribeFileEntryType(
2777                            getUserId(), groupId, fileEntryTypeId);
2778            }
2779    
2780            /**
2781             * Unsubscribe the user from document changes in the folder. This method is
2782             * only supported by the Liferay repository.
2783             *
2784             * @param  groupId the primary key of the folder's group
2785             * @param  folderId the primary key of the folder
2786             * @throws PortalException if the user or group could not be found, or if
2787             *         unsubscribing was not permissible
2788             */
2789            @Override
2790            public void unsubscribeFolder(long groupId, long folderId)
2791                    throws PortalException {
2792    
2793                    DLFolderPermission.check(
2794                            getPermissionChecker(), groupId, folderId, ActionKeys.SUBSCRIBE);
2795    
2796                    dlAppLocalService.unsubscribeFolder(getUserId(), groupId, folderId);
2797            }
2798    
2799            /**
2800             * Updates a file entry and associated metadata based on a byte array
2801             * object. If the file data is <code>null</code>, then only the associated
2802             * metadata (i.e., <code>title</code>, <code>description</code>, and
2803             * parameters in the <code>serviceContext</code>) will be updated.
2804             *
2805             * <p>
2806             * This method takes two file names, the <code>sourceFileName</code> and the
2807             * <code>title</code>. The <code>sourceFileName</code> corresponds to the
2808             * name of the actual file being uploaded. The <code>title</code>
2809             * corresponds to a name the client wishes to assign this file after it has
2810             * been uploaded to the portal.
2811             * </p>
2812             *
2813             * @param  fileEntryId the primary key of the file entry
2814             * @param  sourceFileName the original file's name (optionally
2815             *         <code>null</code>)
2816             * @param  mimeType the file's MIME type (optionally <code>null</code>)
2817             * @param  title the new name to be assigned to the file (optionally <code>
2818             *         <code>null</code></code>)
2819             * @param  description the file's new description
2820             * @param  changeLog the file's version change log (optionally
2821             *         <code>null</code>)
2822             * @param  majorVersion whether the new file version is a major version
2823             * @param  bytes the file's data (optionally <code>null</code>)
2824             * @param  serviceContext the service context to be applied. Can set the
2825             *         asset category IDs, asset tag names, and expando bridge
2826             *         attributes for the file entry. In a Liferay repository, it may
2827             *         include:  <ul> <li> fileEntryTypeId - ID for a custom file entry
2828             *         type </li> <li> fieldsMap - mapping for fields associated with a
2829             *         custom file entry type </li> </ul>
2830             * @return the file entry
2831             * @throws PortalException if the file entry could not be found
2832             */
2833            @Override
2834            public FileEntry updateFileEntry(
2835                            long fileEntryId, String sourceFileName, String mimeType,
2836                            String title, String description, String changeLog,
2837                            boolean majorVersion, byte[] bytes, ServiceContext serviceContext)
2838                    throws PortalException {
2839    
2840                    File file = null;
2841    
2842                    try {
2843                            if (ArrayUtil.isNotEmpty(bytes)) {
2844                                    file = FileUtil.createTempFile(bytes);
2845                            }
2846    
2847                            return updateFileEntry(
2848                                    fileEntryId, sourceFileName, mimeType, title, description,
2849                                    changeLog, majorVersion, file, serviceContext);
2850                    }
2851                    catch (IOException ioe) {
2852                            throw new SystemException("Unable to write temporary file", ioe);
2853                    }
2854                    finally {
2855                            FileUtil.delete(file);
2856                    }
2857            }
2858    
2859            /**
2860             * Updates a file entry and associated metadata based on a {@link
2861             * java.io.File} object. If the file data is <code>null</code>, then only
2862             * the associated metadata (i.e., <code>title</code>,
2863             * <code>description</code>, and parameters in the
2864             * <code>serviceContext</code>) will be updated.
2865             *
2866             * <p>
2867             * This method takes two file names, the <code>sourceFileName</code> and the
2868             * <code>title</code>. The <code>sourceFileName</code> corresponds to the
2869             * name of the actual file being uploaded. The <code>title</code>
2870             * corresponds to a name the client wishes to assign this file after it has
2871             * been uploaded to the portal.
2872             * </p>
2873             *
2874             * @param  fileEntryId the primary key of the file entry
2875             * @param  sourceFileName the original file's name (optionally
2876             *         <code>null</code>)
2877             * @param  mimeType the file's MIME type (optionally <code>null</code>)
2878             * @param  title the new name to be assigned to the file (optionally <code>
2879             *         <code>null</code></code>)
2880             * @param  description the file's new description
2881             * @param  changeLog the file's version change log (optionally
2882             *         <code>null</code>)
2883             * @param  majorVersion whether the new file version is a major version
2884             * @param  file the file's data (optionally <code>null</code>)
2885             * @param  serviceContext the service context to be applied. Can set the
2886             *         asset category IDs, asset tag names, and expando bridge
2887             *         attributes for the file entry. In a Liferay repository, it may
2888             *         include:  <ul> <li> fileEntryTypeId - ID for a custom file entry
2889             *         type </li> <li> fieldsMap - mapping for fields associated with a
2890             *         custom file entry type </li> </ul>
2891             * @return the file entry
2892             * @throws PortalException if the file entry could not be found
2893             */
2894            @Override
2895            public FileEntry updateFileEntry(
2896                            long fileEntryId, String sourceFileName, String mimeType,
2897                            String title, String description, String changeLog,
2898                            boolean majorVersion, File file, ServiceContext serviceContext)
2899                    throws PortalException {
2900    
2901                    if ((file == null) || !file.exists() || (file.length() == 0)) {
2902                            return updateFileEntry(
2903                                    fileEntryId, sourceFileName, mimeType, title, description,
2904                                    changeLog, majorVersion, null, 0, serviceContext);
2905                    }
2906    
2907                    mimeType = DLAppUtil.getMimeType(sourceFileName, mimeType, title, file);
2908    
2909                    Repository repository = getFileEntryRepository(fileEntryId);
2910    
2911                    FileEntry fileEntry = repository.updateFileEntry(
2912                            getUserId(), fileEntryId, sourceFileName, mimeType, title,
2913                            description, changeLog, majorVersion, file, serviceContext);
2914    
2915                    DLProcessorRegistryUtil.cleanUp(fileEntry.getLatestFileVersion());
2916    
2917                    dlAppHelperLocalService.updateFileEntry(
2918                            getUserId(), fileEntry, null, fileEntry.getFileVersion(),
2919                            serviceContext);
2920    
2921                    return fileEntry;
2922            }
2923    
2924            /**
2925             * Updates a file entry and associated metadata based on an {@link
2926             * InputStream} object. If the file data is <code>null</code>, then only the
2927             * associated metadata (i.e., <code>title</code>, <code>description</code>,
2928             * and parameters in the <code>serviceContext</code>) will be updated.
2929             *
2930             * <p>
2931             * This method takes two file names, the <code>sourceFileName</code> and the
2932             * <code>title</code>. The <code>sourceFileName</code> corresponds to the
2933             * name of the actual file being uploaded. The <code>title</code>
2934             * corresponds to a name the client wishes to assign this file after it has
2935             * been uploaded to the portal.
2936             * </p>
2937             *
2938             * @param  fileEntryId the primary key of the file entry
2939             * @param  sourceFileName the original file's name (optionally
2940             *         <code>null</code>)
2941             * @param  mimeType the file's MIME type (optionally <code>null</code>)
2942             * @param  title the new name to be assigned to the file (optionally <code>
2943             *         <code>null</code></code>)
2944             * @param  description the file's new description
2945             * @param  changeLog the file's version change log (optionally
2946             *         <code>null</code>)
2947             * @param  majorVersion whether the new file version is a major version
2948             * @param  is the file's data (optionally <code>null</code>)
2949             * @param  size the file's size (optionally <code>0</code>)
2950             * @param  serviceContext the service context to be applied. Can set the
2951             *         asset category IDs, asset tag names, and expando bridge
2952             *         attributes for the file entry. In a Liferay repository, it may
2953             *         include:  <ul> <li> fileEntryTypeId - ID for a custom file entry
2954             *         type </li> <li> fieldsMap - mapping for fields associated with a
2955             *         custom file entry type </li> </ul>
2956             * @return the file entry
2957             * @throws PortalException if the file entry could not be found
2958             */
2959            @Override
2960            public FileEntry updateFileEntry(
2961                            long fileEntryId, String sourceFileName, String mimeType,
2962                            String title, String description, String changeLog,
2963                            boolean majorVersion, InputStream is, long size,
2964                            ServiceContext serviceContext)
2965                    throws PortalException {
2966    
2967                    if (Validator.isNull(mimeType) ||
2968                            mimeType.equals(ContentTypes.APPLICATION_OCTET_STREAM)) {
2969    
2970                            String extension = DLAppUtil.getExtension(title, sourceFileName);
2971    
2972                            if (size == 0) {
2973                                    mimeType = MimeTypesUtil.getExtensionContentType(extension);
2974                            }
2975                            else {
2976                                    File file = null;
2977    
2978                                    try {
2979                                            file = FileUtil.createTempFile(is);
2980    
2981                                            return updateFileEntry(
2982                                                    fileEntryId, sourceFileName, mimeType, title,
2983                                                    description, changeLog, majorVersion, file,
2984                                                    serviceContext);
2985                                    }
2986                                    catch (IOException ioe) {
2987                                            throw new SystemException(
2988                                                    "Unable to write temporary file", ioe);
2989                                    }
2990                                    finally {
2991                                            FileUtil.delete(file);
2992                                    }
2993                            }
2994                    }
2995    
2996                    Repository repository = getFileEntryRepository(fileEntryId);
2997    
2998                    FileEntry oldFileEntry = repository.getFileEntry(fileEntryId);
2999    
3000                    FileVersion oldFileVersion = oldFileEntry.getFileVersion();
3001    
3002                    FileEntry fileEntry = repository.updateFileEntry(
3003                            getUserId(), fileEntryId, sourceFileName, mimeType, title,
3004                            description, changeLog, majorVersion, is, size, serviceContext);
3005    
3006                    if (is != null) {
3007                            DLProcessorRegistryUtil.cleanUp(fileEntry.getLatestFileVersion());
3008    
3009                            oldFileVersion = null;
3010                    }
3011    
3012                    dlAppHelperLocalService.updateFileEntry(
3013                            getUserId(), fileEntry, oldFileVersion, fileEntry.getFileVersion(),
3014                            serviceContext);
3015    
3016                    return fileEntry;
3017            }
3018    
3019            @Override
3020            public FileEntry updateFileEntryAndCheckIn(
3021                            long fileEntryId, String sourceFileName, String mimeType,
3022                            String title, String description, String changeLog,
3023                            boolean majorVersion, File file, ServiceContext serviceContext)
3024                    throws PortalException {
3025    
3026                    if ((file == null) || !file.exists() || (file.length() == 0)) {
3027                            return updateFileEntryAndCheckIn(
3028                                    fileEntryId, sourceFileName, mimeType, title, description,
3029                                    changeLog, majorVersion, null, 0, serviceContext);
3030                    }
3031    
3032                    Repository repository = getFileEntryRepository(fileEntryId);
3033    
3034                    FileEntry fileEntry = repository.updateFileEntry(
3035                            getUserId(), fileEntryId, sourceFileName, mimeType, title,
3036                            description, changeLog, majorVersion, file, serviceContext);
3037    
3038                    DLProcessorRegistryUtil.cleanUp(fileEntry.getLatestFileVersion());
3039    
3040                    repository.checkInFileEntry(
3041                            getUserId(), fileEntryId, majorVersion, changeLog, serviceContext);
3042    
3043                    dlAppHelperLocalService.updateFileEntry(
3044                            getUserId(), fileEntry, null, fileEntry.getFileVersion(),
3045                            serviceContext);
3046    
3047                    return fileEntry;
3048            }
3049    
3050            @Override
3051            public FileEntry updateFileEntryAndCheckIn(
3052                            long fileEntryId, String sourceFileName, String mimeType,
3053                            String title, String description, String changeLog,
3054                            boolean majorVersion, InputStream is, long size,
3055                            ServiceContext serviceContext)
3056                    throws PortalException {
3057    
3058                    Repository repository = getFileEntryRepository(fileEntryId);
3059    
3060                    FileEntry oldFileEntry = repository.getFileEntry(fileEntryId);
3061    
3062                    FileVersion oldFileVersion = oldFileEntry.getFileVersion();
3063    
3064                    FileEntry fileEntry = repository.updateFileEntry(
3065                            getUserId(), fileEntryId, sourceFileName, mimeType, title,
3066                            description, changeLog, majorVersion, is, size, serviceContext);
3067    
3068                    if (is != null) {
3069                            DLProcessorRegistryUtil.cleanUp(fileEntry.getLatestFileVersion());
3070    
3071                            oldFileVersion = null;
3072                    }
3073    
3074                    repository.checkInFileEntry(
3075                            getUserId(), fileEntryId, majorVersion, changeLog, serviceContext);
3076    
3077                    dlAppHelperLocalService.updateFileEntry(
3078                            getUserId(), fileEntry, oldFileVersion, fileEntry.getFileVersion(),
3079                            serviceContext);
3080    
3081                    return fileEntry;
3082            }
3083    
3084            /**
3085             * Updates a file shortcut to the existing file entry. This method is only
3086             * supported by the Liferay repository.
3087             *
3088             * @param  fileShortcutId the primary key of the file shortcut
3089             * @param  folderId the primary key of the file shortcut's parent folder
3090             * @param  toFileEntryId the primary key of the file shortcut's file entry
3091             * @param  serviceContext the service context to be applied. Can set the
3092             *         asset category IDs, asset tag names, and expando bridge
3093             *         attributes for the file entry.
3094             * @return the file shortcut
3095             * @throws PortalException if the file shortcut, folder, or file entry could
3096             *         not be found
3097             */
3098            @Override
3099            public DLFileShortcut updateFileShortcut(
3100                            long fileShortcutId, long folderId, long toFileEntryId,
3101                            ServiceContext serviceContext)
3102                    throws PortalException {
3103    
3104                    return dlFileShortcutService.updateFileShortcut(
3105                            fileShortcutId, folderId, toFileEntryId, serviceContext);
3106            }
3107    
3108            /**
3109             * Updates the folder.
3110             *
3111             * @param  folderId the primary key of the folder
3112             * @param  name the folder's new name
3113             * @param  description the folder's new description
3114             * @param  serviceContext the service context to be applied. In a Liferay
3115             *         repository, it may include:  <ul> <li> defaultFileEntryTypeId -
3116             *         the file entry type to default all Liferay file entries to </li>
3117             *         <li> dlFileEntryTypesSearchContainerPrimaryKeys - a
3118             *         comma-delimited list of file entry type primary keys allowed in
3119             *         the given folder and all descendants </li> <li> restrictionType -
3120             *         specifying restriction type of file entry types allowed </li>
3121             *         <li> workflowDefinitionXYZ - the workflow definition name
3122             *         specified per file entry type. The parameter name must be the
3123             *         string <code>workflowDefinition</code> appended by the
3124             *         <code>fileEntryTypeId</code> (optionally <code>0</code>).</li>
3125             *         </ul>
3126             * @return the folder
3127             * @throws PortalException if the current or new parent folder could not be
3128             *         found or if the new parent folder's information was invalid
3129             */
3130            @Override
3131            public Folder updateFolder(
3132                            long folderId, String name, String description,
3133                            ServiceContext serviceContext)
3134                    throws PortalException {
3135    
3136                    Repository repository = getFolderRepository(
3137                            folderId, serviceContext.getScopeGroupId());
3138    
3139                    Folder folder = repository.updateFolder(
3140                            folderId, name, description, serviceContext);
3141    
3142                    if (folderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
3143                            dlAppHelperLocalService.updateFolder(
3144                                    getUserId(), folder, serviceContext);
3145                    }
3146    
3147                    return folder;
3148            }
3149    
3150            /**
3151             * Returns <code>true</code> if the file entry is checked out. This method
3152             * is primarily used by WebDAV.
3153             *
3154             * @param  repositoryId the primary key for the repository
3155             * @param  fileEntryId the primary key for the file entry
3156             * @param  lockUuid the lock's UUID
3157             * @return <code>true</code> if the file entry is checked out;
3158             *         <code>false</code> otherwise
3159             * @throws PortalException if the file entry could not be found
3160             */
3161            @Override
3162            public boolean verifyFileEntryCheckOut(
3163                            long repositoryId, long fileEntryId, String lockUuid)
3164                    throws PortalException {
3165    
3166                    Repository repository = getRepository(repositoryId);
3167    
3168                    return repository.verifyFileEntryCheckOut(fileEntryId, lockUuid);
3169            }
3170    
3171            @Override
3172            public boolean verifyFileEntryLock(
3173                            long repositoryId, long fileEntryId, String lockUuid)
3174                    throws PortalException {
3175    
3176                    Repository repository = getRepository(repositoryId);
3177    
3178                    return repository.verifyFileEntryLock(fileEntryId, lockUuid);
3179            }
3180    
3181            /**
3182             * Returns <code>true</code> if the inheritable lock exists. This method is
3183             * primarily used by WebDAV.
3184             *
3185             * @param  repositoryId the primary key for the repository
3186             * @param  folderId the primary key for the folder
3187             * @param  lockUuid the lock's UUID
3188             * @return <code>true</code> if the inheritable lock exists;
3189             *         <code>false</code> otherwise
3190             * @throws PortalException if the folder could not be found
3191             */
3192            @Override
3193            public boolean verifyInheritableLock(
3194                            long repositoryId, long folderId, String lockUuid)
3195                    throws PortalException {
3196    
3197                    Repository repository = getRepository(repositoryId);
3198    
3199                    return repository.verifyInheritableLock(folderId, lockUuid);
3200            }
3201    
3202            protected FileEntry copyFileEntry(
3203                            Repository toRepository, FileEntry fileEntry, long newFolderId,
3204                            ServiceContext serviceContext)
3205                    throws PortalException {
3206    
3207                    List<FileVersion> fileVersions = fileEntry.getFileVersions(
3208                            WorkflowConstants.STATUS_ANY);
3209    
3210                    FileVersion latestFileVersion = fileVersions.get(
3211                            fileVersions.size() - 1);
3212    
3213                    FileEntry destinationFileEntry = toRepository.addFileEntry(
3214                            getUserId(), newFolderId, fileEntry.getTitle(),
3215                            latestFileVersion.getMimeType(), latestFileVersion.getTitle(),
3216                            latestFileVersion.getDescription(), StringPool.BLANK,
3217                            latestFileVersion.getContentStream(false),
3218                            latestFileVersion.getSize(), serviceContext);
3219    
3220                    FileVersion oldDestinationFileVersion =
3221                            destinationFileEntry.getFileVersion();
3222    
3223                    dlAppHelperLocalService.addFileEntry(
3224                            getUserId(), destinationFileEntry, oldDestinationFileVersion,
3225                            serviceContext);
3226    
3227                    for (int i = fileVersions.size() - 2; i >= 0; i--) {
3228                            FileVersion fileVersion = fileVersions.get(i);
3229    
3230                            FileVersion previousFileVersion = fileVersions.get(i + 1);
3231    
3232                            try {
3233                                    destinationFileEntry = toRepository.updateFileEntry(
3234                                            getUserId(), destinationFileEntry.getFileEntryId(),
3235                                            fileVersion.getTitle(), fileVersion.getMimeType(),
3236                                            fileVersion.getTitle(), fileVersion.getDescription(),
3237                                            StringPool.BLANK,
3238                                            DLAppUtil.isMajorVersion(previousFileVersion, fileVersion),
3239                                            fileVersion.getContentStream(false), fileVersion.getSize(),
3240                                            serviceContext);
3241    
3242                                    FileVersion destinationFileVersion =
3243                                            destinationFileEntry.getFileVersion();
3244    
3245                                    dlAppHelperLocalService.updateFileEntry(
3246                                            getUserId(), destinationFileEntry,
3247                                            oldDestinationFileVersion, destinationFileVersion,
3248                                            serviceContext);
3249    
3250                                    oldDestinationFileVersion = destinationFileVersion;
3251                            }
3252                            catch (PortalException pe) {
3253                                    toRepository.deleteFileEntry(
3254                                            destinationFileEntry.getFileEntryId());
3255    
3256                                    throw pe;
3257                            }
3258                    }
3259    
3260                    return destinationFileEntry;
3261            }
3262    
3263            protected void copyFolder(
3264                            Repository repository, Folder srcFolder, Folder destFolder,
3265                            ServiceContext serviceContext)
3266                    throws PortalException {
3267    
3268                    Queue<Folder[]> folders = new LinkedList<Folder[]>();
3269                    final List<FileEntry> fileEntries = new ArrayList<FileEntry>();
3270    
3271                    Folder curSrcFolder = srcFolder;
3272                    Folder curDestFolder = destFolder;
3273    
3274                    while (true) {
3275                            List<FileEntry> srcFileEntries = repository.getFileEntries(
3276                                    curSrcFolder.getFolderId(), QueryUtil.ALL_POS,
3277                                    QueryUtil.ALL_POS, null);
3278    
3279                            for (FileEntry srcFileEntry : srcFileEntries) {
3280                                    try {
3281                                            FileEntry fileEntry = repository.copyFileEntry(
3282                                                    getUserId(), curDestFolder.getGroupId(),
3283                                                    srcFileEntry.getFileEntryId(),
3284                                                    curDestFolder.getFolderId(), serviceContext);
3285    
3286                                            dlAppHelperLocalService.addFileEntry(
3287                                                    getUserId(), fileEntry, fileEntry.getFileVersion(),
3288                                                    serviceContext);
3289    
3290                                            fileEntries.add(fileEntry);
3291                                    }
3292                                    catch (Exception e) {
3293                                            _log.error(e, e);
3294                                    }
3295                            }
3296    
3297                            List<Folder> srcSubfolders = repository.getFolders(
3298                                    curSrcFolder.getFolderId(), false, QueryUtil.ALL_POS,
3299                                    QueryUtil.ALL_POS, null);
3300    
3301                            for (Folder srcSubfolder : srcSubfolders) {
3302                                    Folder destSubfolder = repository.addFolder(
3303                                            getUserId(), curDestFolder.getFolderId(),
3304                                            srcSubfolder.getName(), srcSubfolder.getDescription(),
3305                                            serviceContext);
3306    
3307                                    dlAppHelperLocalService.addFolder(
3308                                            getUserId(), destSubfolder, serviceContext);
3309    
3310                                    folders.offer(new Folder[] {srcSubfolder, destSubfolder});
3311                            }
3312    
3313                            Folder[] next = folders.poll();
3314    
3315                            if (next == null) {
3316                                    break;
3317                            }
3318                            else {
3319                                    curSrcFolder = next[0];
3320                                    curDestFolder = next[1];
3321                            }
3322                    }
3323    
3324                    TransactionCommitCallbackRegistryUtil.registerCallback(
3325                            new Callable<Void>() {
3326    
3327                                    @Override
3328                                    public Void call() throws Exception {
3329                                            for (FileEntry fileEntry : fileEntries) {
3330                                                    DLProcessorRegistryUtil.trigger(fileEntry, null);
3331                                            }
3332    
3333                                            return null;
3334                                    }
3335    
3336                            });
3337            }
3338    
3339            protected void deleteFileEntry(
3340                            long oldFileEntryId, long newFileEntryId, Repository fromRepository,
3341                            Repository toRepository)
3342                    throws PortalException {
3343    
3344                    try {
3345                            FileEntry fileEntry = fromRepository.getFileEntry(oldFileEntryId);
3346    
3347                            dlAppHelperLocalService.deleteFileEntry(fileEntry);
3348    
3349                            fromRepository.deleteFileEntry(oldFileEntryId);
3350                    }
3351                    catch (PortalException pe) {
3352                            FileEntry fileEntry = toRepository.getFileEntry(newFileEntryId);
3353    
3354                            toRepository.deleteFileEntry(newFileEntryId);
3355    
3356                            dlAppHelperLocalService.deleteFileEntry(fileEntry);
3357    
3358                            throw pe;
3359                    }
3360            }
3361    
3362            protected FileEntry fetchFileEntryByUuidAndRepositoryId(
3363                            String uuid, long repositoryId)
3364                    throws PortalException {
3365    
3366                    try {
3367                            Repository repository = getRepository(repositoryId);
3368    
3369                            return repository.getFileEntryByUuid(uuid);
3370                    }
3371                    catch (NoSuchFileEntryException nsfee) {
3372                            return null;
3373                    }
3374                    catch (RepositoryException re) {
3375                            throw new NoSuchFileEntryException(re);
3376                    }
3377            }
3378    
3379            protected Repository getFileEntryRepository(long fileEntryId)
3380                    throws PortalException {
3381    
3382                    try {
3383                            return repositoryService.getRepositoryImpl(0, fileEntryId, 0);
3384                    }
3385                    catch (InvalidRepositoryIdException irie) {
3386                            StringBundler sb = new StringBundler(3);
3387    
3388                            sb.append("No FileEntry exists with the key {fileEntryId=");
3389                            sb.append(fileEntryId);
3390                            sb.append("}");
3391    
3392                            throw new NoSuchFileEntryException(sb.toString(), irie);
3393                    }
3394            }
3395    
3396            protected Repository getFileVersionRepository(long fileVersionId)
3397                    throws PortalException {
3398    
3399                    try {
3400                            return repositoryService.getRepositoryImpl(0, 0, fileVersionId);
3401                    }
3402                    catch (InvalidRepositoryIdException irie) {
3403                            StringBundler sb = new StringBundler(3);
3404    
3405                            sb.append("No FileVersion exists with the key {fileVersionId=");
3406                            sb.append(fileVersionId);
3407                            sb.append("}");
3408    
3409                            throw new NoSuchFileVersionException(sb.toString(), irie);
3410                    }
3411            }
3412    
3413            protected Repository getFolderRepository(long folderId)
3414                    throws PortalException {
3415    
3416                    try {
3417                            return repositoryService.getRepositoryImpl(folderId, 0, 0);
3418                    }
3419                    catch (InvalidRepositoryIdException irie) {
3420                            StringBundler sb = new StringBundler(3);
3421    
3422                            sb.append("No Folder exists with the key {folderId=");
3423                            sb.append(folderId);
3424                            sb.append("}");
3425    
3426                            throw new NoSuchFolderException(sb.toString(), irie);
3427                    }
3428            }
3429    
3430            protected Repository getFolderRepository(long folderId, long groupId)
3431                    throws PortalException {
3432    
3433                    if (folderId == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
3434                            return getRepository(groupId);
3435                    }
3436    
3437                    return getFolderRepository(folderId);
3438            }
3439    
3440            protected Repository getRepository(long repositoryId)
3441                    throws PortalException {
3442    
3443                    try {
3444                            return repositoryService.getRepositoryImpl(repositoryId);
3445                    }
3446                    catch (InvalidRepositoryIdException irie) {
3447                            StringBundler sb = new StringBundler(3);
3448    
3449                            sb.append("No Group exists with the key {repositoryId=");
3450                            sb.append(repositoryId);
3451                            sb.append("}");
3452    
3453                            throw new NoSuchGroupException(sb.toString(), irie);
3454                    }
3455            }
3456    
3457            protected FileEntry moveFileEntries(
3458                            long fileEntryId, long newFolderId, Repository fromRepository,
3459                            Repository toRepository, ServiceContext serviceContext)
3460                    throws PortalException {
3461    
3462                    FileEntry sourceFileEntry = fromRepository.getFileEntry(fileEntryId);
3463    
3464                    FileEntry destinationFileEntry = copyFileEntry(
3465                            toRepository, sourceFileEntry, newFolderId, serviceContext);
3466    
3467                    deleteFileEntry(
3468                            fileEntryId, destinationFileEntry.getFileEntryId(), fromRepository,
3469                            toRepository);
3470    
3471                    return destinationFileEntry;
3472            }
3473    
3474            protected Folder moveFolders(
3475                            long folderId, long parentFolderId, Repository fromRepository,
3476                            Repository toRepository, ServiceContext serviceContext)
3477                    throws PortalException {
3478    
3479                    Folder folder = fromRepository.getFolder(folderId);
3480    
3481                    Folder newFolder = toRepository.addFolder(
3482                            getUserId(), parentFolderId, folder.getName(),
3483                            folder.getDescription(), serviceContext);
3484    
3485                    dlAppHelperLocalService.addFolder(
3486                            getUserId(), newFolder, serviceContext);
3487    
3488                    List<Object> foldersAndFileEntriesAndFileShortcuts =
3489                            getFoldersAndFileEntriesAndFileShortcuts(
3490                                    fromRepository.getRepositoryId(), folderId,
3491                                    WorkflowConstants.STATUS_ANY, true, QueryUtil.ALL_POS,
3492                                    QueryUtil.ALL_POS);
3493    
3494                    try {
3495                            for (Object folderAndFileEntryAndFileShortcut :
3496                                            foldersAndFileEntriesAndFileShortcuts) {
3497    
3498                                    if (folderAndFileEntryAndFileShortcut instanceof FileEntry) {
3499                                            FileEntry fileEntry =
3500                                                    (FileEntry)folderAndFileEntryAndFileShortcut;
3501    
3502                                            copyFileEntry(
3503                                                    toRepository, fileEntry, newFolder.getFolderId(),
3504                                                    serviceContext);
3505                                    }
3506                                    else if (folderAndFileEntryAndFileShortcut instanceof Folder) {
3507                                            Folder currentFolder =
3508                                                    (Folder)folderAndFileEntryAndFileShortcut;
3509    
3510                                            moveFolders(
3511                                                    currentFolder.getFolderId(), newFolder.getFolderId(),
3512                                                    fromRepository, toRepository, serviceContext);
3513                                    }
3514                                    else if (folderAndFileEntryAndFileShortcut
3515                                                            instanceof DLFileShortcut) {
3516    
3517                                            if (newFolder.isSupportsShortcuts()) {
3518                                                    DLFileShortcut dlFileShorcut =
3519                                                            (DLFileShortcut)folderAndFileEntryAndFileShortcut;
3520    
3521                                                    dlFileShortcutService.addFileShortcut(
3522                                                            dlFileShorcut.getGroupId(), newFolder.getFolderId(),
3523                                                            dlFileShorcut.getToFileEntryId(), serviceContext);
3524                                            }
3525                                    }
3526                            }
3527                    }
3528                    catch (PortalException pe) {
3529                            toRepository.deleteFolder(newFolder.getFolderId());
3530    
3531                            throw pe;
3532                    }
3533    
3534                    try {
3535                            fromRepository.deleteFolder(folderId);
3536                    }
3537                    catch (PortalException pe) {
3538                            toRepository.deleteFolder(newFolder.getFolderId());
3539    
3540                            throw pe;
3541                    }
3542    
3543                    return newFolder;
3544            }
3545    
3546            private static Log _log = LogFactoryUtil.getLog(DLAppServiceImpl.class);
3547    
3548    }