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.log.Log;
024    import com.liferay.portal.kernel.log.LogFactoryUtil;
025    import com.liferay.portal.kernel.repository.InvalidRepositoryIdException;
026    import com.liferay.portal.kernel.repository.LocalRepository;
027    import com.liferay.portal.kernel.repository.RepositoryProvider;
028    import com.liferay.portal.kernel.repository.model.FileEntry;
029    import com.liferay.portal.kernel.repository.model.FileShortcut;
030    import com.liferay.portal.kernel.repository.model.FileVersion;
031    import com.liferay.portal.kernel.repository.model.Folder;
032    import com.liferay.portal.kernel.repository.model.RepositoryEntry;
033    import com.liferay.portal.kernel.systemevent.SystemEventHierarchyEntryThreadLocal;
034    import com.liferay.portal.kernel.util.ArrayUtil;
035    import com.liferay.portal.kernel.util.ContentTypes;
036    import com.liferay.portal.kernel.util.FileUtil;
037    import com.liferay.portal.kernel.util.MimeTypesUtil;
038    import com.liferay.portal.kernel.util.StringBundler;
039    import com.liferay.portal.kernel.util.StringPool;
040    import com.liferay.portal.kernel.util.Validator;
041    import com.liferay.portal.kernel.workflow.WorkflowConstants;
042    import com.liferay.portal.model.Repository;
043    import com.liferay.portal.model.UserConstants;
044    import com.liferay.portal.repository.liferayrepository.model.LiferayFolder;
045    import com.liferay.portal.service.ServiceContext;
046    import com.liferay.portlet.documentlibrary.NoSuchFileEntryException;
047    import com.liferay.portlet.documentlibrary.model.DLFileEntryType;
048    import com.liferay.portlet.documentlibrary.model.DLFileEntryTypeConstants;
049    import com.liferay.portlet.documentlibrary.model.DLFileRank;
050    import com.liferay.portlet.documentlibrary.model.DLFolder;
051    import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
052    import com.liferay.portlet.documentlibrary.service.base.DLAppLocalServiceBaseImpl;
053    import com.liferay.portlet.documentlibrary.util.DLAppUtil;
054    
055    import java.io.File;
056    import java.io.IOException;
057    import java.io.InputStream;
058    
059    import java.util.List;
060    
061    /**
062     * Provides the local service for accessing, adding, deleting, moving,
063     * subscription handling of, and updating document library file entries, file
064     * ranks, and folders. All portlets should interact with the document library
065     * through this class or through DLAppService, rather than through the
066     * individual document library service classes.
067     *
068     * <p>
069     * This class provides a unified interface to all Liferay and third party
070     * repositories. While the method signatures are universal for all repositories.
071     * Additional implementation-specific parameters may be specified in the
072     * serviceContext.
073     * </p>
074     *
075     * <p>
076     * The <code>repositoryId</code> parameter used by most of the methods is the
077     * primary key of the specific repository. If the repository is a default
078     * Liferay repository, the <code>repositoryId</code> is the <code>groupId</code>
079     * or <code>scopeGroupId</code>. Otherwise, the <code>repositoryId</code> will
080     * correspond to values obtained from {@link
081     * com.liferay.portal.service.RepositoryLocalServiceUtil}.
082     * </p>
083     *
084     * @author Alexander Chow
085     * @author Mika Koivisto
086     * @see    DLAppServiceImpl
087     */
088    public class DLAppLocalServiceImpl extends DLAppLocalServiceBaseImpl {
089    
090            @Override
091            public FileEntry addFileEntry(
092                            long userId, long repositoryId, long folderId,
093                            String sourceFileName, String mimeType, byte[] bytes,
094                            ServiceContext serviceContext)
095                    throws PortalException {
096    
097                    return addFileEntry(
098                            userId, repositoryId, folderId, sourceFileName, mimeType, null,
099                            StringPool.BLANK, StringPool.BLANK, bytes, serviceContext);
100            }
101    
102            /**
103             * Adds a file entry and associated metadata based on a byte array.
104             *
105             * <p>
106             * This method takes two file names, the <code>sourceFileName</code> and the
107             * <code>title</code>. The <code>sourceFileName</code> corresponds to the
108             * name of the actual file being uploaded. The <code>title</code>
109             * corresponds to a name the client wishes to assign this file after it has
110             * been uploaded to the portal. If it is <code>null</code>, the <code>
111             * sourceFileName</code> will be used.
112             * </p>
113             *
114             * @param  userId the primary key of the file entry's creator/owner
115             * @param  repositoryId the primary key of the file entry's repository
116             * @param  folderId the primary key of the file entry's parent folder
117             * @param  sourceFileName the original file's name
118             * @param  mimeType the file's MIME type
119             * @param  title the name to be assigned to the file (optionally <code>null
120             *         </code>)
121             * @param  description the file's description
122             * @param  changeLog the file's version change log
123             * @param  bytes the file's data (optionally <code>null</code>)
124             * @param  serviceContext the service context to be applied. Can set the
125             *         asset category IDs, asset tag names, and expando bridge
126             *         attributes for the file entry. In a Liferay repository, it may
127             *         include:  <ul> <li> fileEntryTypeId - ID for a custom file entry
128             *         type </li> <li> fieldsMap - mapping for fields associated with a
129             *         custom file entry type </li> </ul>
130             * @return the file entry
131             */
132            @Override
133            public FileEntry addFileEntry(
134                            long userId, long repositoryId, long folderId,
135                            String sourceFileName, String mimeType, String title,
136                            String description, String changeLog, byte[] bytes,
137                            ServiceContext serviceContext)
138                    throws PortalException {
139    
140                    File file = null;
141    
142                    try {
143                            if (ArrayUtil.isNotEmpty(bytes)) {
144                                    file = FileUtil.createTempFile(bytes);
145                            }
146    
147                            return addFileEntry(
148                                    userId, repositoryId, folderId, sourceFileName, mimeType, title,
149                                    description, changeLog, file, serviceContext);
150                    }
151                    catch (IOException ioe) {
152                            throw new SystemException("Unable to write temporary file", ioe);
153                    }
154                    finally {
155                            FileUtil.delete(file);
156                    }
157            }
158    
159            /**
160             * Adds a file entry and associated metadata based on a {@link File} object.
161             *
162             * <p>
163             * This method takes two file names, the <code>sourceFileName</code> and the
164             * <code>title</code>. The <code>sourceFileName</code> corresponds to the
165             * name of the actual file being uploaded. The <code>title</code>
166             * corresponds to a name the client wishes to assign this file after it has
167             * been uploaded to the portal. If it is <code>null</code>, the <code>
168             * sourceFileName</code> will be used.
169             * </p>
170             *
171             * @param  userId the primary key of the file entry's creator/owner
172             * @param  repositoryId the primary key of the repository
173             * @param  folderId the primary key of the file entry's parent folder
174             * @param  sourceFileName the original file's name
175             * @param  mimeType the file's MIME type
176             * @param  title the name to be assigned to the file (optionally <code>null
177             *         </code>)
178             * @param  description the file's description
179             * @param  changeLog the file's version change log
180             * @param  file the file's data (optionally <code>null</code>)
181             * @param  serviceContext the service context to be applied. Can set the
182             *         asset category IDs, asset tag names, and expando bridge
183             *         attributes for the file entry. In a Liferay repository, it may
184             *         include:  <ul> <li> fileEntryTypeId - ID for a custom file entry
185             *         type </li> <li> fieldsMap - mapping for fields associated with a
186             *         custom file entry type </li> </ul>
187             * @return the file entry
188             */
189            @Override
190            public FileEntry addFileEntry(
191                            long userId, long repositoryId, long folderId,
192                            String sourceFileName, String mimeType, String title,
193                            String description, String changeLog, File file,
194                            ServiceContext serviceContext)
195                    throws PortalException {
196    
197                    if ((file == null) || !file.exists() || (file.length() == 0)) {
198                            return addFileEntry(
199                                    userId, repositoryId, folderId, sourceFileName, mimeType, title,
200                                    description, changeLog, null, 0, serviceContext);
201                    }
202    
203                    mimeType = DLAppUtil.getMimeType(sourceFileName, mimeType, title, file);
204    
205                    LocalRepository localRepository = getLocalRepository(repositoryId);
206    
207                    FileEntry fileEntry = localRepository.addFileEntry(
208                            userId, folderId, sourceFileName, mimeType, title, description,
209                            changeLog, file, serviceContext);
210    
211                    return fileEntry;
212            }
213    
214            /**
215             * Adds a file entry and associated metadata based on an {@link InputStream}
216             * object.
217             *
218             * <p>
219             * This method takes two file names, the <code>sourceFileName</code> and the
220             * <code>title</code>. The <code>sourceFileName</code> corresponds to the
221             * name of the actual file being uploaded. The <code>title</code>
222             * corresponds to a name the client wishes to assign this file after it has
223             * been uploaded to the portal. If it is <code>null</code>, the <code>
224             * sourceFileName</code> will be used.
225             * </p>
226             *
227             * @param  userId the primary key of the file entry's creator/owner
228             * @param  repositoryId the primary key of the repository
229             * @param  folderId the primary key of the file entry's parent folder
230             * @param  sourceFileName the original file's name
231             * @param  mimeType the file's MIME type
232             * @param  title the name to be assigned to the file (optionally <code>null
233             *         </code>)
234             * @param  description the file's description
235             * @param  changeLog the file's version change log
236             * @param  is the file's data (optionally <code>null</code>)
237             * @param  size the file's size (optionally <code>0</code>)
238             * @param  serviceContext the service context to be applied. Can set the
239             *         asset category IDs, asset tag names, and expando bridge
240             *         attributes for the file entry. In a Liferay repository, it may
241             *         include:  <ul> <li> fileEntryTypeId - ID for a custom file entry
242             *         type </li> <li> fieldsMap - mapping for fields associated with a
243             *         custom file entry type </li> </ul>
244             * @return the file entry
245             */
246            @Override
247            public FileEntry addFileEntry(
248                            long userId, long repositoryId, long folderId,
249                            String sourceFileName, String mimeType, String title,
250                            String description, String changeLog, InputStream is, long size,
251                            ServiceContext serviceContext)
252                    throws PortalException {
253    
254                    if (is == null) {
255                            is = new UnsyncByteArrayInputStream(new byte[0]);
256                            size = 0;
257                    }
258    
259                    if (Validator.isNull(mimeType) ||
260                            mimeType.equals(ContentTypes.APPLICATION_OCTET_STREAM)) {
261    
262                            String extension = DLAppUtil.getExtension(title, sourceFileName);
263    
264                            if (size == 0) {
265                                    mimeType = MimeTypesUtil.getExtensionContentType(extension);
266                            }
267                            else {
268                                    File file = null;
269    
270                                    try {
271                                            file = FileUtil.createTempFile(is);
272    
273                                            return addFileEntry(
274                                                    userId, repositoryId, folderId, sourceFileName,
275                                                    mimeType, title, description, changeLog, file,
276                                                    serviceContext);
277                                    }
278                                    catch (IOException ioe) {
279                                            throw new SystemException(
280                                                    "Unable to write temporary file", ioe);
281                                    }
282                                    finally {
283                                            FileUtil.delete(file);
284                                    }
285                            }
286                    }
287    
288                    LocalRepository localRepository = getLocalRepository(repositoryId);
289    
290                    FileEntry fileEntry = localRepository.addFileEntry(
291                            userId, folderId, sourceFileName, mimeType, title, description,
292                            changeLog, is, size, serviceContext);
293    
294                    return fileEntry;
295            }
296    
297            /**
298             * Adds the file rank to the existing file entry. This method is only
299             * supported by the Liferay repository.
300             *
301             * @param  repositoryId the primary key of the repository
302             * @param  companyId the primary key of the company
303             * @param  userId the primary key of the file rank's creator/owner
304             * @param  fileEntryId the primary key of the file entry
305             * @param  serviceContext the service context to be applied
306             * @return the file rank
307             */
308            @Override
309            public DLFileRank addFileRank(
310                    long repositoryId, long companyId, long userId, long fileEntryId,
311                    ServiceContext serviceContext) {
312    
313                    return dlFileRankLocalService.addFileRank(
314                            repositoryId, companyId, userId, fileEntryId, serviceContext);
315            }
316    
317            /**
318             * Adds the file shortcut to the existing file entry. This method is only
319             * supported by the Liferay repository.
320             *
321             * @param  userId the primary key of the file shortcut's creator/owner
322             * @param  repositoryId the primary key of the repository
323             * @param  folderId the primary key of the file shortcut's parent folder
324             * @param  toFileEntryId the primary key of the file entry to point to
325             * @param  serviceContext the service context to be applied. Can set the
326             *         asset category IDs, asset tag names, and expando bridge
327             *         attributes for the file entry.
328             * @return the file shortcut
329             */
330            @Override
331            public FileShortcut addFileShortcut(
332                            long userId, long repositoryId, long folderId, long toFileEntryId,
333                            ServiceContext serviceContext)
334                    throws PortalException {
335    
336                    LocalRepository localRepository = getLocalRepository(repositoryId);
337    
338                    return localRepository.addFileShortcut(
339                            userId, folderId, toFileEntryId, serviceContext);
340            }
341    
342            /**
343             * Adds a folder.
344             *
345             * @param  userId the primary key of the folder's creator/owner
346             * @param  repositoryId the primary key of the repository
347             * @param  parentFolderId the primary key of the folder's parent folder
348             * @param  name the folder's name
349             * @param  description the folder's description
350             * @param  serviceContext the service context to be applied. In a Liferay
351             *         repository, it may include mountPoint which is a boolean
352             *         specifying whether the folder is a facade for mounting a
353             *         third-party repository
354             * @return the folder
355             */
356            @Override
357            public Folder addFolder(
358                            long userId, long repositoryId, long parentFolderId, String name,
359                            String description, ServiceContext serviceContext)
360                    throws PortalException {
361    
362                    LocalRepository localRepository = getLocalRepository(repositoryId);
363    
364                    Folder folder = localRepository.addFolder(
365                            userId, parentFolderId, name, description, serviceContext);
366    
367                    dlAppHelperLocalService.addFolder(userId, folder, serviceContext);
368    
369                    return folder;
370            }
371    
372            /**
373             * Delete all data associated to the given repository. This method is only
374             * supported by the Liferay repository.
375             *
376             * @param repositoryId the primary key of the data's repository
377             */
378            @Override
379            public void deleteAll(long repositoryId) throws PortalException {
380                    LocalRepository localRepository = getLocalRepository(repositoryId);
381    
382                    deleteRepository(localRepository);
383            }
384    
385            @Override
386            public void deleteAllRepositories(long groupId) throws PortalException {
387                    LocalRepository groupLocalRepository =
388                            repositoryProvider.getLocalRepository(groupId);
389    
390                    deleteRepository(groupLocalRepository);
391    
392                    List<LocalRepository> localRepositories =
393                            repositoryProvider.getGroupLocalRepositories(groupId);
394    
395                    for (LocalRepository localRepository : localRepositories) {
396                            if (localRepository.getRepositoryId() !=
397                                            groupLocalRepository.getRepositoryId()) {
398    
399                                    deleteRepository(localRepository);
400                            }
401                    }
402            }
403    
404            /**
405             * Deletes the file entry.
406             *
407             * @param fileEntryId the primary key of the file entry
408             */
409            @Override
410            public void deleteFileEntry(long fileEntryId) throws PortalException {
411                    LocalRepository localRepository =
412                            repositoryProvider.getFileEntryLocalRepository(fileEntryId);
413    
414                    FileEntry fileEntry = localRepository.getFileEntry(fileEntryId);
415    
416                    dlAppHelperLocalService.deleteFileEntry(fileEntry);
417    
418                    localRepository.deleteFileEntry(fileEntryId);
419            }
420    
421            /**
422             * Deletes the file ranks associated to a given file entry. This method is
423             * only supported by the Liferay repository.
424             *
425             * @param fileEntryId the primary key of the file entry
426             */
427            @Override
428            public void deleteFileRanksByFileEntryId(long fileEntryId) {
429                    dlFileRankLocalService.deleteFileRanksByFileEntryId(fileEntryId);
430            }
431    
432            /**
433             * Deletes the file ranks associated to a given user. This method is only
434             * supported by the Liferay repository.
435             *
436             * @param userId the primary key of the user
437             */
438            @Override
439            public void deleteFileRanksByUserId(long userId) {
440                    dlFileRankLocalService.deleteFileRanksByUserId(userId);
441            }
442    
443            /**
444             * Deletes the file shortcut. This method is only supported by the Liferay
445             * repository.
446             *
447             * @param fileShortcut the file shortcut
448             */
449            @Override
450            public void deleteFileShortcut(FileShortcut fileShortcut)
451                    throws PortalException {
452    
453                    deleteFileShortcut(fileShortcut.getFileShortcutId());
454            }
455    
456            /**
457             * Deletes the file shortcut. This method is only supported by the Liferay
458             * repository.
459             *
460             * @param fileShortcutId the primary key of the file shortcut
461             */
462            @Override
463            public void deleteFileShortcut(long fileShortcutId) throws PortalException {
464                    LocalRepository localRepository =
465                            repositoryProvider.getFileShortcutLocalRepository(fileShortcutId);
466    
467                    localRepository.deleteFileShortcut(fileShortcutId);
468            }
469    
470            /**
471             * Deletes all file shortcuts associated to the file entry. This method is
472             * only supported by the Liferay repository.
473             *
474             * @param toFileEntryId the primary key of the associated file entry
475             */
476            @Override
477            public void deleteFileShortcuts(long toFileEntryId) throws PortalException {
478                    LocalRepository localRepository =
479                            repositoryProvider.getFileEntryLocalRepository(toFileEntryId);
480    
481                    localRepository.deleteFileShortcuts(toFileEntryId);
482            }
483    
484            /**
485             * Deletes the folder and all of its subfolders and file entries.
486             *
487             * @param folderId the primary key of the folder
488             */
489            @Override
490            public void deleteFolder(long folderId) throws PortalException {
491                    LocalRepository localRepository =
492                            repositoryProvider.getFolderLocalRepository(folderId);
493    
494                    List<FileEntry> fileEntries = localRepository.getRepositoryFileEntries(
495                            UserConstants.USER_ID_DEFAULT, folderId, QueryUtil.ALL_POS,
496                            QueryUtil.ALL_POS, null);
497    
498                    for (FileEntry fileEntry : fileEntries) {
499                            dlAppHelperLocalService.deleteFileEntry(fileEntry);
500                    }
501    
502                    Folder folder = getFolder(folderId);
503    
504                    localRepository.deleteFolder(folderId);
505    
506                    dlAppHelperLocalService.deleteFolder(folder);
507            }
508    
509            /**
510             * Returns the file entry with the primary key.
511             *
512             * @param  fileEntryId the primary key of the file entry
513             * @return the file entry with the primary key
514             */
515            @Override
516            public FileEntry getFileEntry(long fileEntryId) throws PortalException {
517                    LocalRepository localRepository =
518                            repositoryProvider.getFileEntryLocalRepository(fileEntryId);
519    
520                    return localRepository.getFileEntry(fileEntryId);
521            }
522    
523            /**
524             * Returns the file entry with the title in the folder.
525             *
526             * @param  groupId the primary key of the file entry's group
527             * @param  folderId the primary key of the file entry's folder
528             * @param  title the file entry's title
529             * @return the file entry with the title in the folder
530             */
531            @Override
532            public FileEntry getFileEntry(long groupId, long folderId, String title)
533                    throws PortalException {
534    
535                    try {
536                            LocalRepository localRepository = getLocalRepository(groupId);
537    
538                            return localRepository.getFileEntry(folderId, title);
539                    }
540                    catch (NoSuchFileEntryException nsfee) {
541                            if (_log.isDebugEnabled()) {
542                                    _log.debug(nsfee, nsfee);
543                            }
544                    }
545    
546                    LocalRepository localRepository =
547                            repositoryProvider.getFolderLocalRepository(folderId);
548    
549                    return localRepository.getFileEntry(folderId, title);
550            }
551    
552            /**
553             * Returns the file entry with the UUID and group.
554             *
555             * @param  uuid the file entry's UUID
556             * @param  groupId the primary key of the file entry's group
557             * @return the file entry with the UUID and group
558             */
559            @Override
560            public FileEntry getFileEntryByUuidAndGroupId(String uuid, long groupId)
561                    throws PortalException {
562    
563                    try {
564                            LocalRepository localRepository = getLocalRepository(groupId);
565    
566                            return localRepository.getFileEntryByUuid(uuid);
567                    }
568                    catch (NoSuchFileEntryException nsfee) {
569                            if (_log.isDebugEnabled()) {
570                                    _log.debug(nsfee, nsfee);
571                            }
572                    }
573    
574                    List<com.liferay.portal.model.Repository> repositories =
575                            repositoryPersistence.findByGroupId(groupId);
576    
577                    for (Repository repository : repositories) {
578                            try {
579                                    LocalRepository localRepository = getLocalRepository(
580                                            repository.getRepositoryId());
581    
582                                    return localRepository.getFileEntryByUuid(uuid);
583                            }
584                            catch (NoSuchFileEntryException nsfee) {
585                                    if (_log.isDebugEnabled()) {
586                                            _log.debug(nsfee, nsfee);
587                                    }
588                            }
589                    }
590    
591                    StringBundler msg = new StringBundler(6);
592    
593                    msg.append("No DLFileEntry exists with the key {");
594                    msg.append("uuid=");
595                    msg.append(uuid);
596                    msg.append(", groupId=");
597                    msg.append(groupId);
598                    msg.append(StringPool.CLOSE_CURLY_BRACE);
599    
600                    throw new NoSuchFileEntryException(msg.toString());
601            }
602    
603            /**
604             * Returns the file ranks from the user. This method is only supported by
605             * the Liferay repository.
606             *
607             * @param  repositoryId the primary key of the repository
608             * @param  userId the primary key of the user
609             * @return the file ranks from the user
610             */
611            @Override
612            public List<DLFileRank> getFileRanks(long repositoryId, long userId) {
613                    return dlFileRankLocalService.getFileRanks(repositoryId, userId);
614            }
615    
616            /**
617             * Returns the file shortcut with the primary key. This method is only
618             * supported by the Liferay repository.
619             *
620             * @param  fileShortcutId the primary key of the file shortcut
621             * @return the file shortcut with the primary key
622             */
623            @Override
624            public FileShortcut getFileShortcut(long fileShortcutId)
625                    throws PortalException {
626    
627                    LocalRepository localRepository =
628                            repositoryProvider.getFileShortcutLocalRepository(fileShortcutId);
629    
630                    return localRepository.getFileShortcut(fileShortcutId);
631            }
632    
633            /**
634             * Returns the file version with the primary key.
635             *
636             * @param  fileVersionId the primary key of the file version
637             * @return the file version with the primary key
638             */
639            @Override
640            public FileVersion getFileVersion(long fileVersionId)
641                    throws PortalException {
642    
643                    LocalRepository localRepository =
644                            repositoryProvider.getFileVersionLocalRepository(fileVersionId);
645    
646                    return localRepository.getFileVersion(fileVersionId);
647            }
648    
649            /**
650             * Returns the folder with the primary key.
651             *
652             * @param  folderId the primary key of the folder
653             * @return the folder with the primary key
654             */
655            @Override
656            public Folder getFolder(long folderId) throws PortalException {
657                    LocalRepository localRepository =
658                            repositoryProvider.getFolderLocalRepository(folderId);
659    
660                    return localRepository.getFolder(folderId);
661            }
662    
663            /**
664             * Returns the folder with the name in the parent folder.
665             *
666             * @param  repositoryId the primary key of the folder's repository
667             * @param  parentFolderId the primary key of the folder's parent folder
668             * @param  name the folder's name
669             * @return the folder with the name in the parent folder
670             */
671            @Override
672            public Folder getFolder(long repositoryId, long parentFolderId, String name)
673                    throws PortalException {
674    
675                    LocalRepository localRepository = getLocalRepository(repositoryId);
676    
677                    return localRepository.getFolder(parentFolderId, name);
678            }
679    
680            /**
681             * Returns the mount folder of the repository with the primary key. This
682             * method is only supported by the Liferay repository.
683             *
684             * @param  repositoryId the primary key of the repository
685             * @return the folder used for mounting third-party repositories
686             */
687            @Override
688            public Folder getMountFolder(long repositoryId) throws PortalException {
689                    DLFolder dlFolder = dlFolderLocalService.getMountFolder(repositoryId);
690    
691                    return new LiferayFolder(dlFolder);
692            }
693    
694            /**
695             * Moves the file entry to the new folder.
696             *
697             * @param  userId the primary key of the user
698             * @param  fileEntryId the primary key of the file entry
699             * @param  newFolderId the primary key of the new folder
700             * @param  serviceContext the service context to be applied
701             * @return the file entry
702             */
703            @Override
704            public FileEntry moveFileEntry(
705                            long userId, long fileEntryId, long newFolderId,
706                            ServiceContext serviceContext)
707                    throws PortalException {
708    
709                    SystemEventHierarchyEntryThreadLocal.push(FileEntry.class);
710    
711                    try {
712                            LocalRepository fromLocalRepository =
713                                    repositoryProvider.getFileEntryLocalRepository(fileEntryId);
714    
715                            LocalRepository toLocalRepository = getFolderLocalRepository(
716                                    newFolderId, serviceContext.getScopeGroupId());
717    
718                            if (fromLocalRepository.getRepositoryId() ==
719                                            toLocalRepository.getRepositoryId()) {
720    
721                                    // Move file entries within repository
722    
723                                    return fromLocalRepository.moveFileEntry(
724                                            userId, fileEntryId, newFolderId, serviceContext);
725                            }
726    
727                            // Move file entries between repositories
728    
729                            return moveFileEntries(
730                                    userId, fileEntryId, newFolderId, fromLocalRepository,
731                                    toLocalRepository, serviceContext);
732                    }
733                    finally {
734                            SystemEventHierarchyEntryThreadLocal.pop(FileEntry.class);
735                    }
736            }
737    
738            @Override
739            public Folder moveFolder(
740                            long userId, long folderId, long parentFolderId,
741                            ServiceContext serviceContext)
742                    throws PortalException {
743    
744                    SystemEventHierarchyEntryThreadLocal.push(Folder.class);
745    
746                    try {
747                            LocalRepository sourceLocalRepository =
748                                    repositoryProvider.getFolderLocalRepository(folderId);
749    
750                            LocalRepository destinationLocalRepository =
751                                    getFolderLocalRepository(
752                                            parentFolderId, serviceContext.getScopeGroupId());
753    
754                            if (parentFolderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
755                                    Folder toFolder = destinationLocalRepository.getFolder(
756                                            parentFolderId);
757    
758                                    if (toFolder.isMountPoint()) {
759                                            destinationLocalRepository = getLocalRepository(
760                                                    toFolder.getRepositoryId());
761                                    }
762                            }
763    
764                            if (sourceLocalRepository.getRepositoryId() ==
765                                            destinationLocalRepository.getRepositoryId()) {
766    
767                                    // Move file entries within repository
768    
769                                    return sourceLocalRepository.moveFolder(
770                                            userId, folderId, parentFolderId, serviceContext);
771                            }
772    
773                            // Move file entries between repositories
774    
775                            return moveFolders(
776                                    userId, folderId, parentFolderId, sourceLocalRepository,
777                                    destinationLocalRepository, serviceContext);
778                    }
779                    finally {
780                            SystemEventHierarchyEntryThreadLocal.pop(Folder.class);
781                    }
782            }
783    
784            /**
785             * Subscribe the user to changes in documents of the file entry type. This
786             * method is only supported by the Liferay repository.
787             *
788             * @param userId the primary key of the user
789             * @param groupId the primary key of the file entry type's group
790             * @param fileEntryTypeId the primary key of the file entry type
791             */
792            @Override
793            public void subscribeFileEntryType(
794                            long userId, long groupId, long fileEntryTypeId)
795                    throws PortalException {
796    
797                    if (fileEntryTypeId ==
798                                    DLFileEntryTypeConstants.FILE_ENTRY_TYPE_ID_BASIC_DOCUMENT) {
799    
800                            fileEntryTypeId = groupId;
801                    }
802    
803                    subscriptionLocalService.addSubscription(
804                            userId, groupId, DLFileEntryType.class.getName(), fileEntryTypeId);
805            }
806    
807            /**
808             * Subscribe the user to document changes in the folder. This method is only
809             * supported by the Liferay repository.
810             *
811             * @param userId the primary key of the user
812             * @param groupId the primary key of the folder's group
813             * @param folderId the primary key of the folder
814             */
815            @Override
816            public void subscribeFolder(long userId, long groupId, long folderId)
817                    throws PortalException {
818    
819                    if (folderId == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
820                            folderId = groupId;
821                    }
822    
823                    subscriptionLocalService.addSubscription(
824                            userId, groupId, DLFolder.class.getName(), folderId);
825            }
826    
827            /**
828             * Unsubscribe the user from changes in documents of the file entry type.
829             * This method is only supported by the Liferay repository.
830             *
831             * @param userId the primary key of the user
832             * @param groupId the primary key of the file entry type's group
833             * @param fileEntryTypeId the primary key of the file entry type
834             */
835            @Override
836            public void unsubscribeFileEntryType(
837                            long userId, long groupId, long fileEntryTypeId)
838                    throws PortalException {
839    
840                    if (fileEntryTypeId ==
841                                    DLFileEntryTypeConstants.FILE_ENTRY_TYPE_ID_BASIC_DOCUMENT) {
842    
843                            fileEntryTypeId = groupId;
844                    }
845    
846                    subscriptionLocalService.deleteSubscription(
847                            userId, DLFileEntryType.class.getName(), fileEntryTypeId);
848            }
849    
850            /**
851             * Unsubscribe the user from document changes in the folder. This method is
852             * only supported by the Liferay repository.
853             *
854             * @param userId the primary key of the user
855             * @param groupId the primary key of the folder's group
856             * @param folderId the primary key of the folder
857             */
858            @Override
859            public void unsubscribeFolder(long userId, long groupId, long folderId)
860                    throws PortalException {
861    
862                    if (folderId == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
863                            folderId = groupId;
864                    }
865    
866                    subscriptionLocalService.deleteSubscription(
867                            userId, DLFolder.class.getName(), folderId);
868            }
869    
870            /**
871             * Updates the file entry's asset replacing its asset categories, tags, and
872             * links.
873             *
874             * @param userId the primary key of the user
875             * @param fileEntry the file entry to update
876             * @param fileVersion the file version to update
877             * @param assetCategoryIds the primary keys of the new asset categories
878             * @param assetTagNames the new asset tag names
879             * @param assetLinkEntryIds the primary keys of the new asset link entries
880             */
881            @Override
882            public void updateAsset(
883                            long userId, FileEntry fileEntry, FileVersion fileVersion,
884                            long[] assetCategoryIds, String[] assetTagNames,
885                            long[] assetLinkEntryIds)
886                    throws PortalException {
887    
888                    dlAppHelperLocalService.updateAsset(
889                            userId, fileEntry, fileVersion, assetCategoryIds, assetTagNames,
890                            assetLinkEntryIds);
891            }
892    
893            /**
894             * Updates a file entry and associated metadata based on a byte array
895             * object. If the file data is <code>null</code>, then only the associated
896             * metadata (i.e., <code>title</code>, <code>description</code>, and
897             * parameters in the <code>serviceContext</code>) will be updated.
898             *
899             * <p>
900             * This method takes two file names, the <code>sourceFileName</code> and the
901             * <code>title</code>. The <code>sourceFileName</code> corresponds to the
902             * name of the actual file being uploaded. The <code>title</code>
903             * corresponds to a name the client wishes to assign this file after it has
904             * been uploaded to the portal.
905             * </p>
906             *
907             * @param  userId the primary key of the user
908             * @param  fileEntryId the primary key of the file entry
909             * @param  sourceFileName the original file's name (optionally
910             *         <code>null</code>)
911             * @param  mimeType the file's MIME type (optionally <code>null</code>)
912             * @param  title the new name to be assigned to the file (optionally <code>
913             *         <code>null</code></code>)
914             * @param  description the file's new description
915             * @param  changeLog the file's version change log (optionally
916             *         <code>null</code>)
917             * @param  majorVersion whether the new file version is a major version
918             * @param  bytes the file's data (optionally <code>null</code>)
919             * @param  serviceContext the service context to be applied. Can set the
920             *         asset category IDs, asset tag names, and expando bridge
921             *         attributes for the file entry. In a Liferay repository, it may
922             *         include:  <ul> <li> fileEntryTypeId - ID for a custom file entry
923             *         type </li> <li> fieldsMap - mapping for fields associated with a
924             *         custom file entry type </li> </ul>
925             * @return the file entry
926             */
927            @Override
928            public FileEntry updateFileEntry(
929                            long userId, long fileEntryId, String sourceFileName,
930                            String mimeType, String title, String description, String changeLog,
931                            boolean majorVersion, byte[] bytes, ServiceContext serviceContext)
932                    throws PortalException {
933    
934                    File file = null;
935    
936                    try {
937                            if (ArrayUtil.isNotEmpty(bytes)) {
938                                    file = FileUtil.createTempFile(bytes);
939                            }
940    
941                            return updateFileEntry(
942                                    userId, fileEntryId, sourceFileName, mimeType, title,
943                                    description, changeLog, majorVersion, file, serviceContext);
944                    }
945                    catch (IOException ioe) {
946                            throw new SystemException("Unable to write temporary file", ioe);
947                    }
948                    finally {
949                            FileUtil.delete(file);
950                    }
951            }
952    
953            /**
954             * Updates a file entry and associated metadata based on a {@link File}
955             * object. If the file data is <code>null</code>, then only the associated
956             * metadata (i.e., <code>title</code>, <code>description</code>, and
957             * parameters in the <code>serviceContext</code>) will be updated.
958             *
959             * <p>
960             * This method takes two file names, the <code>sourceFileName</code> and the
961             * <code>title</code>. The <code>sourceFileName</code> corresponds to the
962             * name of the actual file being uploaded. The <code>title</code>
963             * corresponds to a name the client wishes to assign this file after it has
964             * been uploaded to the portal.
965             * </p>
966             *
967             * @param  userId the primary key of the user
968             * @param  fileEntryId the primary key of the file entry
969             * @param  sourceFileName the original file's name (optionally
970             *         <code>null</code>)
971             * @param  mimeType the file's MIME type (optionally <code>null</code>)
972             * @param  title the new name to be assigned to the file (optionally <code>
973             *         <code>null</code></code>)
974             * @param  description the file's new description
975             * @param  changeLog the file's version change log (optionally
976             *         <code>null</code>)
977             * @param  majorVersion whether the new file version is a major version
978             * @param  file the file's data (optionally <code>null</code>)
979             * @param  serviceContext the service context to be applied. Can set the
980             *         asset category IDs, asset tag names, and expando bridge
981             *         attributes for the file entry. In a Liferay repository, it may
982             *         include:  <ul> <li> fileEntryTypeId - ID for a custom file entry
983             *         type </li> <li> fieldsMap - mapping for fields associated with a
984             *         custom file entry type </li> </ul>
985             * @return the file entry
986             */
987            @Override
988            public FileEntry updateFileEntry(
989                            long userId, long fileEntryId, String sourceFileName,
990                            String mimeType, String title, String description, String changeLog,
991                            boolean majorVersion, File file, ServiceContext serviceContext)
992                    throws PortalException {
993    
994                    if ((file == null) || !file.exists() || (file.length() == 0)) {
995                            return updateFileEntry(
996                                    userId, fileEntryId, sourceFileName, mimeType, title,
997                                    description, changeLog, majorVersion, null, 0, serviceContext);
998                    }
999    
1000                    mimeType = DLAppUtil.getMimeType(sourceFileName, mimeType, title, file);
1001    
1002                    LocalRepository localRepository =
1003                            repositoryProvider.getFileEntryLocalRepository(fileEntryId);
1004    
1005                    FileEntry fileEntry = localRepository.updateFileEntry(
1006                            userId, fileEntryId, sourceFileName, mimeType, title, description,
1007                            changeLog, majorVersion, file, serviceContext);
1008    
1009                    dlAppHelperLocalService.updateFileEntry(
1010                            userId, fileEntry, null, fileEntry.getFileVersion(),
1011                            serviceContext);
1012    
1013                    return fileEntry;
1014            }
1015    
1016            /**
1017             * Updates a file entry and associated metadata based on an {@link
1018             * InputStream} object. If the file data is <code>null</code>, then only the
1019             * associated metadata (i.e., <code>title</code>, <code>description</code>,
1020             * and parameters in the <code>serviceContext</code>) will be updated.
1021             *
1022             * <p>
1023             * This method takes two file names, the <code>sourceFileName</code> and the
1024             * <code>title</code>. The <code>sourceFileName</code> corresponds to the
1025             * name of the actual file being uploaded. The <code>title</code>
1026             * corresponds to a name the client wishes to assign this file after it has
1027             * been uploaded to the portal.
1028             * </p>
1029             *
1030             * @param  userId the primary key of the user
1031             * @param  fileEntryId the primary key of the file entry
1032             * @param  sourceFileName the original file's name (optionally
1033             *         <code>null</code>)
1034             * @param  mimeType the file's MIME type (optionally <code>null</code>)
1035             * @param  title the new name to be assigned to the file (optionally <code>
1036             *         <code>null</code></code>)
1037             * @param  description the file's new description
1038             * @param  changeLog the file's version change log (optionally
1039             *         <code>null</code>)
1040             * @param  majorVersion whether the new file version is a major version
1041             * @param  is the file's data (optionally <code>null</code>)
1042             * @param  size the file's size (optionally <code>0</code>)
1043             * @param  serviceContext the service context to be applied. Can set the
1044             *         asset category IDs, asset tag names, and expando bridge
1045             *         attributes for the file entry. In a Liferay repository, it may
1046             *         include:  <ul> <li> fileEntryTypeId - ID for a custom file entry
1047             *         type </li> <li> fieldsMap - mapping for fields associated with a
1048             *         custom file entry type </li> </ul>
1049             * @return the file entry
1050             */
1051            @Override
1052            public FileEntry updateFileEntry(
1053                            long userId, long fileEntryId, String sourceFileName,
1054                            String mimeType, String title, String description, String changeLog,
1055                            boolean majorVersion, InputStream is, long size,
1056                            ServiceContext serviceContext)
1057                    throws PortalException {
1058    
1059                    if (Validator.isNull(mimeType) ||
1060                            mimeType.equals(ContentTypes.APPLICATION_OCTET_STREAM)) {
1061    
1062                            String extension = DLAppUtil.getExtension(title, sourceFileName);
1063    
1064                            if (size == 0) {
1065                                    mimeType = MimeTypesUtil.getExtensionContentType(extension);
1066                            }
1067                            else {
1068                                    File file = null;
1069    
1070                                    try {
1071                                            file = FileUtil.createTempFile(is);
1072    
1073                                            return updateFileEntry(
1074                                                    userId, fileEntryId, sourceFileName, mimeType, title,
1075                                                    description, changeLog, majorVersion, file,
1076                                                    serviceContext);
1077                                    }
1078                                    catch (IOException ioe) {
1079                                            throw new SystemException(
1080                                                    "Unable to write temporary file", ioe);
1081                                    }
1082                                    finally {
1083                                            FileUtil.delete(file);
1084                                    }
1085                            }
1086                    }
1087    
1088                    LocalRepository localRepository =
1089                            repositoryProvider.getFileEntryLocalRepository(fileEntryId);
1090    
1091                    FileEntry fileEntry = localRepository.updateFileEntry(
1092                            userId, fileEntryId, sourceFileName, mimeType, title, description,
1093                            changeLog, majorVersion, is, size, serviceContext);
1094    
1095                    dlAppHelperLocalService.updateFileEntry(
1096                            userId, fileEntry, null, fileEntry.getFileVersion(),
1097                            serviceContext);
1098    
1099                    return fileEntry;
1100            }
1101    
1102            /**
1103             * Updates a file rank to the existing file entry. This method is only
1104             * supported by the Liferay repository.
1105             *
1106             * @param  repositoryId the primary key of the file rank's repository
1107             * @param  companyId the primary key of the file rank's company
1108             * @param  userId the primary key of the file rank's creator/owner
1109             * @param  fileEntryId the primary key of the file rank's file entry
1110             * @param  serviceContext the service context to be applied
1111             * @return the file rank
1112             */
1113            @Override
1114            public DLFileRank updateFileRank(
1115                    long repositoryId, long companyId, long userId, long fileEntryId,
1116                    ServiceContext serviceContext) {
1117    
1118                    return dlFileRankLocalService.updateFileRank(
1119                            repositoryId, companyId, userId, fileEntryId, serviceContext);
1120            }
1121    
1122            /**
1123             * Updates a file shortcut to the existing file entry. This method is only
1124             * supported by the Liferay repository.
1125             *
1126             * @param  userId the primary key of the file shortcut's creator/owner
1127             * @param  fileShortcutId the primary key of the file shortcut
1128             * @param  folderId the primary key of the file shortcut's parent folder
1129             * @param  toFileEntryId the primary key of the file shortcut's file entry
1130             * @param  serviceContext the service context to be applied. Can set the
1131             *         asset category IDs, asset tag names, and expando bridge
1132             *         attributes for the file entry.
1133             * @return the file shortcut
1134             */
1135            @Override
1136            public FileShortcut updateFileShortcut(
1137                            long userId, long fileShortcutId, long folderId, long toFileEntryId,
1138                            ServiceContext serviceContext)
1139                    throws PortalException {
1140    
1141                    LocalRepository localRepository =
1142                            repositoryProvider.getFileShortcutLocalRepository(fileShortcutId);
1143    
1144                    return localRepository.updateFileShortcut(
1145                            userId, fileShortcutId, folderId, toFileEntryId, serviceContext);
1146            }
1147    
1148            /**
1149             * Updates all file shortcuts to the existing file entry to the new file
1150             * entry. This method is only supported by the Liferay repository.
1151             *
1152             * @param oldToFileEntryId the primary key of the old file entry pointed to
1153             * @param newToFileEntryId the primary key of the new file entry to point to
1154             */
1155            @Override
1156            public void updateFileShortcuts(
1157                            long oldToFileEntryId, long newToFileEntryId)
1158                    throws PortalException {
1159    
1160                    LocalRepository localRepository =
1161                            repositoryProvider.getFileEntryLocalRepository(newToFileEntryId);
1162    
1163                    localRepository.updateFileShortcuts(oldToFileEntryId, newToFileEntryId);
1164            }
1165    
1166            /**
1167             * Deprecated as of 7.0.0, replaced by {@link #updateFileShortcuts(long,
1168             * long)}
1169             */
1170            @Deprecated
1171            @Override
1172            public void updateFileShortcuts(
1173                            long toRepositoryId, long oldToFileEntryId, long newToFileEntryId)
1174                    throws PortalException {
1175    
1176                    updateFileShortcuts(oldToFileEntryId, newToFileEntryId);
1177            }
1178    
1179            /**
1180             * Updates the folder.
1181             *
1182             * @param  folderId the primary key of the folder
1183             * @param  parentFolderId the primary key of the folder's new parent folder
1184             * @param  name the folder's new name
1185             * @param  description the folder's new description
1186             * @param  serviceContext the service context to be applied. In a Liferay
1187             *         repository, it may include:  <ul> <li> defaultFileEntryTypeId -
1188             *         the file entry type to default all Liferay file entries to </li>
1189             *         <li> dlFileEntryTypesSearchContainerPrimaryKeys - a
1190             *         comma-delimited list of file entry type primary keys allowed in
1191             *         the given folder and all descendants </li> <li> restrictionType -
1192             *         specifying restriction type of file entry types allowed </li>
1193             *         <li> workflowDefinitionXYZ - the workflow definition name
1194             *         specified per file entry type. The parameter name must be the
1195             *         string <code>workflowDefinition</code> appended by the
1196             *         <code>fileEntryTypeId</code> (optionally <code>0</code>).</li>
1197             *         </ul>
1198             * @return the folder
1199             */
1200            @Override
1201            public Folder updateFolder(
1202                            long folderId, long parentFolderId, String name, String description,
1203                            ServiceContext serviceContext)
1204                    throws PortalException {
1205    
1206                    LocalRepository localRepository =
1207                            repositoryProvider.getFolderLocalRepository(folderId);
1208    
1209                    Folder folder = localRepository.updateFolder(
1210                            folderId, parentFolderId, name, description, serviceContext);
1211    
1212                    if (folderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
1213                            dlAppHelperLocalService.updateFolder(
1214                                    serviceContext.getUserId(), folder, serviceContext);
1215                    }
1216    
1217                    return folder;
1218            }
1219    
1220            protected FileEntry copyFileEntry(
1221                            long userId, LocalRepository toLocalRepository, FileEntry fileEntry,
1222                            long newFolderId, ServiceContext serviceContext)
1223                    throws PortalException {
1224    
1225                    List<FileVersion> fileVersions = fileEntry.getFileVersions(
1226                            WorkflowConstants.STATUS_ANY);
1227    
1228                    FileVersion latestFileVersion = fileVersions.get(
1229                            fileVersions.size() - 1);
1230    
1231                    String sourceFileName = DLAppUtil.getSourceFileName(latestFileVersion);
1232    
1233                    FileEntry destinationFileEntry = toLocalRepository.addFileEntry(
1234                            userId, newFolderId, sourceFileName,
1235                            latestFileVersion.getMimeType(), latestFileVersion.getTitle(),
1236                            latestFileVersion.getDescription(), StringPool.BLANK,
1237                            latestFileVersion.getContentStream(false),
1238                            latestFileVersion.getSize(), serviceContext);
1239    
1240                    for (int i = fileVersions.size() - 2; i >= 0; i--) {
1241                            FileVersion fileVersion = fileVersions.get(i);
1242    
1243                            sourceFileName = DLAppUtil.getSourceFileName(fileVersion);
1244    
1245                            FileVersion previousFileVersion = fileVersions.get(i + 1);
1246    
1247                            try {
1248                                    destinationFileEntry = toLocalRepository.updateFileEntry(
1249                                            userId, destinationFileEntry.getFileEntryId(),
1250                                            sourceFileName, destinationFileEntry.getMimeType(),
1251                                            destinationFileEntry.getTitle(),
1252                                            destinationFileEntry.getDescription(), StringPool.BLANK,
1253                                            DLAppUtil.isMajorVersion(fileVersion, previousFileVersion),
1254                                            fileVersion.getContentStream(false), fileVersion.getSize(),
1255                                            serviceContext);
1256                            }
1257                            catch (PortalException pe) {
1258                                    toLocalRepository.deleteFileEntry(
1259                                            destinationFileEntry.getFileEntryId());
1260    
1261                                    throw pe;
1262                            }
1263                    }
1264    
1265                    return destinationFileEntry;
1266            }
1267    
1268            protected void deleteFileEntry(
1269                            long oldFileEntryId, long newFileEntryId,
1270                            LocalRepository fromLocalRepository,
1271                            LocalRepository toLocalRepository)
1272                    throws PortalException {
1273    
1274                    try {
1275                            FileEntry fileEntry = fromLocalRepository.getFileEntry(
1276                                    oldFileEntryId);
1277    
1278                            fromLocalRepository.deleteFileEntry(oldFileEntryId);
1279    
1280                            dlAppHelperLocalService.deleteFileEntry(fileEntry);
1281                    }
1282                    catch (PortalException pe) {
1283                            FileEntry fileEntry = toLocalRepository.getFileEntry(
1284                                    newFileEntryId);
1285    
1286                            toLocalRepository.deleteFileEntry(newFileEntryId);
1287    
1288                            dlAppHelperLocalService.deleteFileEntry(fileEntry);
1289    
1290                            throw pe;
1291                    }
1292            }
1293    
1294            protected void deleteRepository(LocalRepository localRepository)
1295                    throws PortalException {
1296    
1297                    long repositoryId = localRepository.getRepositoryId();
1298    
1299                    dlAppHelperLocalService.deleteRepositoryFileEntries(repositoryId);
1300    
1301                    localRepository.deleteAll();
1302    
1303                    repositoryLocalService.deleteRepository(repositoryId);
1304            }
1305    
1306            protected LocalRepository getFolderLocalRepository(
1307                            long folderId, long groupId)
1308                    throws PortalException {
1309    
1310                    if (folderId == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
1311                            return getLocalRepository(groupId);
1312                    }
1313    
1314                    return repositoryProvider.getFolderLocalRepository(folderId);
1315            }
1316    
1317            protected LocalRepository getLocalRepository(long repositoryId)
1318                    throws PortalException {
1319    
1320                    try {
1321                            return repositoryProvider.getLocalRepository(repositoryId);
1322                    }
1323                    catch (InvalidRepositoryIdException irie) {
1324                            StringBundler sb = new StringBundler(3);
1325    
1326                            sb.append("No Group exists with the key {repositoryId=");
1327                            sb.append(repositoryId);
1328                            sb.append("}");
1329    
1330                            throw new NoSuchGroupException(sb.toString(), irie);
1331                    }
1332            }
1333    
1334            protected FileEntry moveFileEntries(
1335                            long userId, long fileEntryId, long newFolderId,
1336                            LocalRepository fromLocalRepository,
1337                            LocalRepository toLocalRepository, ServiceContext serviceContext)
1338                    throws PortalException {
1339    
1340                    FileEntry sourceFileEntry = fromLocalRepository.getFileEntry(
1341                            fileEntryId);
1342    
1343                    FileEntry destinationFileEntry = copyFileEntry(
1344                            userId, toLocalRepository, sourceFileEntry, newFolderId,
1345                            serviceContext);
1346    
1347                    deleteFileEntry(
1348                            fileEntryId, destinationFileEntry.getFileEntryId(),
1349                            fromLocalRepository, toLocalRepository);
1350    
1351                    return destinationFileEntry;
1352            }
1353    
1354            protected Folder moveFolders(
1355                            long userId, long folderId, long parentFolderId,
1356                            LocalRepository sourceLocalRepository,
1357                            LocalRepository destinationLocalRepository,
1358                            ServiceContext serviceContext)
1359                    throws PortalException {
1360    
1361                    Folder sourceFolder = sourceLocalRepository.getFolder(folderId);
1362    
1363                    Folder destinationFolder = destinationLocalRepository.addFolder(
1364                            userId, parentFolderId, sourceFolder.getName(),
1365                            sourceFolder.getDescription(), serviceContext);
1366    
1367                    dlAppHelperLocalService.addFolder(
1368                            userId, destinationFolder, serviceContext);
1369    
1370                    List<RepositoryEntry> foldersAndFileEntriesAndFileShortcuts =
1371                            sourceLocalRepository.getFoldersAndFileEntriesAndFileShortcuts(
1372                                    folderId, WorkflowConstants.STATUS_ANY, true, QueryUtil.ALL_POS,
1373                                    QueryUtil.ALL_POS, null);
1374    
1375                    try {
1376                            for (RepositoryEntry folderAndFileEntryAndFileShortcut :
1377                                            foldersAndFileEntriesAndFileShortcuts) {
1378    
1379                                    if (folderAndFileEntryAndFileShortcut instanceof FileEntry) {
1380                                            FileEntry fileEntry =
1381                                                    (FileEntry)folderAndFileEntryAndFileShortcut;
1382    
1383                                            moveFileEntry(
1384                                                    userId, fileEntry.getFileEntryId(),
1385                                                    destinationFolder.getFolderId(), serviceContext);
1386                                    }
1387                                    else if (folderAndFileEntryAndFileShortcut instanceof Folder) {
1388                                            Folder folder = (Folder)folderAndFileEntryAndFileShortcut;
1389    
1390                                            moveFolders(
1391                                                    userId, folder.getFolderId(),
1392                                                    destinationFolder.getFolderId(), sourceLocalRepository,
1393                                                    destinationLocalRepository, serviceContext);
1394                                    }
1395                                    else if (folderAndFileEntryAndFileShortcut
1396                                                            instanceof FileShortcut) {
1397    
1398                                            if (destinationFolder.isSupportsShortcuts()) {
1399                                                    FileShortcut fileShortcut =
1400                                                            (FileShortcut)folderAndFileEntryAndFileShortcut;
1401    
1402                                                    destinationLocalRepository.addFileShortcut(
1403                                                            userId, destinationFolder.getFolderId(),
1404                                                            fileShortcut.getToFileEntryId(), serviceContext);
1405                                            }
1406                                    }
1407                            }
1408                    }
1409                    catch (PortalException pe) {
1410                            int fileEntriesAndFileShortcutsCount =
1411                                    destinationLocalRepository.getFileEntriesAndFileShortcutsCount(
1412                                            destinationFolder.getFolderId(),
1413                                            WorkflowConstants.STATUS_ANY);
1414    
1415                            if (fileEntriesAndFileShortcutsCount == 0) {
1416                                    destinationLocalRepository.deleteFolder(
1417                                            destinationFolder.getFolderId());
1418                            }
1419    
1420                            throw pe;
1421                    }
1422    
1423                    try {
1424                            sourceLocalRepository.deleteFolder(folderId);
1425                    }
1426                    catch (PortalException pe) {
1427                            destinationLocalRepository.deleteFolder(
1428                                    destinationFolder.getFolderId());
1429    
1430                            throw pe;
1431                    }
1432    
1433                    return destinationFolder;
1434            }
1435    
1436            @BeanReference(type = RepositoryProvider.class)
1437            protected RepositoryProvider repositoryProvider;
1438    
1439            private static final Log _log = LogFactoryUtil.getLog(
1440                    DLAppLocalServiceImpl.class);
1441    
1442    }