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