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