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