1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portlet.documentlibrary.service.impl;
16  
17  import com.liferay.documentlibrary.DuplicateFileException;
18  import com.liferay.documentlibrary.FileSizeException;
19  import com.liferay.documentlibrary.NoSuchFileException;
20  import com.liferay.documentlibrary.util.JCRHook;
21  import com.liferay.portal.kernel.exception.PortalException;
22  import com.liferay.portal.kernel.exception.SystemException;
23  import com.liferay.portal.kernel.io.unsync.UnsyncBufferedInputStream;
24  import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayInputStream;
25  import com.liferay.portal.kernel.log.Log;
26  import com.liferay.portal.kernel.log.LogFactoryUtil;
27  import com.liferay.portal.kernel.search.Indexer;
28  import com.liferay.portal.kernel.search.IndexerRegistryUtil;
29  import com.liferay.portal.kernel.util.GetterUtil;
30  import com.liferay.portal.kernel.util.MimeTypesUtil;
31  import com.liferay.portal.kernel.util.OrderByComparator;
32  import com.liferay.portal.kernel.util.StringPool;
33  import com.liferay.portal.kernel.util.StringUtil;
34  import com.liferay.portal.kernel.util.Validator;
35  import com.liferay.portal.kernel.workflow.StatusConstants;
36  import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
37  import com.liferay.portal.model.Resource;
38  import com.liferay.portal.model.ResourceConstants;
39  import com.liferay.portal.model.User;
40  import com.liferay.portal.service.ServiceContext;
41  import com.liferay.portal.util.PortalUtil;
42  import com.liferay.portal.util.PortletKeys;
43  import com.liferay.portal.util.PropsValues;
44  import com.liferay.portlet.documentlibrary.DuplicateFolderNameException;
45  import com.liferay.portlet.documentlibrary.NoSuchFileEntryException;
46  import com.liferay.portlet.documentlibrary.NoSuchFolderException;
47  import com.liferay.portlet.documentlibrary.model.DLFileEntry;
48  import com.liferay.portlet.documentlibrary.model.DLFileEntryConstants;
49  import com.liferay.portlet.documentlibrary.model.DLFileShortcut;
50  import com.liferay.portlet.documentlibrary.model.DLFileVersion;
51  import com.liferay.portlet.documentlibrary.model.DLFolder;
52  import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
53  import com.liferay.portlet.documentlibrary.model.impl.DLFileEntryImpl;
54  import com.liferay.portlet.documentlibrary.service.base.DLFileEntryLocalServiceBaseImpl;
55  import com.liferay.portlet.documentlibrary.social.DLActivityKeys;
56  import com.liferay.portlet.documentlibrary.util.DLUtil;
57  import com.liferay.portlet.documentlibrary.util.comparator.FileEntryModifiedDateComparator;
58  import com.liferay.portlet.messageboards.model.MBDiscussion;
59  import com.liferay.portlet.ratings.model.RatingsEntry;
60  import com.liferay.portlet.ratings.model.RatingsStats;
61  
62  import java.io.File;
63  import java.io.FileInputStream;
64  import java.io.FileNotFoundException;
65  import java.io.InputStream;
66  
67  import java.util.Date;
68  import java.util.List;
69  
70  /**
71   * <a href="DLFileEntryLocalServiceImpl.java.html"><b><i>View Source</i></b></a>
72   *
73   * <p>
74   * For DLFileEntries, the naming convention for some of the variables is not
75   * very informative, due to legacy code. Each DLFileEntry has a corresponding
76   * name and title. The "name" is a unique identifier for a given file and
77   * usually follows the format "1234" whereas the "title" is the actual name
78   * specified by the user (e.g., "Budget.xls").
79   * </p>
80   *
81   * @author Brian Wing Shun Chan
82   * @author Harry Mark
83   */
84  public class DLFileEntryLocalServiceImpl
85      extends DLFileEntryLocalServiceBaseImpl {
86  
87      public DLFileEntry addFileEntry(
88              String uuid, long userId, long groupId, long folderId, String name,
89              String title, String description, String versionDescription,
90              String extraSettings, byte[] bytes, ServiceContext serviceContext)
91          throws PortalException, SystemException {
92  
93          if (!PropsValues.WEBDAV_LITMUS) {
94              if (bytes == null) {
95                  throw new FileSizeException();
96              }
97          }
98  
99          InputStream is = new UnsyncByteArrayInputStream(bytes);
100 
101         return addFileEntry(
102             uuid, userId, groupId, folderId, name, title, description,
103             versionDescription, extraSettings, is, bytes.length,
104             serviceContext);
105     }
106 
107     public DLFileEntry addFileEntry(
108             String uuid, long userId, long groupId, long folderId, String name,
109             String title, String description, String versionDescription,
110             String extraSettings, File file, ServiceContext serviceContext)
111         throws PortalException, SystemException {
112 
113         if (!PropsValues.WEBDAV_LITMUS) {
114             if (file == null) {
115                 throw new FileSizeException();
116             }
117         }
118 
119         try {
120             InputStream is = new UnsyncBufferedInputStream(
121                 new FileInputStream(file));
122 
123             return addFileEntry(
124                 uuid, userId, groupId, folderId, name, title, description,
125                 versionDescription, extraSettings, is, file.length(),
126                 serviceContext);
127         }
128         catch (FileNotFoundException fnfe) {
129             throw new FileSizeException();
130         }
131     }
132 
133     public DLFileEntry addFileEntry(
134             String uuid, long userId, long groupId, long folderId, String name,
135             String title, String description, String versionDescription,
136             String extraSettings, InputStream is, long size,
137             ServiceContext serviceContext)
138         throws PortalException, SystemException {
139 
140         // File entry
141 
142         User user = userPersistence.findByPrimaryKey(userId);
143         folderId = getFolderId(user.getCompanyId(), folderId);
144         Date now = new Date();
145 
146         if (Validator.isNull(title)) {
147             title = name;
148         }
149 
150         name = String.valueOf(
151             counterLocalService.increment(DLFileEntry.class.getName()));
152 
153         validate(groupId, folderId, title, is);
154 
155         long fileEntryId = counterLocalService.increment();
156 
157         DLFileEntry fileEntry = dlFileEntryPersistence.create(fileEntryId);
158 
159         fileEntry.setUuid(uuid);
160         fileEntry.setGroupId(groupId);
161         fileEntry.setCompanyId(user.getCompanyId());
162         fileEntry.setUserId(user.getUserId());
163         fileEntry.setUserName(user.getFullName());
164         fileEntry.setVersionUserId(user.getUserId());
165         fileEntry.setVersionUserName(user.getFullName());
166         fileEntry.setCreateDate(now);
167         fileEntry.setModifiedDate(now);
168         fileEntry.setFolderId(folderId);
169         fileEntry.setName(name);
170         fileEntry.setTitle(title);
171         fileEntry.setDescription(description);
172 
173         if (serviceContext.getStatus() == StatusConstants.APPROVED) {
174             fileEntry.setVersion(DLFileEntryConstants.DEFAULT_VERSION);
175         }
176         else {
177             fileEntry.setVersion(StringPool.BLANK);
178         }
179 
180         fileEntry.setSize((int)size);
181         fileEntry.setReadCount(DLFileEntryConstants.DEFAULT_READ_COUNT);
182         fileEntry.setExtraSettings(extraSettings);
183         fileEntry.setExpandoBridgeAttributes(serviceContext);
184 
185         dlFileEntryPersistence.update(fileEntry, false);
186 
187         // Resources
188 
189         if (serviceContext.getAddCommunityPermissions() ||
190                 serviceContext.getAddGuestPermissions()) {
191 
192             addFileEntryResources(
193                 fileEntry, serviceContext.getAddCommunityPermissions(),
194                 serviceContext.getAddGuestPermissions());
195         }
196         else {
197             addFileEntryResources(
198                 fileEntry, serviceContext.getCommunityPermissions(),
199                 serviceContext.getGuestPermissions());
200         }
201 
202         // File version
203 
204         addFileVersion(
205             user, fileEntry, fileEntry.getVersion(), null,
206             serviceContext.getStatus());
207 
208         // Folder
209 
210         if (folderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
211             DLFolder folder = dlFolderPersistence.findByPrimaryKey(folderId);
212 
213             folder.setLastPostDate(fileEntry.getModifiedDate());
214 
215             dlFolderPersistence.update(folder, false);
216         }
217 
218         // Asset
219 
220         updateAsset(
221             userId, fileEntry, serviceContext.getAssetCategoryIds(),
222             serviceContext.getAssetTagNames());
223 
224         // Message boards
225 
226         if (PropsValues.DL_FILE_ENTRY_COMMENTS_ENABLED) {
227             mbMessageLocalService.addDiscussionMessage(
228                 userId, fileEntry.getUserName(), DLFileEntry.class.getName(),
229                 fileEntryId, StatusConstants.APPROVED);
230         }
231 
232         // File
233 
234         dlLocalService.addFile(
235             user.getCompanyId(), PortletKeys.DOCUMENT_LIBRARY,
236             fileEntry.getGroupId(), fileEntry.getRepositoryId(), name, false,
237             fileEntryId, fileEntry.getLuceneProperties(),
238             fileEntry.getModifiedDate(), serviceContext, is);
239 
240         // Workflow
241 
242         if (serviceContext.isStartWorkflow()) {
243             try {
244                 WorkflowHandlerRegistryUtil.startWorkflowInstance(
245                     user.getCompanyId(), groupId, userId,
246                     DLFileEntry.class.getName(), fileEntryId, fileEntry);
247             }
248             catch (Exception e) {
249                 throw new SystemException(e);
250             }
251         }
252 
253         return fileEntry;
254     }
255 
256     public void addFileEntryResources(
257             DLFileEntry fileEntry, boolean addCommunityPermissions,
258             boolean addGuestPermissions)
259         throws PortalException, SystemException {
260 
261         resourceLocalService.addResources(
262             fileEntry.getCompanyId(), fileEntry.getGroupId(),
263             fileEntry.getUserId(), DLFileEntry.class.getName(),
264             fileEntry.getFileEntryId(), false, addCommunityPermissions,
265             addGuestPermissions);
266     }
267 
268     public void addFileEntryResources(
269             DLFileEntry fileEntry, String[] communityPermissions,
270             String[] guestPermissions)
271         throws PortalException, SystemException {
272 
273         resourceLocalService.addModelResources(
274             fileEntry.getCompanyId(), fileEntry.getGroupId(),
275             fileEntry.getUserId(), DLFileEntry.class.getName(),
276             fileEntry.getFileEntryId(), communityPermissions, guestPermissions);
277     }
278 
279     public void addFileEntryResources(
280             long fileEntryId, boolean addCommunityPermissions,
281             boolean addGuestPermissions)
282         throws PortalException, SystemException {
283 
284         DLFileEntry fileEntry = dlFileEntryPersistence.findByPrimaryKey(
285             fileEntryId);
286 
287         addFileEntryResources(
288             fileEntry, addCommunityPermissions, addGuestPermissions);
289     }
290 
291     public void addFileEntryResources(
292             long fileEntryId, String[] communityPermissions,
293             String[] guestPermissions)
294         throws PortalException, SystemException {
295 
296         DLFileEntry fileEntry = dlFileEntryPersistence.findByPrimaryKey(
297             fileEntryId);
298 
299         addFileEntryResources(
300             fileEntry, communityPermissions, guestPermissions);
301     }
302 
303     public DLFileEntry addOrOverwriteFileEntry(
304             long userId, long groupId, long folderId, String name,
305             String sourceName, String title, String description,
306             String versionDescription, String extraSettings, File file,
307             ServiceContext serviceContext)
308         throws PortalException, SystemException {
309 
310         try {
311             dlFileEntryPersistence.findByG_F_T(groupId, folderId, title);
312 
313             return updateFileEntry(
314                 userId, groupId, folderId, folderId, name, sourceName, title,
315                 description, versionDescription, false, extraSettings, file,
316                 serviceContext);
317         }
318         catch (NoSuchFileEntryException nsfee) {
319             return addFileEntry(
320                 null, userId, groupId, folderId, name, title, description,
321                 versionDescription, extraSettings, file, serviceContext);
322         }
323     }
324 
325     public void deleteFileEntries(long groupId, long folderId)
326         throws PortalException, SystemException {
327 
328         List<DLFileEntry> fileEntries = dlFileEntryPersistence.findByG_F(
329             groupId, folderId);
330 
331         for (DLFileEntry fileEntry : fileEntries) {
332             deleteFileEntry(fileEntry);
333         }
334     }
335 
336     public void deleteFileEntry(DLFileEntry fileEntry)
337         throws PortalException, SystemException {
338 
339         // File entry
340 
341         dlFileEntryPersistence.remove(fileEntry);
342 
343         // Resources
344 
345         resourceLocalService.deleteResource(
346             fileEntry.getCompanyId(), DLFileEntry.class.getName(),
347             ResourceConstants.SCOPE_INDIVIDUAL, fileEntry.getFileEntryId());
348 
349         // WebDAVProps
350 
351         webDAVPropsLocalService.deleteWebDAVProps(
352             DLFileEntry.class.getName(), fileEntry.getFileEntryId());
353 
354         // Workflow
355 
356         workflowInstanceLinkLocalService.deleteWorkflowInstanceLink(
357             fileEntry.getCompanyId(), fileEntry.getGroupId(),
358             DLFileEntry.class.getName(), fileEntry.getFileEntryId());
359 
360         // File ranks
361 
362         dlFileRankLocalService.deleteFileRanks(
363             fileEntry.getFolderId(), fileEntry.getName());
364 
365         // File shortcuts
366 
367         dlFileShortcutLocalService.deleteFileShortcuts(
368             fileEntry.getGroupId(), fileEntry.getFolderId(),
369             fileEntry.getName());
370 
371         // File versions
372 
373         List<DLFileVersion> fileVersions = dlFileVersionPersistence.findByG_F_N(
374             fileEntry.getGroupId(), fileEntry.getFolderId(),
375             fileEntry.getName());
376 
377         for (DLFileVersion fileVersion : fileVersions) {
378             dlFileVersionPersistence.remove(fileVersion);
379         }
380 
381         // Asset
382 
383         assetEntryLocalService.deleteEntry(
384             DLFileEntry.class.getName(), fileEntry.getFileEntryId());
385 
386         // Expando
387 
388         expandoValueLocalService.deleteValues(
389             DLFileEntry.class.getName(), fileEntry.getFileEntryId());
390 
391         // Message boards
392 
393         mbMessageLocalService.deleteDiscussionMessages(
394             DLFileEntry.class.getName(), fileEntry.getFileEntryId());
395 
396         // Ratings
397 
398         ratingsStatsLocalService.deleteStats(
399             DLFileEntry.class.getName(), fileEntry.getFileEntryId());
400 
401         // Social
402 
403         socialActivityLocalService.deleteActivities(
404             DLFileEntry.class.getName(), fileEntry.getFileEntryId());
405 
406         // File
407 
408         try {
409             dlService.deleteFile(
410                 fileEntry.getCompanyId(), PortletKeys.DOCUMENT_LIBRARY,
411                 fileEntry.getRepositoryId(), fileEntry.getName());
412         }
413         catch (Exception e) {
414             if (_log.isWarnEnabled()) {
415                 _log.warn(e, e);
416             }
417         }
418     }
419 
420     public void deleteFileEntry(long groupId, long folderId, String name)
421         throws PortalException, SystemException {
422 
423         deleteFileEntry(groupId, folderId, name, null);
424     }
425 
426     public void deleteFileEntry(
427             long groupId, long folderId, String name, String version)
428         throws PortalException, SystemException {
429 
430         DLFileEntry fileEntry = dlFileEntryPersistence.findByG_F_N(
431             groupId, folderId, name);
432 
433         if (Validator.isNotNull(version)) {
434             try {
435                 dlService.deleteFile(
436                     fileEntry.getCompanyId(), PortletKeys.DOCUMENT_LIBRARY,
437                     fileEntry.getRepositoryId(), fileEntry.getName(), version);
438             }
439             catch (Exception e) {
440                 if (_log.isWarnEnabled()) {
441                     _log.warn(e, e);
442                 }
443             }
444 
445             dlFileVersionPersistence.removeByG_F_N_V(
446                 groupId, folderId, name, version);
447         }
448         else {
449             deleteFileEntry(fileEntry);
450         }
451     }
452 
453     public List<DLFileEntry> getCompanyFileEntries(
454             long companyId, int start, int end)
455         throws SystemException {
456 
457         return dlFileEntryPersistence.findByCompanyId(companyId, start, end);
458     }
459 
460     public List<DLFileEntry> getCompanyFileEntries(
461             long companyId, int start, int end, OrderByComparator obc)
462         throws SystemException {
463 
464         return dlFileEntryPersistence.findByCompanyId(
465             companyId, start, end, obc);
466     }
467 
468     public int getCompanyFileEntriesCount(long companyId)
469         throws SystemException {
470 
471         return dlFileEntryPersistence.countByCompanyId(companyId);
472     }
473 
474     public InputStream getFileAsStream(
475             long companyId, long userId, long groupId, long folderId,
476             String name)
477         throws PortalException, SystemException {
478 
479         return getFileAsStream(
480             companyId, userId, groupId, folderId, name, StringPool.BLANK);
481     }
482 
483     public InputStream getFileAsStream(
484             long companyId, long userId, long groupId, long folderId,
485             String name, String version)
486         throws PortalException, SystemException {
487 
488         DLFileEntry fileEntry = dlFileEntryPersistence.findByG_F_N(
489             groupId, folderId, name);
490 
491         if (userId > 0) {
492             dlFileRankLocalService.updateFileRank(
493                 groupId, companyId, userId, folderId, name);
494         }
495 
496         fileEntry.setReadCount(fileEntry.getReadCount() + 1);
497 
498         dlFileEntryPersistence.update(fileEntry, false);
499 
500         assetEntryLocalService.incrementViewCounter(
501             DLFileEntry.class.getName(), fileEntry.getFileEntryId());
502 
503         List<DLFileShortcut> fileShortcuts =
504             dlFileShortcutPersistence.findByG_TF_TN(groupId, folderId, name);
505 
506         for (DLFileShortcut fileShortcut : fileShortcuts) {
507             assetEntryLocalService.incrementViewCounter(
508                 DLFileShortcut.class.getName(),
509                 fileShortcut.getFileShortcutId());
510         }
511 
512         if (Validator.isNotNull(version)) {
513             return dlLocalService.getFileAsStream(
514                 companyId, fileEntry.getRepositoryId(), name, version);
515         }
516         else {
517             return dlLocalService.getFileAsStream(
518                 companyId, fileEntry.getRepositoryId(), name,
519                 fileEntry.getVersion());
520         }
521     }
522 
523     public List<DLFileEntry> getFileEntries(long groupId, long folderId)
524         throws SystemException {
525 
526         return dlFileEntryPersistence.findByG_F(groupId, folderId);
527     }
528 
529     public List<DLFileEntry> getFileEntries(
530             long groupId, long folderId, int start, int end)
531         throws SystemException {
532 
533         return dlFileEntryPersistence.findByG_F(groupId, folderId, start, end);
534     }
535 
536     public List<DLFileEntry> getFileEntries(
537             long groupId, long folderId, int start, int end,
538             OrderByComparator obc)
539         throws SystemException {
540 
541         return dlFileEntryPersistence.findByG_F(
542             groupId, folderId, start, end, obc);
543     }
544 
545     public int getFileEntriesCount(long groupId, long folderId)
546         throws SystemException {
547 
548         return dlFileEntryPersistence.countByG_F(groupId, folderId);
549     }
550 
551     public DLFileEntry getFileEntry(long fileEntryId)
552         throws PortalException, SystemException {
553 
554         return dlFileEntryPersistence.findByPrimaryKey(fileEntryId);
555     }
556 
557     public DLFileEntry getFileEntry(long groupId, long folderId, String name)
558         throws PortalException, SystemException {
559 
560         return dlFileEntryPersistence.findByG_F_N(groupId, folderId, name);
561     }
562 
563     public DLFileEntry getFileEntryByTitle(
564             long groupId, long folderId, String title)
565         throws PortalException, SystemException {
566 
567         return dlFileEntryPersistence.findByG_F_T(groupId, folderId, title);
568     }
569 
570     public DLFileEntry getFileEntryByUuidAndGroupId(String uuid, long groupId)
571         throws PortalException, SystemException {
572 
573         return dlFileEntryPersistence.findByUUID_G(uuid, groupId);
574     }
575 
576     public int getFoldersFileEntriesCount(
577             long groupId, List<Long> folderIds, int status)
578         throws SystemException {
579 
580         if (folderIds.size() <= PropsValues.SQL_DATA_MAX_PARAMETERS) {
581             return dlFileEntryFinder.countByG_F_S(groupId, folderIds, status);
582         }
583         else {
584             int start = 0;
585             int end = PropsValues.SQL_DATA_MAX_PARAMETERS;
586 
587             int filesCount = dlFileEntryFinder.countByG_F_S(
588                 groupId, folderIds.subList(start, end), status);
589 
590             folderIds.subList(start, end).clear();
591 
592             filesCount += getFoldersFileEntriesCount(
593                 groupId, folderIds, status);
594 
595             return filesCount;
596         }
597     }
598 
599     public List<DLFileEntry> getGroupFileEntries(
600             long groupId, int start, int end)
601         throws SystemException {
602 
603         return getGroupFileEntries(
604             groupId, start, end, new FileEntryModifiedDateComparator());
605     }
606 
607     public List<DLFileEntry> getGroupFileEntries(
608             long groupId, int start, int end, OrderByComparator obc)
609         throws SystemException {
610 
611         return dlFileEntryPersistence.findByGroupId(groupId, start, end, obc);
612     }
613 
614     public List<DLFileEntry> getGroupFileEntries(
615             long groupId, long userId, int start, int end)
616         throws SystemException {
617 
618         return getGroupFileEntries(
619             groupId, userId, start, end, new FileEntryModifiedDateComparator());
620     }
621 
622     public List<DLFileEntry> getGroupFileEntries(
623             long groupId, long userId, int start, int end,
624             OrderByComparator obc)
625         throws SystemException {
626 
627         if (userId <= 0) {
628             return dlFileEntryPersistence.findByGroupId(
629                 groupId, start, end, obc);
630         }
631         else {
632             return dlFileEntryPersistence.findByG_U(
633                 groupId, userId, start, end, obc);
634         }
635     }
636 
637     public int getGroupFileEntriesCount(long groupId) throws SystemException {
638         return dlFileEntryPersistence.countByGroupId(groupId);
639     }
640 
641     public int getGroupFileEntriesCount(long groupId, long userId)
642         throws SystemException {
643 
644         if (userId <= 0) {
645             return dlFileEntryPersistence.countByGroupId(groupId);
646         }
647         else {
648             return dlFileEntryPersistence.countByG_U(groupId, userId);
649         }
650     }
651 
652     public List<DLFileEntry> getNoAssetFileEntries() throws SystemException {
653         return dlFileEntryFinder.findByNoAssets();
654     }
655 
656     public void updateAsset(
657             long userId, DLFileEntry fileEntry, long[] assetCategoryIds,
658             String[] assetTagNames)
659         throws PortalException, SystemException {
660 
661         String mimeType = MimeTypesUtil.getContentType(fileEntry.getTitle());
662 
663         assetEntryLocalService.updateEntry(
664             userId, fileEntry.getGroupId(), DLFileEntry.class.getName(),
665             fileEntry.getFileEntryId(), assetCategoryIds, assetTagNames, true,
666             null, null, null, null, mimeType, fileEntry.getTitle(),
667             fileEntry.getDescription(), null, null, 0, 0, null, false);
668 
669         List<DLFileShortcut> fileShortcuts =
670             dlFileShortcutPersistence.findByG_TF_TN(
671                 fileEntry.getGroupId(), fileEntry.getFolderId(),
672                 fileEntry.getName());
673 
674         for (DLFileShortcut fileShortcut : fileShortcuts) {
675             assetEntryLocalService.updateEntry(
676                 userId, fileShortcut.getGroupId(),
677                 DLFileShortcut.class.getName(),
678                 fileShortcut.getFileShortcutId(), assetCategoryIds,
679                 assetTagNames, true, null, null, null, null, mimeType,
680                 fileEntry.getTitle(), fileEntry.getDescription(), null, null, 0,
681                 0, null, false);
682         }
683     }
684 
685     public DLFileEntry updateFileEntry(
686             long userId, long groupId, long folderId, long newFolderId,
687             String name, String sourceFileName, String title,
688             String description, String versionDescription, boolean majorVersion,
689             String extraSettings, byte[] bytes, ServiceContext serviceContext)
690         throws PortalException, SystemException {
691 
692         InputStream is = null;
693         long size = 0;
694 
695         if (bytes != null) {
696             is = new UnsyncByteArrayInputStream(bytes);
697             size = bytes.length;
698         }
699 
700         return updateFileEntry(
701             userId, groupId, folderId, newFolderId, name, sourceFileName, title,
702             description, versionDescription, majorVersion, extraSettings, is,
703             size, serviceContext);
704     }
705 
706     public DLFileEntry updateFileEntry(
707             long userId, long groupId, long folderId, long newFolderId,
708             String name, String sourceFileName, String title,
709             String description, String versionDescription, boolean majorVersion,
710             String extraSettings, File file, ServiceContext serviceContext)
711         throws PortalException, SystemException {
712 
713         try {
714             InputStream is = null;
715             long size = 0;
716 
717             if ((file != null) && file.exists()) {
718                 is = new UnsyncBufferedInputStream(new FileInputStream(file));
719                 size = file.length();
720             }
721 
722             return updateFileEntry(
723                 userId, groupId, folderId, newFolderId, name, sourceFileName,
724                 title, description, versionDescription, majorVersion,
725                 extraSettings, is, size, serviceContext);
726         }
727         catch (FileNotFoundException fnfe) {
728             throw new NoSuchFileException();
729         }
730     }
731 
732     public DLFileEntry updateFileEntry(
733             long userId, long groupId, long folderId, long newFolderId,
734             String name, String sourceFileName, String title,
735             String description, String versionDescription, boolean majorVersion,
736             String extraSettings, InputStream is, long size,
737             ServiceContext serviceContext)
738         throws PortalException, SystemException {
739 
740         // File entry
741 
742         User user = userPersistence.findByPrimaryKey(userId);
743         Date now = new Date();
744 
745         if (Validator.isNull(title)) {
746             title = sourceFileName;
747 
748             if (Validator.isNull(title)) {
749                 title = name;
750             }
751         }
752 
753         DLFileEntry fileEntry = dlFileEntryPersistence.findByG_F_N(
754             groupId, folderId, name);
755 
756         validate(
757             groupId, folderId, newFolderId, name, title, sourceFileName, is);
758 
759         fileEntry.setTitle(title);
760         fileEntry.setDescription(description);
761         fileEntry.setExtraSettings(extraSettings);
762         fileEntry.setExpandoBridgeAttributes(serviceContext);
763 
764         dlFileEntryPersistence.update(fileEntry, false);
765 
766         // Move file entry
767 
768         if (folderId != newFolderId) {
769             long oldFileEntryId = fileEntry.getFileEntryId();
770 
771             if (dlLocalService.hasFile(
772                     user.getCompanyId(),
773                     DLFileEntryImpl.getRepositoryId(groupId, newFolderId),
774                     name, StringPool.BLANK)) {
775 
776                 throw new DuplicateFileException(name);
777             }
778 
779             long newFileEntryId = counterLocalService.increment();
780 
781             DLFileEntry newFileEntry = dlFileEntryPersistence.create(
782                 newFileEntryId);
783 
784             newFileEntry.setGroupId(fileEntry.getGroupId());
785             newFileEntry.setCompanyId(fileEntry.getCompanyId());
786             newFileEntry.setUserId(fileEntry.getUserId());
787             newFileEntry.setUserName(fileEntry.getUserName());
788             newFileEntry.setVersionUserId(fileEntry.getVersionUserId());
789             newFileEntry.setVersionUserName(fileEntry.getVersionUserName());
790             newFileEntry.setCreateDate(fileEntry.getCreateDate());
791             newFileEntry.setModifiedDate(fileEntry.getModifiedDate());
792             newFileEntry.setFolderId(newFolderId);
793             newFileEntry.setName(name);
794             newFileEntry.setTitle(fileEntry.getTitle());
795             newFileEntry.setDescription(fileEntry.getDescription());
796             newFileEntry.setVersion(fileEntry.getVersion());
797             newFileEntry.setSize(fileEntry.getSize());
798             newFileEntry.setReadCount(fileEntry.getReadCount());
799             newFileEntry.setExtraSettings(extraSettings);
800 
801             dlFileEntryPersistence.update(newFileEntry, false);
802 
803             dlFileEntryPersistence.remove(fileEntry);
804 
805             List<DLFileVersion> fileVersions =
806                 dlFileVersionPersistence.findByG_F_N(
807                     groupId, folderId, name);
808 
809             for (DLFileVersion fileVersion : fileVersions) {
810                 long newFileVersionId = counterLocalService.increment();
811 
812                 DLFileVersion newFileVersion = dlFileVersionPersistence.create(
813                     newFileVersionId);
814 
815                 newFileVersion.setGroupId(fileVersion.getGroupId());
816                 newFileVersion.setCompanyId(fileVersion.getCompanyId());
817                 newFileVersion.setUserId(fileVersion.getUserId());
818                 newFileVersion.setUserName(fileVersion.getUserName());
819                 newFileVersion.setCreateDate(fileVersion.getCreateDate());
820                 newFileVersion.setFolderId(newFolderId);
821                 newFileVersion.setName(name);
822                 newFileVersion.setVersion(fileVersion.getVersion());
823                 newFileVersion.setSize(fileVersion.getSize());
824                 newFileVersion.setStatus(fileVersion.getStatus());
825                 newFileVersion.setStatusByUserId(userId);
826                 newFileVersion.setStatusByUserName(user.getFullName());
827                 newFileVersion.setStatusDate(now);
828 
829                 dlFileVersionPersistence.update(newFileVersion, false);
830 
831                 dlFileVersionPersistence.remove(fileVersion);
832             }
833 
834             dlFileShortcutLocalService.updateFileShortcuts(
835                 groupId, folderId, name, newFolderId, name);
836 
837             // Resources
838 
839             Resource resource = resourceLocalService.getResource(
840                 fileEntry.getCompanyId(), DLFileEntry.class.getName(),
841                 ResourceConstants.SCOPE_INDIVIDUAL,
842                 String.valueOf(fileEntry.getFileEntryId()));
843 
844             resource.setPrimKey(String.valueOf(newFileEntryId));
845 
846             resourcePersistence.update(resource, false);
847 
848             // Asset
849 
850             assetEntryLocalService.deleteEntry(
851                 DLFileEntry.class.getName(), fileEntry.getFileEntryId());
852 
853             List<DLFileShortcut> fileShortcuts =
854                 dlFileShortcutPersistence.findByG_TF_TN(
855                     groupId, folderId, name);
856 
857             for (DLFileShortcut fileShortcut : fileShortcuts) {
858                 assetEntryLocalService.deleteEntry(
859                     DLFileShortcut.class.getName(),
860                     fileShortcut.getFileShortcutId());
861             }
862 
863             // Expando
864 
865             expandoValueLocalService.deleteValues(
866                 DLFileEntry.class.getName(), fileEntry.getFileEntryId());
867 
868             // Ratings
869 
870             RatingsStats stats = ratingsStatsLocalService.getStats(
871                 DLFileEntry.class.getName(), oldFileEntryId);
872 
873             stats.setClassPK(newFileEntryId);
874 
875             ratingsStatsPersistence.update(stats, false);
876 
877             long classNameId = PortalUtil.getClassNameId(
878                 DLFileEntry.class.getName());
879 
880             List<RatingsEntry> entries = ratingsEntryPersistence.findByC_C(
881                 classNameId, oldFileEntryId);
882 
883             for (RatingsEntry entry : entries) {
884                 entry.setClassPK(newFileEntryId);
885 
886                 ratingsEntryPersistence.update(entry, false);
887             }
888 
889             // Message boards
890 
891             MBDiscussion discussion = mbDiscussionPersistence.fetchByC_C(
892                 classNameId, oldFileEntryId);
893 
894             if (discussion != null) {
895                 discussion.setClassPK(newFileEntryId);
896 
897                 mbDiscussionPersistence.update(discussion, false);
898             }
899 
900             // Social
901 
902             socialActivityLocalService.deleteActivities(
903                 DLFileEntry.class.getName(), fileEntry.getFileEntryId());
904 
905             // File
906 
907             dlService.updateFile(
908                 user.getCompanyId(), PortletKeys.DOCUMENT_LIBRARY,
909                 newFileEntry.getGroupId(), fileEntry.getRepositoryId(),
910                 newFileEntry.getRepositoryId(), name, newFileEntryId);
911 
912             folderId = newFolderId;
913             fileEntry = newFileEntry;
914         }
915 
916         // Asset
917 
918         updateAsset(
919             userId, fileEntry, serviceContext.getAssetCategoryIds(),
920             serviceContext.getAssetTagNames());
921 
922         // File version
923 
924         String version = getNextVersion(fileEntry, majorVersion);
925 
926         if (is == null) {
927             fileEntry.setVersion(version);
928 
929             dlFileEntryPersistence.update(fileEntry, false);
930 
931             int fetchFailures = 0;
932 
933             while (is == null) {
934                 try {
935                     is = dlLocalService.getFileAsStream(
936                         user.getCompanyId(), fileEntry.getRepositoryId(), name);
937                 }
938                 catch (NoSuchFileException nsfe) {
939                     fetchFailures++;
940 
941                     if (PropsValues.DL_HOOK_IMPL.equals(
942                             JCRHook.class.getName()) &&
943                         (fetchFailures <
944                             PropsValues.DL_HOOK_JCR_FETCH_MAX_FAILURES)) {
945 
946                         try {
947                             Thread.sleep(PropsValues.DL_HOOK_JCR_FETCH_DELAY);
948                         }
949                         catch (InterruptedException ie) {
950                         }
951                     }
952                     else {
953                         throw nsfe;
954                     }
955                 }
956             }
957 
958             dlLocalService.updateFile(
959                 user.getCompanyId(), PortletKeys.DOCUMENT_LIBRARY,
960                 fileEntry.getGroupId(), fileEntry.getRepositoryId(), name,
961                 false, version, name, fileEntry.getFileEntryId(),
962                 fileEntry.getLuceneProperties(), fileEntry.getModifiedDate(),
963                 serviceContext, is);
964 
965             return fileEntry;
966         }
967 
968         addFileVersion(
969             user, fileEntry, version, versionDescription,
970             serviceContext.getStatus());
971 
972         // File entry
973 
974         fileEntry.setVersionUserId(user.getUserId());
975         fileEntry.setVersionUserName(user.getFullName());
976         fileEntry.setModifiedDate(new Date());
977         fileEntry.setVersion(version);
978         fileEntry.setSize((int)size);
979         fileEntry.setExpandoBridgeAttributes(serviceContext);
980 
981         dlFileEntryPersistence.update(fileEntry, false);
982 
983         // Folder
984 
985         if (fileEntry.getFolderId() !=
986                 DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
987 
988             DLFolder folder = dlFolderPersistence.findByPrimaryKey(
989                 fileEntry.getFolderId());
990 
991             folder.setLastPostDate(fileEntry.getModifiedDate());
992 
993             dlFolderPersistence.update(folder, false);
994         }
995 
996         // File
997 
998         dlLocalService.updateFile(
999             user.getCompanyId(), PortletKeys.DOCUMENT_LIBRARY,
1000            fileEntry.getGroupId(), fileEntry.getRepositoryId(), name, false,
1001            version, sourceFileName, fileEntry.getFileEntryId(),
1002            fileEntry.getLuceneProperties(), fileEntry.getModifiedDate(),
1003            serviceContext, is);
1004
1005        // Workflow
1006
1007        if (serviceContext.isStartWorkflow()) {
1008            try {
1009                WorkflowHandlerRegistryUtil.startWorkflowInstance(
1010                    user.getCompanyId(), groupId, userId,
1011                    DLFileEntry.class.getName(), fileEntry.getFileEntryId(),
1012                    fileEntry);
1013            }
1014            catch (Exception e) {
1015                throw new SystemException(e);
1016            }
1017        }
1018
1019        return fileEntry;
1020    }
1021
1022    public DLFileEntry updateWorkflowStatus(
1023            long userId, long fileEntryId, ServiceContext serviceContext)
1024        throws PortalException, SystemException {
1025
1026        // File entry
1027
1028        User user = userPersistence.findByPrimaryKey(userId);
1029
1030        DLFileEntry fileEntry = dlFileEntryPersistence.findByPrimaryKey(
1031            fileEntryId);
1032
1033        // File version
1034
1035        DLFileVersion fileVersion =
1036            dlFileVersionLocalService.getLatestFileVersion(
1037                fileEntry.getGroupId(), fileEntry.getFolderId(),
1038                fileEntry.getName());
1039
1040        fileVersion.setStatus(serviceContext.getStatus());
1041        fileVersion.setStatusByUserId(user.getUserId());
1042        fileVersion.setStatusByUserName(user.getFullName());
1043        fileVersion.setStatusDate(new Date());
1044
1045        if (fileVersion.isApproved() &&
1046            (DLUtil.compareVersions(
1047                fileVersion.getVersion(),
1048                DLFileEntryConstants.DEFAULT_VERSION) < 0)) {
1049
1050            fileVersion.setVersion(DLFileEntryConstants.DEFAULT_VERSION);
1051        }
1052
1053        dlFileVersionPersistence.update(fileVersion, false);
1054
1055        // File entry
1056
1057        if (fileVersion.isApproved() &&
1058            (DLUtil.compareVersions(
1059                fileEntry.getVersion(), fileVersion.getVersion()) < 0)) {
1060
1061            fileEntry.setVersion(fileVersion.getVersion());
1062
1063            dlFileEntryPersistence.update(fileEntry, false);
1064        }
1065        else if (!fileVersion.isApproved() &&
1066                 (DLUtil.compareVersions(
1067                    fileEntry.getVersion(), fileVersion.getVersion()) == 0)) {
1068
1069            String newVersion = DLFileEntryConstants.DEFAULT_VERSION;
1070
1071            if (DLUtil.compareVersions(
1072                    fileVersion.getVersion(), newVersion) > 1) {
1073
1074                List<DLFileVersion> approvedFileVersions =
1075                    dlFileVersionPersistence.findByG_F_N_S(
1076                        fileEntry.getGroupId(), fileEntry.getFolderId(),
1077                        fileEntry.getName(), StatusConstants.APPROVED);
1078
1079                if (!approvedFileVersions.isEmpty()) {
1080                    newVersion = approvedFileVersions.get(0).getVersion();
1081                }
1082            }
1083
1084            fileEntry.setPendingVersion(fileVersion.getVersion());
1085            fileEntry.setVersion(newVersion);
1086
1087            dlFileEntryPersistence.update(fileEntry, false);
1088        }
1089
1090        // Asset
1091
1092        if (fileVersion.isApproved() &&
1093            (DLUtil.compareVersions(
1094                fileEntry.getVersion(), fileVersion.getVersion()) == 0)) {
1095
1096            assetEntryLocalService.updateVisible(
1097                DLFileEntry.class.getName(), fileEntry.getFileEntryId(),
1098                true);
1099        }
1100        else if (Validator.isNull(fileEntry.getVersion())) {
1101            assetEntryLocalService.updateVisible(
1102                DLFileEntry.class.getName(), fileEntry.getFileEntryId(),
1103                false);
1104        }
1105
1106        // Social
1107
1108        if (fileVersion.isApproved() &&
1109            (DLUtil.compareVersions(
1110                fileEntry.getVersion(), fileVersion.getVersion()) == 0)) {
1111
1112            if (fileVersion.getVersion().equals(
1113                    DLFileEntryConstants.DEFAULT_VERSION)) {
1114
1115                socialActivityLocalService.addUniqueActivity(
1116                    fileVersion.getUserId(), fileVersion.getGroupId(),
1117                    fileVersion.getCreateDate(), DLFileEntry.class.getName(),
1118                    fileEntryId, DLActivityKeys.ADD_FILE_ENTRY,
1119                    StringPool.BLANK, 0);
1120            }
1121            else {
1122                socialActivityLocalService.addActivity(
1123                    fileVersion.getUserId(), fileVersion.getGroupId(),
1124                    fileVersion.getCreateDate(), DLFileEntry.class.getName(),
1125                    fileEntryId, DLActivityKeys.UPDATE_FILE_ENTRY,
1126                    StringPool.BLANK, 0);
1127            }
1128        }
1129
1130        // Indexer
1131
1132        Indexer indexer = IndexerRegistryUtil.getIndexer(DLFileEntry.class);
1133
1134        if (fileVersion.isApproved() &&
1135            (DLUtil.compareVersions(
1136                fileEntry.getVersion(), fileVersion.getVersion()) == 0)) {
1137
1138            indexer.reindex(fileEntry);
1139        }
1140        else if (Validator.isNull(fileEntry.getVersion())) {
1141            indexer.delete(fileEntry);
1142        }
1143
1144        return fileEntry;
1145    }
1146
1147    protected void addFileVersion(
1148            User user, DLFileEntry fileEntry, String version,
1149            String description, int status)
1150        throws SystemException {
1151
1152        long fileVersionId = counterLocalService.increment();
1153
1154        DLFileVersion fileVersion = dlFileVersionPersistence.create(
1155            fileVersionId);
1156
1157        long versionUserId = fileEntry.getVersionUserId();
1158
1159        if (versionUserId <= 0) {
1160            versionUserId = fileEntry.getUserId();
1161        }
1162
1163        String versionUserName = GetterUtil.getString(
1164            fileEntry.getVersionUserName(), fileEntry.getUserName());
1165
1166        fileVersion.setGroupId(fileEntry.getGroupId());
1167        fileVersion.setCompanyId(fileEntry.getCompanyId());
1168        fileVersion.setUserId(versionUserId);
1169        fileVersion.setUserName(versionUserName);
1170        fileVersion.setCreateDate(fileEntry.getModifiedDate());
1171        fileVersion.setFolderId(fileEntry.getFolderId());
1172        fileVersion.setName(fileEntry.getName());
1173        fileVersion.setDescription(description);
1174        fileVersion.setVersion(version);
1175        fileVersion.setSize(fileEntry.getSize());
1176        fileVersion.setStatus(status);
1177        fileVersion.setStatusByUserId(user.getUserId());
1178        fileVersion.setStatusByUserName(user.getFullName());
1179        fileVersion.setStatusDate(fileEntry.getModifiedDate());
1180
1181        dlFileVersionPersistence.update(fileVersion, false);
1182    }
1183
1184    protected long getFolderId(long companyId, long folderId)
1185        throws SystemException {
1186
1187        if (folderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
1188
1189            // Ensure folder exists and belongs to the proper company
1190
1191            DLFolder folder = dlFolderPersistence.fetchByPrimaryKey(folderId);
1192
1193            if ((folder == null) || (companyId != folder.getCompanyId())) {
1194                folderId = DLFolderConstants.DEFAULT_PARENT_FOLDER_ID;
1195            }
1196        }
1197
1198        return folderId;
1199    }
1200
1201    protected String getNextVersion(
1202        DLFileEntry fileEntry, boolean majorVersion) {
1203
1204        String version = fileEntry.getVersion();
1205
1206        if (DLUtil.compareVersions(
1207                fileEntry.getVersion(), fileEntry.getPendingVersion()) < 0) {
1208
1209            version = fileEntry.getPendingVersion();
1210        }
1211
1212        int[] splitVersion = StringUtil.split(version, StringPool.PERIOD, 0);
1213
1214        if (majorVersion) {
1215            splitVersion[0]++;
1216            splitVersion[1] = 0;
1217        }
1218        else {
1219            splitVersion[1]++;
1220        }
1221
1222        return splitVersion[0] + StringPool.PERIOD + splitVersion[1];
1223    }
1224
1225    protected void validate(
1226            long groupId, long folderId, long newFolderId, String name,
1227            String title, String sourceFileName, InputStream is)
1228        throws PortalException, SystemException {
1229
1230        if (Validator.isNotNull(sourceFileName)) {
1231            dlLocalService.validate(title, sourceFileName, is);
1232        }
1233
1234        if (folderId != newFolderId) {
1235            folderId = newFolderId;
1236        }
1237
1238        validate(groupId, folderId, name, title);
1239    }
1240
1241    protected void validate(
1242            long groupId, long folderId, String title, InputStream is)
1243        throws PortalException, SystemException {
1244
1245        dlLocalService.validate(title, true, is);
1246
1247        validate(groupId, folderId, null, title);
1248    }
1249
1250    protected void validate(
1251            long groupId, long folderId, String name, String title)
1252        throws PortalException, SystemException {
1253
1254        try {
1255            dlFolderLocalService.getFolder(groupId, folderId, title);
1256
1257            throw new DuplicateFolderNameException();
1258        }
1259        catch (NoSuchFolderException nsfe) {
1260        }
1261
1262        try {
1263            DLFileEntry fileEntry =
1264                dlFileEntryPersistence.findByG_F_T(groupId, folderId, title);
1265
1266            if (!fileEntry.getName().equals(name)) {
1267                throw new DuplicateFileException(title);
1268            }
1269        }
1270        catch (NoSuchFileEntryException nsfee) {
1271        }
1272    }
1273
1274    private static Log _log = LogFactoryUtil.getLog(
1275        DLFileEntryLocalServiceImpl.class);
1276
1277}