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