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