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