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