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