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