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