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