001
014
015 package com.liferay.portal.verify;
016
017 import com.liferay.counter.service.CounterLocalServiceUtil;
018 import com.liferay.portal.kernel.dao.orm.ActionableDynamicQuery;
019 import com.liferay.portal.kernel.dao.orm.Criterion;
020 import com.liferay.portal.kernel.dao.orm.DynamicQuery;
021 import com.liferay.portal.kernel.dao.orm.DynamicQueryFactoryUtil;
022 import com.liferay.portal.kernel.dao.orm.Projection;
023 import com.liferay.portal.kernel.dao.orm.ProjectionFactoryUtil;
024 import com.liferay.portal.kernel.dao.orm.Property;
025 import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
026 import com.liferay.portal.kernel.dao.orm.RestrictionsFactoryUtil;
027 import com.liferay.portal.kernel.exception.PortalException;
028 import com.liferay.portal.kernel.exception.SystemException;
029 import com.liferay.portal.kernel.log.Log;
030 import com.liferay.portal.kernel.log.LogFactoryUtil;
031 import com.liferay.portal.kernel.repository.model.FileEntry;
032 import com.liferay.portal.kernel.repository.model.FileVersion;
033 import com.liferay.portal.kernel.repository.model.Folder;
034 import com.liferay.portal.kernel.util.ContentTypes;
035 import com.liferay.portal.kernel.util.ListUtil;
036 import com.liferay.portal.kernel.util.LocaleUtil;
037 import com.liferay.portal.kernel.util.MimeTypesUtil;
038 import com.liferay.portal.kernel.util.StreamUtil;
039 import com.liferay.portal.kernel.util.StringPool;
040 import com.liferay.portal.kernel.util.StringUtil;
041 import com.liferay.portal.kernel.workflow.WorkflowConstants;
042 import com.liferay.portal.repository.liferayrepository.model.LiferayFileEntry;
043 import com.liferay.portal.repository.liferayrepository.model.LiferayFileVersion;
044 import com.liferay.portal.repository.liferayrepository.model.LiferayFolder;
045 import com.liferay.portal.util.PortalInstances;
046 import com.liferay.portal.util.PortalUtil;
047 import com.liferay.portlet.asset.model.AssetEntry;
048 import com.liferay.portlet.documentlibrary.DuplicateFileException;
049 import com.liferay.portlet.documentlibrary.DuplicateFolderNameException;
050 import com.liferay.portlet.documentlibrary.model.DLFileEntry;
051 import com.liferay.portlet.documentlibrary.model.DLFileEntryType;
052 import com.liferay.portlet.documentlibrary.model.DLFileEntryTypeConstants;
053 import com.liferay.portlet.documentlibrary.model.DLFileVersion;
054 import com.liferay.portlet.documentlibrary.model.DLFolder;
055 import com.liferay.portlet.documentlibrary.service.DLAppHelperLocalServiceUtil;
056 import com.liferay.portlet.documentlibrary.service.DLFileEntryLocalServiceUtil;
057 import com.liferay.portlet.documentlibrary.service.DLFileEntryTypeLocalServiceUtil;
058 import com.liferay.portlet.documentlibrary.service.DLFileVersionLocalServiceUtil;
059 import com.liferay.portlet.documentlibrary.service.DLFolderLocalServiceUtil;
060 import com.liferay.portlet.documentlibrary.service.persistence.DLFileEntryActionableDynamicQuery;
061 import com.liferay.portlet.documentlibrary.service.persistence.DLFileVersionActionableDynamicQuery;
062 import com.liferay.portlet.documentlibrary.service.persistence.DLFolderActionableDynamicQuery;
063 import com.liferay.portlet.documentlibrary.store.DLStoreUtil;
064 import com.liferay.portlet.documentlibrary.util.DLUtil;
065 import com.liferay.portlet.documentlibrary.util.comparator.FileVersionVersionComparator;
066 import com.liferay.portlet.documentlibrary.webdav.DLWebDAVStorageImpl;
067 import com.liferay.portlet.trash.model.TrashEntry;
068 import com.liferay.portlet.trash.service.TrashEntryLocalServiceUtil;
069
070 import java.io.InputStream;
071
072 import java.util.Collections;
073 import java.util.Date;
074 import java.util.List;
075
076
081 public class VerifyDocumentLibrary extends VerifyProcess {
082
083 protected void addDLFileVersion(DLFileEntry dlFileEntry)
084 throws SystemException {
085
086 long fileVersionId = CounterLocalServiceUtil.increment();
087
088 DLFileVersion dlFileVersion =
089 DLFileVersionLocalServiceUtil.createDLFileVersion(fileVersionId);
090
091 dlFileVersion.setGroupId(dlFileEntry.getGroupId());
092 dlFileVersion.setCompanyId(dlFileEntry.getCompanyId());
093
094 long userId = dlFileEntry.getUserId();
095
096 dlFileVersion.setUserId(userId);
097
098 String userName = dlFileEntry.getUserName();
099
100 dlFileVersion.setUserName(userName);
101
102 dlFileVersion.setCreateDate(dlFileEntry.getModifiedDate());
103 dlFileVersion.setModifiedDate(dlFileEntry.getModifiedDate());
104 dlFileVersion.setRepositoryId(dlFileEntry.getRepositoryId());
105 dlFileVersion.setFolderId(dlFileEntry.getFolderId());
106 dlFileVersion.setFileEntryId(dlFileEntry.getFileEntryId());
107 dlFileVersion.setExtension(dlFileEntry.getExtension());
108 dlFileVersion.setMimeType(dlFileEntry.getMimeType());
109 dlFileVersion.setTitle(dlFileEntry.getTitle());
110 dlFileVersion.setDescription(dlFileEntry.getDescription());
111 dlFileVersion.setExtraSettings(dlFileEntry.getExtraSettings());
112 dlFileVersion.setFileEntryTypeId(dlFileEntry.getFileEntryTypeId());
113 dlFileVersion.setVersion(dlFileEntry.getVersion());
114 dlFileVersion.setSize(dlFileEntry.getSize());
115 dlFileVersion.setStatus(WorkflowConstants.STATUS_APPROVED);
116 dlFileVersion.setStatusByUserId(userId);
117 dlFileVersion.setStatusByUserName(userName);
118 dlFileVersion.setStatusDate(new Date());
119
120 DLFileVersionLocalServiceUtil.updateDLFileVersion(dlFileVersion);
121 }
122
123 protected void checkDLFileEntryType() throws Exception {
124 DLFileEntryType dlFileEntryType =
125 DLFileEntryTypeLocalServiceUtil.fetchDLFileEntryType(
126 DLFileEntryTypeConstants.FILE_ENTRY_TYPE_ID_BASIC_DOCUMENT);
127
128 if (dlFileEntryType != null) {
129 return;
130 }
131
132 Date now = new Date();
133
134 dlFileEntryType = DLFileEntryTypeLocalServiceUtil.createDLFileEntryType(
135 DLFileEntryTypeConstants.FILE_ENTRY_TYPE_ID_BASIC_DOCUMENT);
136
137 dlFileEntryType.setCreateDate(now);
138 dlFileEntryType.setModifiedDate(now);
139 dlFileEntryType.setFileEntryTypeKey(
140 StringUtil.toUpperCase(
141 DLFileEntryTypeConstants.NAME_BASIC_DOCUMENT));
142 dlFileEntryType.setName(
143 DLFileEntryTypeConstants.NAME_BASIC_DOCUMENT,
144 LocaleUtil.getDefault());
145
146 DLFileEntryTypeLocalServiceUtil.updateDLFileEntryType(dlFileEntryType);
147 }
148
149 protected void checkDuplicateTitles() throws Exception {
150 ActionableDynamicQuery actionableDynamicQuery =
151 new DLFileEntryActionableDynamicQuery() {
152
153 @Override
154 public void performAction(Object object) {
155 DLFileEntry dlFileEntry = (DLFileEntry)object;
156
157 if (dlFileEntry.isInTrash()) {
158 return;
159 }
160
161 try {
162 DLFileEntryLocalServiceUtil.validateFile(
163 dlFileEntry.getGroupId(), dlFileEntry.getFolderId(),
164 dlFileEntry.getFileEntryId(),
165 dlFileEntry.getTitle(), dlFileEntry.getExtension());
166 }
167 catch (Exception e1) {
168 if (!(e1 instanceof DuplicateFileException) &&
169 !(e1 instanceof DuplicateFolderNameException)) {
170
171 return;
172 }
173
174 try {
175 renameDuplicateTitle(dlFileEntry);
176 }
177 catch (Exception e2) {
178 if (_log.isWarnEnabled()) {
179 _log.warn(
180 "Unable to rename duplicate title for " +
181 "file entry " +
182 dlFileEntry.getFileEntryId() +
183 ": " + e2.getMessage(),
184 e2);
185 }
186 }
187 }
188 }
189
190 };
191
192 actionableDynamicQuery.performActions();
193 }
194
195 protected void checkFileEntryMimeTypes(final String originalMimeType)
196 throws Exception {
197
198 ActionableDynamicQuery actionableDynamicQuery =
199 new DLFileEntryActionableDynamicQuery() {
200
201 @Override
202 public void addCriteria(DynamicQuery dynamicQuery) {
203 Property property = PropertyFactoryUtil.forName("mimeType");
204
205 dynamicQuery.add(property.eq(originalMimeType));
206 }
207
208 @Override
209 protected void performAction(Object object)
210 throws PortalException, SystemException {
211
212 DLFileEntry dlFileEntry = (DLFileEntry)object;
213
214 InputStream inputStream = null;
215
216 try {
217 inputStream = DLFileEntryLocalServiceUtil.getFileAsStream(
218 dlFileEntry.getFileEntryId(), dlFileEntry.getVersion(),
219 false);
220 }
221 catch (Exception e) {
222 if (_log.isWarnEnabled()) {
223 _log.warn(
224 "Unable to find file entry " +
225 dlFileEntry.getName(),
226 e);
227 }
228
229 return;
230 }
231
232 String title = DLUtil.getTitleWithExtension(
233 dlFileEntry.getTitle(), dlFileEntry.getExtension());
234
235 String mimeType = getMimeType(inputStream, title);
236
237 if (mimeType.equals(originalMimeType)) {
238 return;
239 }
240
241 dlFileEntry.setMimeType(mimeType);
242
243 DLFileEntryLocalServiceUtil.updateDLFileEntry(dlFileEntry);
244
245 DLFileVersion dlFileVersion = dlFileEntry.getFileVersion();
246
247 dlFileVersion.setMimeType(mimeType);
248
249 DLFileVersionLocalServiceUtil.updateDLFileVersion(
250 dlFileVersion);
251 }
252
253 };
254
255 actionableDynamicQuery.performActions();
256 }
257
258 protected void checkFileVersionMimeTypes(final String originalMimeType)
259 throws Exception {
260
261 ActionableDynamicQuery actionableDynamicQuery =
262 new DLFileVersionActionableDynamicQuery() {
263
264 @Override
265 public void addCriteria(DynamicQuery dynamicQuery) {
266 Property property = PropertyFactoryUtil.forName("mimeType");
267
268 dynamicQuery.add(property.eq(originalMimeType));
269 }
270
271 @Override
272 protected void performAction(Object object) throws SystemException {
273 DLFileVersion dlFileVersion = (DLFileVersion)object;
274
275 InputStream inputStream = null;
276
277 try {
278 inputStream = DLFileEntryLocalServiceUtil.getFileAsStream(
279 dlFileVersion.getFileEntryId(),
280 dlFileVersion.getVersion(), false);
281 }
282 catch (Exception e) {
283 if (_log.isWarnEnabled()) {
284 DLFileEntry dlFileEntry =
285 DLFileEntryLocalServiceUtil.fetchDLFileEntry(
286 dlFileVersion.getFileEntryId());
287
288 if (dlFileEntry == null) {
289 _log.warn(
290 "Unable to find file entry associated with " +
291 "file version " +
292 dlFileVersion.getFileVersionId(),
293 e);
294 }
295 else {
296 _log.warn(
297 "Unable to find file version " +
298 dlFileVersion.getVersion() + " for file " +
299 "entry " + dlFileEntry.getName(),
300 e);
301 }
302 }
303
304 return;
305 }
306
307 String title = DLUtil.getTitleWithExtension(
308 dlFileVersion.getTitle(), dlFileVersion.getExtension());
309
310 String mimeType = getMimeType(inputStream, title);
311
312 if (mimeType.equals(originalMimeType)) {
313 return;
314 }
315
316 dlFileVersion.setMimeType(mimeType);
317
318 DLFileVersionLocalServiceUtil.updateDLFileVersion(
319 dlFileVersion);
320 }
321
322 };
323
324 actionableDynamicQuery.performActions();
325 }
326
327 protected void checkMimeTypes() throws Exception {
328 String[] mimeTypes = {
329 ContentTypes.APPLICATION_OCTET_STREAM,
330 DLWebDAVStorageImpl.MS_OFFICE_2010_TEXT_XML_UTF8
331 };
332
333 for (String mimeType : mimeTypes) {
334 checkFileEntryMimeTypes(mimeType);
335 checkFileVersionMimeTypes(mimeType);
336 }
337
338 if (_log.isDebugEnabled()) {
339 _log.debug("Fixed file entries with invalid mime types");
340 }
341 }
342
343 protected void checkMisversionedDLFileEntries() throws Exception {
344 List<DLFileEntry> dlFileEntries =
345 DLFileEntryLocalServiceUtil.getMisversionedFileEntries();
346
347 if (_log.isDebugEnabled()) {
348 _log.debug(
349 "Processing " + dlFileEntries.size() +
350 " misversioned file entries");
351 }
352
353 for (DLFileEntry dlFileEntry : dlFileEntries) {
354 copyDLFileEntry(dlFileEntry);
355
356 addDLFileVersion(dlFileEntry);
357 }
358
359 if (_log.isDebugEnabled()) {
360 _log.debug("Fixed misversioned file entries");
361 }
362 }
363
364 protected void checkTitles() throws Exception {
365 DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
366 DLFileEntry.class);
367
368 Criterion criterion1 = RestrictionsFactoryUtil.like("title", "%/%");
369 Criterion criterion2 = RestrictionsFactoryUtil.like("title", "%\\\\%");
370
371 dynamicQuery.add(RestrictionsFactoryUtil.or(criterion1, criterion2));
372
373 List<DLFileEntry> dlFileEntries =
374 DLFileEntryLocalServiceUtil.dynamicQuery(dynamicQuery);
375
376 for (DLFileEntry dlFileEntry : dlFileEntries) {
377 TrashEntry trashEntry = TrashEntryLocalServiceUtil.fetchEntry(
378 dlFileEntry.getModelClassName(), dlFileEntry.getFileEntryId());
379
380 if (trashEntry != null) {
381 continue;
382 }
383
384 String title = dlFileEntry.getTitle();
385
386 String newTitle = title.replace(StringPool.SLASH, StringPool.BLANK);
387
388 newTitle = newTitle.replace(
389 StringPool.BACK_SLASH, StringPool.UNDERLINE);
390
391 renameTitle(dlFileEntry, newTitle);
392 }
393
394 checkDuplicateTitles();
395 }
396
397 protected void copyDLFileEntry(DLFileEntry dlFileEntry)
398 throws PortalException, SystemException {
399
400 long companyId = dlFileEntry.getCompanyId();
401 long dataRepositoryId = dlFileEntry.getDataRepositoryId();
402 String name = dlFileEntry.getName();
403 String version = dlFileEntry.getVersion();
404
405 if (DLStoreUtil.hasFile(companyId, dataRepositoryId, name, version)) {
406 return;
407 }
408
409 FileVersionVersionComparator comparator =
410 new FileVersionVersionComparator();
411
412 List<DLFileVersion> dlFileVersions = dlFileEntry.getFileVersions(
413 WorkflowConstants.STATUS_APPROVED);
414
415 if (dlFileVersions.isEmpty()) {
416 dlFileVersions = dlFileEntry.getFileVersions(
417 WorkflowConstants.STATUS_ANY);
418 }
419
420 if (dlFileVersions.isEmpty()) {
421 DLStoreUtil.addFile(companyId, dataRepositoryId, name, new byte[0]);
422
423 return;
424 }
425
426 dlFileVersions = ListUtil.copy(dlFileVersions);
427
428 Collections.sort(dlFileVersions, comparator);
429
430 DLFileVersion dlFileVersion = dlFileVersions.get(0);
431
432 DLStoreUtil.copyFileVersion(
433 companyId, dataRepositoryId, name, dlFileVersion.getVersion(),
434 version);
435 }
436
437 @Override
438 protected void doVerify() throws Exception {
439 checkMisversionedDLFileEntries();
440
441 checkDLFileEntryType();
442 checkMimeTypes();
443 checkTitles();
444 removeOrphanedDLFileEntries();
445 updateClassNameId();
446 updateFileEntryAssets();
447 updateFolderAssets();
448 verifyTree();
449 }
450
451 protected String getMimeType(InputStream inputStream, String title) {
452 String mimeType = null;
453
454 try {
455 mimeType = MimeTypesUtil.getContentType(inputStream, title);
456 }
457 finally {
458 StreamUtil.cleanUp(inputStream);
459 }
460
461 return mimeType;
462 }
463
464 protected void updateClassNameId() {
465 try {
466 runSQL(
467 "update DLFileEntry set classNameId = 0 where classNameId is " +
468 "null");
469 }
470 catch (Exception e) {
471 if (_log.isWarnEnabled()) {
472 _log.warn(
473 "Unable to fix file entries where class name ID is null",
474 e);
475 }
476 }
477 }
478
479 protected void removeOrphanedDLFileEntries() throws Exception {
480 List<DLFileEntry> dlFileEntries =
481 DLFileEntryLocalServiceUtil.getOrphanedFileEntries();
482
483 if (_log.isDebugEnabled()) {
484 _log.debug(
485 "Processing " + dlFileEntries.size() +
486 " file entries with no group");
487 }
488
489 for (DLFileEntry dlFileEntry : dlFileEntries) {
490 try {
491 DLFileEntryLocalServiceUtil.deleteFileEntry(
492 dlFileEntry.getFileEntryId());
493 }
494 catch (Exception e) {
495 if (_log.isWarnEnabled()) {
496 _log.warn(
497 "Unable to remove file entry " +
498 dlFileEntry.getFileEntryId() + ": " +
499 e.getMessage());
500 }
501 }
502 }
503
504 if (_log.isDebugEnabled()) {
505 _log.debug("Removed orphaned file entries");
506 }
507 }
508
509 protected void renameDuplicateTitle(DLFileEntry dlFileEntry)
510 throws PortalException, SystemException {
511
512 String uniqueTitle = DLFileEntryLocalServiceUtil.getUniqueTitle(
513 dlFileEntry.getGroupId(), dlFileEntry.getFolderId(),
514 dlFileEntry.getFileEntryId(), dlFileEntry.getTitle(),
515 dlFileEntry.getExtension());
516
517 renameTitle(dlFileEntry, uniqueTitle);
518 }
519
520 protected void renameTitle(DLFileEntry dlFileEntry, String newTitle)
521 throws PortalException, SystemException {
522
523 String title = dlFileEntry.getTitle();
524
525 dlFileEntry.setTitle(newTitle);
526
527 DLFileEntryLocalServiceUtil.updateDLFileEntry(dlFileEntry);
528
529 DLFileVersion dlFileVersion = dlFileEntry.getFileVersion();
530
531 dlFileVersion.setTitle(newTitle);
532
533 DLFileVersionLocalServiceUtil.updateDLFileVersion(dlFileVersion);
534
535 if (_log.isDebugEnabled()) {
536 _log.debug(
537 "Invalid title " + title + " renamed to " + newTitle +
538 " for file entry " + dlFileEntry.getFileEntryId());
539 }
540 }
541
542 protected void updateFileEntryAssets() throws Exception {
543 ActionableDynamicQuery actionableDynamicQuery =
544 new DLFileEntryActionableDynamicQuery() {
545
546 @Override
547 public void addCriteria(DynamicQuery dynamicQuery) {
548 Property fileEntryIdProperty = PropertyFactoryUtil.forName(
549 "fileEntryId");
550
551 DynamicQuery assetEntryDynamicQuery =
552 DynamicQueryFactoryUtil.forClass(AssetEntry.class);
553
554 Property classNameIdProperty = PropertyFactoryUtil.forName(
555 "classNameId");
556
557 long classNameId = PortalUtil.getClassNameId(
558 DLFileEntry.class);
559
560 assetEntryDynamicQuery.add(
561 classNameIdProperty.eq(classNameId));
562
563 Projection projection = ProjectionFactoryUtil.property(
564 "classPK");
565
566 assetEntryDynamicQuery.setProjection(projection);
567
568 dynamicQuery.add(
569 fileEntryIdProperty.notIn(assetEntryDynamicQuery));
570 }
571
572 @Override
573 protected void performAction(Object object)
574 throws PortalException, SystemException {
575
576 DLFileEntry dlFileEntry = (DLFileEntry)object;
577
578 FileEntry fileEntry = new LiferayFileEntry(dlFileEntry);
579 FileVersion fileVersion = new LiferayFileVersion(
580 dlFileEntry.getFileVersion());
581
582 try {
583 DLAppHelperLocalServiceUtil.updateAsset(
584 dlFileEntry.getUserId(), fileEntry, fileVersion,
585 null, null, null);
586 }
587 catch (Exception e) {
588 if (_log.isWarnEnabled()) {
589 _log.warn(
590 "Unable to update asset for file entry " +
591 dlFileEntry.getFileEntryId() + ": " +
592 e.getMessage());
593 }
594 }
595 }
596 };
597
598 if (_log.isDebugEnabled()) {
599 long count = actionableDynamicQuery.performCount();
600
601 _log.debug("Processing " + count + " file entries with no asset");
602 }
603
604 actionableDynamicQuery.performActions();
605
606 if (_log.isDebugEnabled()) {
607 _log.debug("Assets verified for file entries");
608 }
609 }
610
611 protected void updateFolderAssets() throws Exception {
612 ActionableDynamicQuery actionableDynamicQuery =
613 new DLFolderActionableDynamicQuery() {
614
615 @Override
616 public void addCriteria(DynamicQuery dynamicQuery) {
617 Property folderIdProperty = PropertyFactoryUtil.forName(
618 "folderId");
619
620 DynamicQuery assetEntryDynamicQuery =
621 DynamicQueryFactoryUtil.forClass(AssetEntry.class);
622
623 Property classNameIdProperty = PropertyFactoryUtil.forName(
624 "classNameId");
625
626 long classNameId = PortalUtil.getClassNameId(
627 DLFolder.class);
628
629 assetEntryDynamicQuery.add(
630 classNameIdProperty.eq(classNameId));
631
632 Projection projection = ProjectionFactoryUtil.property(
633 "classPK");
634
635 assetEntryDynamicQuery.setProjection(projection);
636
637 dynamicQuery.add(
638 folderIdProperty.notIn(assetEntryDynamicQuery));
639 }
640
641 @Override
642 protected void performAction(Object object)
643 throws PortalException, SystemException {
644
645 DLFolder dlFolder = (DLFolder)object;
646
647 Folder folder = new LiferayFolder(dlFolder);
648
649 try {
650 DLAppHelperLocalServiceUtil.updateAsset(
651 dlFolder.getUserId(), folder, null, null, null);
652 }
653 catch (Exception e) {
654 if (_log.isWarnEnabled()) {
655 _log.warn(
656 "Unable to update asset for folder " +
657 dlFolder.getFolderId() + ": " +
658 e.getMessage());
659 }
660 }
661 }
662 };
663
664 if (_log.isDebugEnabled()) {
665 long count = actionableDynamicQuery.performCount();
666
667 _log.debug("Processing " + count + " folders with no asset");
668 }
669
670 actionableDynamicQuery.performActions();
671
672 if (_log.isDebugEnabled()) {
673 _log.debug("Assets verified for folders");
674 }
675 }
676
677 protected void verifyTree() throws Exception {
678 long[] companyIds = PortalInstances.getCompanyIdsBySQL();
679
680 for (long companyId : companyIds) {
681 DLFolderLocalServiceUtil.rebuildTree(companyId);
682 }
683 }
684
685 private static Log _log = LogFactoryUtil.getLog(
686 VerifyDocumentLibrary.class);
687
688 }