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.Property;
023 import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
024 import com.liferay.portal.kernel.dao.orm.RestrictionsFactoryUtil;
025 import com.liferay.portal.kernel.exception.PortalException;
026 import com.liferay.portal.kernel.exception.SystemException;
027 import com.liferay.portal.kernel.log.Log;
028 import com.liferay.portal.kernel.log.LogFactoryUtil;
029 import com.liferay.portal.kernel.repository.model.FileEntry;
030 import com.liferay.portal.kernel.repository.model.FileVersion;
031 import com.liferay.portal.kernel.repository.model.Folder;
032 import com.liferay.portal.kernel.util.ContentTypes;
033 import com.liferay.portal.kernel.util.ListUtil;
034 import com.liferay.portal.kernel.util.LocaleUtil;
035 import com.liferay.portal.kernel.util.MimeTypesUtil;
036 import com.liferay.portal.kernel.util.StreamUtil;
037 import com.liferay.portal.kernel.util.StringPool;
038 import com.liferay.portal.kernel.util.StringUtil;
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 public void addCriteria(DynamicQuery dynamicQuery) {
198 Property property = PropertyFactoryUtil.forName("mimeType");
199
200 dynamicQuery.add(property.eq(originalMimeType));
201 }
202
203 @Override
204 protected void performAction(Object object)
205 throws PortalException, SystemException {
206
207 DLFileEntry dlFileEntry = (DLFileEntry)object;
208
209 InputStream inputStream = null;
210
211 try {
212 inputStream = DLFileEntryLocalServiceUtil.getFileAsStream(
213 dlFileEntry.getFileEntryId(), dlFileEntry.getVersion(),
214 false);
215 }
216 catch (Exception e) {
217 if (_log.isWarnEnabled()) {
218 _log.warn(
219 "Unable to find file entry " +
220 dlFileEntry.getName(),
221 e);
222 }
223
224 return;
225 }
226
227 String title = DLUtil.getTitleWithExtension(
228 dlFileEntry.getTitle(), dlFileEntry.getExtension());
229
230 String mimeType = getMimeType(inputStream, title);
231
232 if (mimeType.equals(originalMimeType)) {
233 return;
234 }
235
236 dlFileEntry.setMimeType(mimeType);
237
238 DLFileEntryLocalServiceUtil.updateDLFileEntry(dlFileEntry);
239
240 DLFileVersion dlFileVersion = dlFileEntry.getFileVersion();
241
242 dlFileVersion.setMimeType(mimeType);
243
244 DLFileVersionLocalServiceUtil.updateDLFileVersion(
245 dlFileVersion);
246 }
247
248 };
249
250 actionableDynamicQuery.performActions();
251 }
252
253 protected void checkFileVersionMimeTypes(final String originalMimeType)
254 throws Exception {
255
256 ActionableDynamicQuery actionableDynamicQuery =
257 new DLFileVersionActionableDynamicQuery() {
258
259 @Override
260 public void addCriteria(DynamicQuery dynamicQuery) {
261 Property property = PropertyFactoryUtil.forName("mimeType");
262
263 dynamicQuery.add(property.eq(originalMimeType));
264 }
265
266 @Override
267 protected void performAction(Object object) throws SystemException {
268 DLFileVersion dlFileVersion = (DLFileVersion)object;
269
270 InputStream inputStream = null;
271
272 try {
273 inputStream = DLFileEntryLocalServiceUtil.getFileAsStream(
274 dlFileVersion.getFileEntryId(),
275 dlFileVersion.getVersion(), false);
276 }
277 catch (Exception e) {
278 if (_log.isWarnEnabled()) {
279 DLFileEntry dlFileEntry =
280 DLFileEntryLocalServiceUtil.fetchDLFileEntry(
281 dlFileVersion.getFileEntryId());
282
283 if (dlFileEntry == null) {
284 _log.warn(
285 "Unable to find file entry associated with " +
286 "file version " +
287 dlFileVersion.getFileVersionId(),
288 e);
289 }
290 else {
291 _log.warn(
292 "Unable to find file version " +
293 dlFileVersion.getVersion() + " for file " +
294 "entry " + dlFileEntry.getName(),
295 e);
296 }
297 }
298
299 return;
300 }
301
302 String title = DLUtil.getTitleWithExtension(
303 dlFileVersion.getTitle(), dlFileVersion.getExtension());
304
305 String mimeType = getMimeType(inputStream, title);
306
307 if (mimeType.equals(originalMimeType)) {
308 return;
309 }
310
311 dlFileVersion.setMimeType(mimeType);
312
313 DLFileVersionLocalServiceUtil.updateDLFileVersion(
314 dlFileVersion);
315 }
316
317 };
318
319 actionableDynamicQuery.performActions();
320 }
321
322 protected void checkMimeTypes() throws Exception {
323 String[] mimeTypes = {
324 ContentTypes.APPLICATION_OCTET_STREAM,
325 DLWebDAVStorageImpl.MS_OFFICE_2010_TEXT_XML_UTF8
326 };
327
328 for (String mimeType : mimeTypes) {
329 checkFileEntryMimeTypes(mimeType);
330 checkFileVersionMimeTypes(mimeType);
331 }
332
333 if (_log.isDebugEnabled()) {
334 _log.debug("Fixed file entries with invalid mime types");
335 }
336 }
337
338 protected void checkMisversionedDLFileEntries() throws Exception {
339 List<DLFileEntry> dlFileEntries =
340 DLFileEntryLocalServiceUtil.getMisversionedFileEntries();
341
342 if (_log.isDebugEnabled()) {
343 _log.debug(
344 "Processing " + dlFileEntries.size() +
345 " misversioned file entries");
346 }
347
348 for (DLFileEntry dlFileEntry : dlFileEntries) {
349 copyDLFileEntry(dlFileEntry);
350
351 addDLFileVersion(dlFileEntry);
352 }
353
354 if (_log.isDebugEnabled()) {
355 _log.debug("Fixed misversioned file entries");
356 }
357 }
358
359 protected void checkTitles() throws Exception {
360 DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
361 DLFileEntry.class);
362
363 Criterion criterion1 = RestrictionsFactoryUtil.like("title", "%/%");
364 Criterion criterion2 = RestrictionsFactoryUtil.like("title", "%\\\\%");
365
366 dynamicQuery.add(RestrictionsFactoryUtil.or(criterion1, criterion2));
367
368 List<DLFileEntry> dlFileEntries =
369 DLFileEntryLocalServiceUtil.dynamicQuery(dynamicQuery);
370
371 for (DLFileEntry dlFileEntry : dlFileEntries) {
372 TrashEntry trashEntry = TrashEntryLocalServiceUtil.fetchEntry(
373 dlFileEntry.getModelClassName(), dlFileEntry.getFileEntryId());
374
375 if (trashEntry != null) {
376 continue;
377 }
378
379 String title = dlFileEntry.getTitle();
380
381 String newTitle = title.replace(StringPool.SLASH, StringPool.BLANK);
382
383 newTitle = newTitle.replace(
384 StringPool.BACK_SLASH, StringPool.UNDERLINE);
385
386 renameTitle(dlFileEntry, newTitle);
387 }
388
389 checkDuplicateTitles();
390 }
391
392 protected void copyDLFileEntry(DLFileEntry dlFileEntry)
393 throws PortalException, SystemException {
394
395 long companyId = dlFileEntry.getCompanyId();
396 long dataRepositoryId = dlFileEntry.getDataRepositoryId();
397 String name = dlFileEntry.getName();
398 String version = dlFileEntry.getVersion();
399
400 if (DLStoreUtil.hasFile(companyId, dataRepositoryId, name, version)) {
401 return;
402 }
403
404 FileVersionVersionComparator comparator =
405 new FileVersionVersionComparator();
406
407 List<DLFileVersion> dlFileVersions = dlFileEntry.getFileVersions(
408 WorkflowConstants.STATUS_APPROVED);
409
410 if (dlFileVersions.isEmpty()) {
411 dlFileVersions = dlFileEntry.getFileVersions(
412 WorkflowConstants.STATUS_ANY);
413 }
414
415 if (dlFileVersions.isEmpty()) {
416 DLStoreUtil.addFile(companyId, dataRepositoryId, name, new byte[0]);
417
418 return;
419 }
420
421 dlFileVersions = ListUtil.copy(dlFileVersions);
422
423 Collections.sort(dlFileVersions, comparator);
424
425 DLFileVersion dlFileVersion = dlFileVersions.get(0);
426
427 DLStoreUtil.copyFileVersion(
428 companyId, dataRepositoryId, name, dlFileVersion.getVersion(),
429 version);
430 }
431
432 @Override
433 protected void doVerify() throws Exception {
434 checkMisversionedDLFileEntries();
435
436 checkDLFileEntryType();
437 checkMimeTypes();
438 checkTitles();
439 removeOrphanedDLFileEntries();
440 updateClassNameId();
441 updateFileEntryAssets();
442 updateFolderAssets();
443 verifyTree();
444 }
445
446 protected String getMimeType(InputStream inputStream, String title) {
447 String mimeType = null;
448
449 try {
450 mimeType = MimeTypesUtil.getContentType(inputStream, title);
451 }
452 finally {
453 StreamUtil.cleanUp(inputStream);
454 }
455
456 return mimeType;
457 }
458
459 protected void updateClassNameId() {
460 try {
461 runSQL(
462 "update DLFileEntry set classNameId = 0 where classNameId is " +
463 "null");
464 }
465 catch (Exception e) {
466 if (_log.isWarnEnabled()) {
467 _log.warn(
468 "Unable to fix file entries where class name ID is null",
469 e);
470 }
471 }
472 }
473
474 protected void removeOrphanedDLFileEntries() throws Exception {
475 List<DLFileEntry> dlFileEntries =
476 DLFileEntryLocalServiceUtil.getOrphanedFileEntries();
477
478 if (_log.isDebugEnabled()) {
479 _log.debug(
480 "Processing " + dlFileEntries.size() +
481 " file entries with no group");
482 }
483
484 for (DLFileEntry dlFileEntry : dlFileEntries) {
485 try {
486 DLFileEntryLocalServiceUtil.deleteFileEntry(
487 dlFileEntry.getFileEntryId());
488 }
489 catch (Exception e) {
490 if (_log.isWarnEnabled()) {
491 _log.warn(
492 "Unable to remove file entry " +
493 dlFileEntry.getFileEntryId() + ": " +
494 e.getMessage());
495 }
496 }
497 }
498
499 if (_log.isDebugEnabled()) {
500 _log.debug("Removed orphaned file entries");
501 }
502 }
503
504 protected void renameDuplicateTitle(DLFileEntry dlFileEntry)
505 throws PortalException, SystemException {
506
507 String uniqueTitle = DLFileEntryLocalServiceUtil.getUniqueTitle(
508 dlFileEntry.getGroupId(), dlFileEntry.getFolderId(),
509 dlFileEntry.getFileEntryId(), dlFileEntry.getTitle(),
510 dlFileEntry.getExtension());
511
512 renameTitle(dlFileEntry, uniqueTitle);
513 }
514
515 protected void renameTitle(DLFileEntry dlFileEntry, String newTitle)
516 throws PortalException, SystemException {
517
518 String title = dlFileEntry.getTitle();
519
520 dlFileEntry.setTitle(newTitle);
521
522 DLFileEntryLocalServiceUtil.updateDLFileEntry(dlFileEntry);
523
524 DLFileVersion dlFileVersion = dlFileEntry.getFileVersion();
525
526 dlFileVersion.setTitle(newTitle);
527
528 DLFileVersionLocalServiceUtil.updateDLFileVersion(dlFileVersion);
529
530 if (_log.isDebugEnabled()) {
531 _log.debug(
532 "Invalid title " + title + " renamed to " + newTitle +
533 " for file entry " + dlFileEntry.getFileEntryId());
534 }
535 }
536
537 protected void updateFileEntryAssets() throws Exception {
538 List<DLFileEntry> dlFileEntries =
539 DLFileEntryLocalServiceUtil.getNoAssetFileEntries();
540
541 if (_log.isDebugEnabled()) {
542 _log.debug(
543 "Processing " + dlFileEntries.size() +
544 " file entries with no asset");
545 }
546
547 for (DLFileEntry dlFileEntry : dlFileEntries) {
548 FileEntry fileEntry = new LiferayFileEntry(dlFileEntry);
549 FileVersion fileVersion = new LiferayFileVersion(
550 dlFileEntry.getFileVersion());
551
552 try {
553 DLAppHelperLocalServiceUtil.updateAsset(
554 dlFileEntry.getUserId(), fileEntry, fileVersion, null, null,
555 null);
556 }
557 catch (Exception e) {
558 if (_log.isWarnEnabled()) {
559 _log.warn(
560 "Unable to update asset for file entry " +
561 dlFileEntry.getFileEntryId() + ": " +
562 e.getMessage());
563 }
564 }
565 }
566
567 if (_log.isDebugEnabled()) {
568 _log.debug("Assets verified for file entries");
569 }
570 }
571
572 protected void updateFolderAssets() throws Exception {
573 List<DLFolder> dlFolders = DLFolderLocalServiceUtil.getNoAssetFolders();
574
575 if (_log.isDebugEnabled()) {
576 _log.debug(
577 "Processing " + dlFolders.size() + " folders with no asset");
578 }
579
580 for (DLFolder dlFolder : dlFolders) {
581 Folder folder = new LiferayFolder(dlFolder);
582
583 try {
584 DLAppHelperLocalServiceUtil.updateAsset(
585 dlFolder.getUserId(), folder, null, null, null);
586 }
587 catch (Exception e) {
588 if (_log.isWarnEnabled()) {
589 _log.warn(
590 "Unable to update asset for folder " +
591 dlFolder.getFolderId() + ": " + e.getMessage());
592 }
593 }
594 }
595
596 if (_log.isDebugEnabled()) {
597 _log.debug("Assets verified for folders");
598 }
599 }
600
601 protected void verifyTree() throws Exception {
602 long[] companyIds = PortalInstances.getCompanyIdsBySQL();
603
604 for (long companyId : companyIds) {
605 DLFolderLocalServiceUtil.rebuildTree(companyId);
606 }
607 }
608
609 private static Log _log = LogFactoryUtil.getLog(
610 VerifyDocumentLibrary.class);
611
612 }