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