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