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