001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
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.ListUtil;
032    import com.liferay.portal.kernel.util.LocaleUtil;
033    import com.liferay.portal.kernel.util.MimeTypesUtil;
034    import com.liferay.portal.kernel.util.StringPool;
035    import com.liferay.portal.kernel.util.StringUtil;
036    import com.liferay.portal.kernel.workflow.WorkflowConstants;
037    import com.liferay.portal.repository.liferayrepository.model.LiferayFileEntry;
038    import com.liferay.portal.repository.liferayrepository.model.LiferayFileVersion;
039    import com.liferay.portal.repository.liferayrepository.model.LiferayFolder;
040    import com.liferay.portal.util.PortalInstances;
041    import com.liferay.portlet.documentlibrary.model.DLFileEntry;
042    import com.liferay.portlet.documentlibrary.model.DLFileEntryType;
043    import com.liferay.portlet.documentlibrary.model.DLFileEntryTypeConstants;
044    import com.liferay.portlet.documentlibrary.model.DLFileVersion;
045    import com.liferay.portlet.documentlibrary.model.DLFolder;
046    import com.liferay.portlet.documentlibrary.service.DLAppHelperLocalServiceUtil;
047    import com.liferay.portlet.documentlibrary.service.DLFileEntryLocalServiceUtil;
048    import com.liferay.portlet.documentlibrary.service.DLFileEntryTypeLocalServiceUtil;
049    import com.liferay.portlet.documentlibrary.service.DLFileShortcutLocalServiceUtil;
050    import com.liferay.portlet.documentlibrary.service.DLFileVersionLocalServiceUtil;
051    import com.liferay.portlet.documentlibrary.service.DLFolderLocalServiceUtil;
052    import com.liferay.portlet.documentlibrary.service.persistence.DLFileEntryActionableDynamicQuery;
053    import com.liferay.portlet.documentlibrary.service.persistence.DLFileVersionActionableDynamicQuery;
054    import com.liferay.portlet.documentlibrary.store.DLStoreUtil;
055    import com.liferay.portlet.documentlibrary.util.DLUtil;
056    import com.liferay.portlet.documentlibrary.util.comparator.FileVersionVersionComparator;
057    import com.liferay.portlet.documentlibrary.webdav.DLWebDAVStorageImpl;
058    import com.liferay.portlet.trash.model.TrashEntry;
059    import com.liferay.portlet.trash.service.TrashEntryLocalServiceUtil;
060    
061    import java.io.InputStream;
062    
063    import java.util.Collections;
064    import java.util.Date;
065    import java.util.List;
066    
067    /**
068     * @author Raymond Aug??
069     * @author Douglas Wong
070     * @author Alexander Chow
071     */
072    public class VerifyDocumentLibrary extends VerifyProcess {
073    
074            protected void addDLFileVersion(DLFileEntry dlFileEntry)
075                    throws SystemException {
076    
077                    long fileVersionId = CounterLocalServiceUtil.increment();
078    
079                    DLFileVersion dlFileVersion =
080                            DLFileVersionLocalServiceUtil.createDLFileVersion(fileVersionId);
081    
082                    dlFileVersion.setGroupId(dlFileEntry.getGroupId());
083                    dlFileVersion.setCompanyId(dlFileEntry.getCompanyId());
084    
085                    long userId = dlFileEntry.getUserId();
086    
087                    dlFileVersion.setUserId(userId);
088    
089                    String userName = dlFileEntry.getUserName();
090    
091                    dlFileVersion.setUserName(userName);
092    
093                    dlFileVersion.setCreateDate(dlFileEntry.getModifiedDate());
094                    dlFileVersion.setModifiedDate(dlFileEntry.getModifiedDate());
095                    dlFileVersion.setRepositoryId(dlFileEntry.getRepositoryId());
096                    dlFileVersion.setFolderId(dlFileEntry.getFolderId());
097                    dlFileVersion.setFileEntryId(dlFileEntry.getFileEntryId());
098                    dlFileVersion.setExtension(dlFileEntry.getExtension());
099                    dlFileVersion.setMimeType(dlFileEntry.getMimeType());
100                    dlFileVersion.setTitle(dlFileEntry.getTitle());
101                    dlFileVersion.setDescription(dlFileEntry.getDescription());
102                    dlFileVersion.setExtraSettings(dlFileEntry.getExtraSettings());
103                    dlFileVersion.setFileEntryTypeId(dlFileEntry.getFileEntryTypeId());
104                    dlFileVersion.setVersion(dlFileEntry.getVersion());
105                    dlFileVersion.setSize(dlFileEntry.getSize());
106                    dlFileVersion.setStatus(WorkflowConstants.STATUS_APPROVED);
107                    dlFileVersion.setStatusByUserId(userId);
108                    dlFileVersion.setStatusByUserName(userName);
109                    dlFileVersion.setStatusDate(new Date());
110    
111                    DLFileVersionLocalServiceUtil.updateDLFileVersion(dlFileVersion);
112            }
113    
114            protected void checkDLFileEntryType() throws Exception {
115                    DLFileEntryType dlFileEntryType =
116                            DLFileEntryTypeLocalServiceUtil.fetchDLFileEntryType(
117                                    DLFileEntryTypeConstants.FILE_ENTRY_TYPE_ID_BASIC_DOCUMENT);
118    
119                    if (dlFileEntryType != null) {
120                            return;
121                    }
122    
123                    Date now = new Date();
124    
125                    dlFileEntryType = DLFileEntryTypeLocalServiceUtil.createDLFileEntryType(
126                            DLFileEntryTypeConstants.FILE_ENTRY_TYPE_ID_BASIC_DOCUMENT);
127    
128                    dlFileEntryType.setCreateDate(now);
129                    dlFileEntryType.setModifiedDate(now);
130                    dlFileEntryType.setFileEntryTypeKey(
131                            StringUtil.toUpperCase(
132                                    DLFileEntryTypeConstants.NAME_BASIC_DOCUMENT));
133                    dlFileEntryType.setName(
134                            DLFileEntryTypeConstants.NAME_BASIC_DOCUMENT,
135                            LocaleUtil.getDefault());
136    
137                    DLFileEntryTypeLocalServiceUtil.updateDLFileEntryType(dlFileEntryType);
138            }
139    
140            protected void checkFileEntryMimeTypes(final String originalMimeType)
141                    throws Exception {
142    
143                    ActionableDynamicQuery actionableDynamicQuery =
144                            new DLFileEntryActionableDynamicQuery() {
145    
146                            @Override
147                            protected void performAction(Object object)
148                                    throws PortalException, SystemException {
149    
150                                    DLFileEntry dlFileEntry = (DLFileEntry)object;
151    
152                                    InputStream inputStream = null;
153    
154                                    try {
155                                            inputStream = DLFileEntryLocalServiceUtil.getFileAsStream(
156                                                    dlFileEntry.getUserId(), dlFileEntry.getFileEntryId(),
157                                                    dlFileEntry.getVersion(), false);
158                                    }
159                                    catch (Exception e) {
160                                            if (_log.isWarnEnabled()) {
161                                                    _log.warn(
162                                                            "Unable to find file entry " +
163                                                                    dlFileEntry.getName(),
164                                                            e);
165                                            }
166    
167                                            return;
168                                    }
169    
170                                    String title = DLUtil.getTitleWithExtension(
171                                            dlFileEntry.getTitle(), dlFileEntry.getExtension());
172    
173                                    String mimeType = MimeTypesUtil.getContentType(
174                                            inputStream, title);
175    
176                                    if (mimeType.equals(originalMimeType)) {
177                                            return;
178                                    }
179    
180                                    dlFileEntry.setMimeType(mimeType);
181    
182                                    DLFileEntryLocalServiceUtil.updateDLFileEntry(dlFileEntry);
183    
184                                    DLFileVersion dlFileVersion = dlFileEntry.getFileVersion();
185    
186                                    dlFileVersion.setMimeType(mimeType);
187    
188                                    DLFileVersionLocalServiceUtil.updateDLFileVersion(
189                                            dlFileVersion);
190                            }
191    
192                    };
193    
194                    actionableDynamicQuery.performActions();
195            }
196    
197            protected void checkFileVersionMimeTypes(final String originalMimeType)
198                    throws Exception {
199    
200                    ActionableDynamicQuery actionableDynamicQuery =
201                            new DLFileVersionActionableDynamicQuery() {
202    
203                            @Override
204                            protected void performAction(Object object)
205                                    throws PortalException, SystemException {
206    
207                                    DLFileVersion dlFileVersion = (DLFileVersion)object;
208    
209                                    InputStream inputStream = null;
210    
211                                    try {
212                                            inputStream = DLFileEntryLocalServiceUtil.getFileAsStream(
213                                                    dlFileVersion.getUserId(),
214                                                    dlFileVersion.getFileEntryId(),
215                                                    dlFileVersion.getVersion(), false);
216                                    }
217                                    catch (Exception e) {
218                                            DLFileEntry fileEntry = dlFileVersion.getFileEntry();
219    
220                                            if (_log.isWarnEnabled()) {
221                                                    _log.warn(
222                                                            "Unable to find file version " +
223                                                                    dlFileVersion.getVersion() + " for file " +
224                                                                            "entry " + fileEntry.getName(),
225                                                            e);
226                                            }
227    
228                                            return;
229                                    }
230    
231                                    String title = DLUtil.getTitleWithExtension(
232                                            dlFileVersion.getTitle(), dlFileVersion.getExtension());
233    
234                                    String mimeType = MimeTypesUtil.getContentType(
235                                            inputStream, title);
236    
237                                    if (mimeType.equals(originalMimeType)) {
238                                            return;
239                                    }
240    
241                                    dlFileVersion.setMimeType(mimeType);
242    
243                                    DLFileVersionLocalServiceUtil.updateDLFileVersion(
244                                            dlFileVersion);
245                            }
246    
247                    };
248    
249                    actionableDynamicQuery.performActions();
250            }
251    
252            protected void checkMimeTypes() throws Exception {
253                    String[] mimeTypes = {
254                            ContentTypes.APPLICATION_OCTET_STREAM,
255                            DLWebDAVStorageImpl.MS_OFFICE_2010_TEXT_XML_UTF8
256                    };
257    
258                    for (String mimeType : mimeTypes) {
259                            checkFileEntryMimeTypes(mimeType);
260                            checkFileVersionMimeTypes(mimeType);
261                    }
262    
263                    if (_log.isDebugEnabled()) {
264                            _log.debug("Fixed file entries with invalid mime types");
265                    }
266            }
267    
268            protected void checkMisversionedDLFileEntries() throws Exception {
269                    List<DLFileEntry> dlFileEntries =
270                            DLFileEntryLocalServiceUtil.getMisversionedFileEntries();
271    
272                    if (_log.isDebugEnabled()) {
273                            _log.debug(
274                                    "Processing " + dlFileEntries.size() +
275                                            " misversioned file entries");
276                    }
277    
278                    for (DLFileEntry dlFileEntry : dlFileEntries) {
279                            copyDLFileEntry(dlFileEntry);
280    
281                            addDLFileVersion(dlFileEntry);
282                    }
283    
284                    if (_log.isDebugEnabled()) {
285                            _log.debug("Fixed misversioned file entries");
286                    }
287            }
288    
289            protected void checkTitles() throws Exception {
290                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
291                            DLFileEntry.class);
292    
293                    Criterion criterion1 = RestrictionsFactoryUtil.like("title", "%/%");
294                    Criterion criterion2 = RestrictionsFactoryUtil.like("title", "%\\\\%");
295    
296                    dynamicQuery.add(RestrictionsFactoryUtil.or(criterion1, criterion2));
297    
298                    List<DLFileEntry> dlFileEntries =
299                            DLFileEntryLocalServiceUtil.dynamicQuery(dynamicQuery);
300    
301                    for (DLFileEntry dlFileEntry : dlFileEntries) {
302                            TrashEntry trashEntry = TrashEntryLocalServiceUtil.fetchEntry(
303                                    dlFileEntry.getModelClassName(), dlFileEntry.getFileEntryId());
304    
305                            if (trashEntry != null) {
306                                    continue;
307                            }
308    
309                            String title = dlFileEntry.getTitle();
310    
311                            String newTitle = title.replace(StringPool.SLASH, StringPool.BLANK);
312    
313                            newTitle = newTitle.replace(
314                                    StringPool.BACK_SLASH, StringPool.UNDERLINE);
315    
316                            dlFileEntry.setTitle(newTitle);
317    
318                            DLFileEntryLocalServiceUtil.updateDLFileEntry(dlFileEntry);
319    
320                            DLFileVersion dlFileVersion = dlFileEntry.getFileVersion();
321    
322                            dlFileVersion.setTitle(newTitle);
323    
324                            DLFileVersionLocalServiceUtil.updateDLFileVersion(dlFileVersion);
325    
326                            if (_log.isDebugEnabled()) {
327                                    _log.debug(
328                                            "Invalid document title " + title + "renamed to " +
329                                                    newTitle);
330                            }
331                    }
332            }
333    
334            protected void copyDLFileEntry(DLFileEntry dlFileEntry)
335                    throws PortalException, SystemException {
336    
337                    long companyId = dlFileEntry.getCompanyId();
338                    long dataRepositoryId = dlFileEntry.getDataRepositoryId();
339                    String name = dlFileEntry.getName();
340                    String version = dlFileEntry.getVersion();
341    
342                    if (DLStoreUtil.hasFile(companyId, dataRepositoryId, name, version)) {
343                            return;
344                    }
345    
346                    FileVersionVersionComparator comparator =
347                            new FileVersionVersionComparator();
348    
349                    List<DLFileVersion> dlFileVersions = dlFileEntry.getFileVersions(
350                            WorkflowConstants.STATUS_APPROVED);
351    
352                    if (dlFileVersions.isEmpty()) {
353                            dlFileVersions = dlFileEntry.getFileVersions(
354                                    WorkflowConstants.STATUS_ANY);
355                    }
356    
357                    if (dlFileVersions.isEmpty()) {
358                            DLStoreUtil.addFile(companyId, dataRepositoryId, name, new byte[0]);
359    
360                            return;
361                    }
362    
363                    dlFileVersions = ListUtil.copy(dlFileVersions);
364    
365                    Collections.sort(dlFileVersions, comparator);
366    
367                    DLFileVersion dlFileVersion = dlFileVersions.get(0);
368    
369                    DLStoreUtil.copyFileVersion(
370                            companyId, dataRepositoryId, name, dlFileVersion.getVersion(),
371                            version);
372            }
373    
374            @Override
375            protected void doVerify() throws Exception {
376                    checkMisversionedDLFileEntries();
377    
378                    checkDLFileEntryType();
379                    checkMimeTypes();
380                    checkTitles();
381                    removeOrphanedDLFileEntries();
382                    updateFileEntryAssets();
383                    updateFolderAssets();
384                    verifyTree();
385            }
386    
387            protected void removeOrphanedDLFileEntries() throws Exception {
388                    List<DLFileEntry> dlFileEntries =
389                            DLFileEntryLocalServiceUtil.getOrphanedFileEntries();
390    
391                    if (_log.isDebugEnabled()) {
392                            _log.debug(
393                                    "Processing " + dlFileEntries.size() +
394                                            " file entries with no group");
395                    }
396    
397                    for (DLFileEntry dlFileEntry : dlFileEntries) {
398                            try {
399                                    DLFileEntryLocalServiceUtil.deleteFileEntry(
400                                            dlFileEntry.getFileEntryId());
401                            }
402                            catch (Exception e) {
403                                    if (_log.isWarnEnabled()) {
404                                            _log.warn(
405                                                    "Unable to remove file entry " +
406                                                            dlFileEntry.getFileEntryId() + ": " +
407                                                                    e.getMessage());
408                                    }
409                            }
410                    }
411    
412                    if (_log.isDebugEnabled()) {
413                            _log.debug("Removed orphaned file entries");
414                    }
415            }
416    
417            protected void updateFileEntryAssets() throws Exception {
418                    List<DLFileEntry> dlFileEntries =
419                            DLFileEntryLocalServiceUtil.getNoAssetFileEntries();
420    
421                    if (_log.isDebugEnabled()) {
422                            _log.debug(
423                                    "Processing " + dlFileEntries.size() +
424                                            " file entries with no asset");
425                    }
426    
427                    for (DLFileEntry dlFileEntry : dlFileEntries) {
428                            FileEntry fileEntry = new LiferayFileEntry(dlFileEntry);
429                            FileVersion fileVersion = new LiferayFileVersion(
430                                    dlFileEntry.getFileVersion());
431    
432                            try {
433                                    DLAppHelperLocalServiceUtil.updateAsset(
434                                            dlFileEntry.getUserId(), fileEntry, fileVersion, null, null,
435                                            null);
436                            }
437                            catch (Exception e) {
438                                    if (_log.isWarnEnabled()) {
439                                            _log.warn(
440                                                    "Unable to update asset for file entry " +
441                                                            dlFileEntry.getFileEntryId() + ": " +
442                                                                    e.getMessage());
443                                    }
444                            }
445                    }
446    
447                    if (_log.isDebugEnabled()) {
448                            _log.debug("Assets verified for file entries");
449                    }
450            }
451    
452            protected void updateFolderAssets() throws Exception {
453                    List<DLFolder> dlFolders = DLFolderLocalServiceUtil.getNoAssetFolders();
454    
455                    if (_log.isDebugEnabled()) {
456                            _log.debug(
457                                    "Processing " + dlFolders.size() + " folders with no asset");
458                    }
459    
460                    for (DLFolder dlFolder : dlFolders) {
461                            Folder folder = new LiferayFolder(dlFolder);
462    
463                            try {
464                                    DLAppHelperLocalServiceUtil.updateAsset(
465                                            dlFolder.getUserId(), folder, null, null, null);
466                            }
467                            catch (Exception e) {
468                                    if (_log.isWarnEnabled()) {
469                                            _log.warn(
470                                                    "Unable to update asset for folder " +
471                                                            dlFolder.getFolderId() + ": " + e.getMessage());
472                                    }
473                            }
474                    }
475    
476                    if (_log.isDebugEnabled()) {
477                            _log.debug("Assets verified for folders");
478                    }
479            }
480    
481            protected void verifyTree() throws Exception {
482                    long[] companyIds = PortalInstances.getCompanyIdsBySQL();
483    
484                    for (long companyId : companyIds) {
485                            DLFileEntryLocalServiceUtil.rebuildTree(companyId);
486                            DLFileShortcutLocalServiceUtil.rebuildTree(companyId);
487                            DLFileVersionLocalServiceUtil.rebuildTree(companyId);
488                            DLFolderLocalServiceUtil.rebuildTree(companyId);
489                    }
490            }
491    
492            private static Log _log = LogFactoryUtil.getLog(
493                    VerifyDocumentLibrary.class);
494    
495    }