001    /**
002     * Copyright (c) 2000-2012 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.GetterUtil;
032    import com.liferay.portal.kernel.util.ListUtil;
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    
056    import java.io.InputStream;
057    
058    import java.util.Collections;
059    import java.util.Date;
060    import java.util.List;
061    
062    /**
063     * @author Raymond Augé
064     * @author Douglas Wong
065     * @author Alexander Chow
066     */
067    public class VerifyDocumentLibrary extends VerifyProcess {
068    
069            protected void addDLFileVersion(DLFileEntry dlFileEntry)
070                    throws SystemException {
071    
072                    long fileVersionId = CounterLocalServiceUtil.increment();
073    
074                    DLFileVersion dlFileVersion =
075                            DLFileVersionLocalServiceUtil.createDLFileVersion(fileVersionId);
076    
077                    dlFileVersion.setGroupId(dlFileEntry.getGroupId());
078                    dlFileVersion.setCompanyId(dlFileEntry.getCompanyId());
079    
080                    long versionUserId = dlFileEntry.getVersionUserId();
081    
082                    if (versionUserId <= 0) {
083                            versionUserId = dlFileEntry.getUserId();
084                    }
085    
086                    dlFileVersion.setUserId(versionUserId);
087    
088                    String versionUserName = GetterUtil.getString(
089                            dlFileEntry.getVersionUserName(), dlFileEntry.getUserName());
090    
091                    dlFileVersion.setUserName(versionUserName);
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(versionUserId);
108                    dlFileVersion.setStatusByUserName(versionUserName);
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.setName(DLFileEntryTypeConstants.NAME_BASIC_DOCUMENT);
131    
132                    DLFileEntryTypeLocalServiceUtil.updateDLFileEntryType(dlFileEntryType);
133            }
134    
135            protected void checkFileEntryMimeTypes(final String originalMimeType)
136                    throws Exception {
137    
138                    ActionableDynamicQuery actionableDynamicQuery =
139                            new DLFileEntryActionableDynamicQuery() {
140    
141                            @Override
142                            protected void performAction(Object object)
143                                    throws PortalException, SystemException {
144    
145                                    DLFileEntry dlFileEntry = (DLFileEntry)object;
146    
147                                    InputStream inputStream =
148                                            DLFileEntryLocalServiceUtil.getFileAsStream(
149                                                    dlFileEntry.getUserId(), dlFileEntry.getFileEntryId(),
150                                                    dlFileEntry.getVersion(), false);
151    
152                                    String title = DLUtil.getTitleWithExtension(
153                                            dlFileEntry.getTitle(), dlFileEntry.getExtension());
154    
155                                    String mimeType = MimeTypesUtil.getContentType(
156                                            inputStream, title);
157    
158                                    if (mimeType.equals(originalMimeType)) {
159                                            return;
160                                    }
161    
162                                    dlFileEntry.setMimeType(mimeType);
163    
164                                    DLFileEntryLocalServiceUtil.updateDLFileEntry(dlFileEntry);
165    
166                                    DLFileVersion dlFileVersion = dlFileEntry.getFileVersion();
167    
168                                    dlFileVersion.setMimeType(mimeType);
169    
170                                    DLFileVersionLocalServiceUtil.updateDLFileVersion(
171                                            dlFileVersion);
172                            }
173    
174                    };
175    
176                    actionableDynamicQuery.performActions();
177            }
178    
179            protected void checkFileVersionMimeTypes(final String originalMimeType)
180                    throws Exception {
181    
182                    ActionableDynamicQuery actionableDynamicQuery =
183                            new DLFileVersionActionableDynamicQuery() {
184    
185                            @Override
186                            protected void performAction(Object object)
187                                    throws PortalException, SystemException {
188    
189                                    DLFileVersion dlFileVersion = (DLFileVersion)object;
190    
191                                    InputStream inputStream =
192                                            DLFileEntryLocalServiceUtil.getFileAsStream(
193                                                    dlFileVersion.getUserId(),
194                                                    dlFileVersion.getFileEntryId(),
195                                                    dlFileVersion.getVersion(), false);
196    
197                                    String title = DLUtil.getTitleWithExtension(
198                                            dlFileVersion.getTitle(), dlFileVersion.getExtension());
199    
200                                    String mimeType = MimeTypesUtil.getContentType(
201                                            inputStream, title);
202    
203                                    if (mimeType.equals(originalMimeType)) {
204                                            return;
205                                    }
206    
207                                    dlFileVersion.setMimeType(mimeType);
208    
209                                    DLFileVersionLocalServiceUtil.updateDLFileVersion(
210                                            dlFileVersion);
211                            }
212    
213                    };
214    
215                    actionableDynamicQuery.performActions();
216            }
217    
218            protected void checkMimeTypes() throws Exception {
219                    String[] mimeTypes = {
220                            ContentTypes.APPLICATION_OCTET_STREAM,
221                            DLWebDAVStorageImpl.MS_OFFICE_2010_TEXT_XML_UTF8
222                    };
223    
224                    for (String mimeType : mimeTypes) {
225                            checkFileEntryMimeTypes(mimeType);
226                            checkFileVersionMimeTypes(mimeType);
227                    }
228    
229                    if (_log.isDebugEnabled()) {
230                            _log.debug("Fixed file entries with invalid mime types");
231                    }
232            }
233    
234            protected void checkMisversionedDLFileEntries() throws Exception {
235                    List<DLFileEntry> dlFileEntries =
236                            DLFileEntryLocalServiceUtil.getMisversionedFileEntries();
237    
238                    if (_log.isDebugEnabled()) {
239                            _log.debug(
240                                    "Processing " + dlFileEntries.size() +
241                                            " misversioned file entries");
242                    }
243    
244                    for (DLFileEntry dlFileEntry : dlFileEntries) {
245                            copyDLFileEntry(dlFileEntry);
246    
247                            addDLFileVersion(dlFileEntry);
248                    }
249    
250                    if (_log.isDebugEnabled()) {
251                            _log.debug("Fixed misversioned file entries");
252                    }
253            }
254    
255            protected void checkTitles() throws Exception {
256                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
257                            DLFileEntry.class);
258    
259                    Criterion criterion1 = RestrictionsFactoryUtil.like("title", "%/%");
260                    Criterion criterion2 = RestrictionsFactoryUtil.like("title", "%\\\\%");
261    
262                    dynamicQuery.add(RestrictionsFactoryUtil.or(criterion1, criterion2));
263    
264                    List<DLFileEntry> dlFileEntries =
265                            DLFileEntryLocalServiceUtil.dynamicQuery(dynamicQuery);
266    
267                    for (DLFileEntry dlFileEntry : dlFileEntries) {
268                            String title = dlFileEntry.getTitle();
269    
270                            String newTitle = title.replace(StringPool.SLASH, StringPool.BLANK);
271    
272                            newTitle = newTitle.replace(
273                                    StringPool.BACK_SLASH, StringPool.UNDERLINE);
274    
275                            dlFileEntry.setTitle(newTitle);
276    
277                            DLFileEntryLocalServiceUtil.updateDLFileEntry(dlFileEntry);
278    
279                            DLFileVersion dlFileVersion = dlFileEntry.getFileVersion();
280    
281                            dlFileVersion.setTitle(newTitle);
282    
283                            DLFileVersionLocalServiceUtil.updateDLFileVersion(dlFileVersion);
284    
285                            if (_log.isDebugEnabled()) {
286                                    _log.debug(
287                                            "Invalid document title " + title + "renamed to " +
288                                                    newTitle);
289                            }
290                    }
291            }
292    
293            protected void copyDLFileEntry(DLFileEntry dlFileEntry)
294                    throws PortalException, SystemException {
295    
296                    long companyId = dlFileEntry.getCompanyId();
297                    long dataRepositoryId = dlFileEntry.getDataRepositoryId();
298                    String name = dlFileEntry.getName();
299                    String version = dlFileEntry.getVersion();
300    
301                    if (DLStoreUtil.hasFile(companyId, dataRepositoryId, name, version)) {
302                            return;
303                    }
304    
305                    FileVersionVersionComparator comparator =
306                            new FileVersionVersionComparator();
307    
308                    List<DLFileVersion> dlFileVersions = dlFileEntry.getFileVersions(
309                            WorkflowConstants.STATUS_APPROVED);
310    
311                    if (dlFileVersions.isEmpty()) {
312                            dlFileVersions = dlFileEntry.getFileVersions(
313                                    WorkflowConstants.STATUS_ANY);
314                    }
315    
316                    if (dlFileVersions.isEmpty()) {
317                            DLStoreUtil.addFile(companyId, dataRepositoryId, name, new byte[0]);
318    
319                            return;
320                    }
321    
322                    dlFileVersions = ListUtil.copy(dlFileVersions);
323    
324                    Collections.sort(dlFileVersions, comparator);
325    
326                    DLFileVersion dlFileVersion = dlFileVersions.get(0);
327    
328                    DLStoreUtil.copyFileVersion(
329                            companyId, dataRepositoryId, name, dlFileVersion.getVersion(),
330                            version);
331            }
332    
333            @Override
334            protected void doVerify() throws Exception {
335                    checkMisversionedDLFileEntries();
336    
337                    checkDLFileEntryType();
338                    checkMimeTypes();
339                    checkTitles();
340                    removeOrphanedDLFileEntries();
341                    updateFileEntryAssets();
342                    updateFolderAssets();
343            }
344    
345            protected void removeOrphanedDLFileEntries() throws Exception {
346                    List<DLFileEntry> dlFileEntries =
347                            DLFileEntryLocalServiceUtil.getOrphanedFileEntries();
348    
349                    if (_log.isDebugEnabled()) {
350                            _log.debug(
351                                    "Processing " + dlFileEntries.size() +
352                                            " file entries with no group");
353                    }
354    
355                    for (DLFileEntry dlFileEntry : dlFileEntries) {
356                            try {
357                                    DLFileEntryLocalServiceUtil.deleteFileEntry(
358                                            dlFileEntry.getFileEntryId());
359                            }
360                            catch (Exception e) {
361                                    if (_log.isWarnEnabled()) {
362                                            _log.warn(
363                                                    "Unable to remove file entry " +
364                                                            dlFileEntry.getFileEntryId() + ": " +
365                                                                    e.getMessage());
366                                    }
367                            }
368                    }
369    
370                    if (_log.isDebugEnabled()) {
371                            _log.debug("Removed orphaned file entries");
372                    }
373            }
374    
375            protected void updateFileEntryAssets() throws Exception {
376                    List<DLFileEntry> dlFileEntries =
377                            DLFileEntryLocalServiceUtil.getNoAssetFileEntries();
378    
379                    if (_log.isDebugEnabled()) {
380                            _log.debug(
381                                    "Processing " + dlFileEntries.size() +
382                                            " file entries with no asset");
383                    }
384    
385                    for (DLFileEntry dlFileEntry : dlFileEntries) {
386                            FileEntry fileEntry = new LiferayFileEntry(dlFileEntry);
387                            FileVersion fileVersion = new LiferayFileVersion(
388                                    dlFileEntry.getFileVersion());
389    
390                            try {
391                                    DLAppHelperLocalServiceUtil.updateAsset(
392                                            dlFileEntry.getUserId(), fileEntry, fileVersion, null, null,
393                                            null);
394                            }
395                            catch (Exception e) {
396                                    if (_log.isWarnEnabled()) {
397                                            _log.warn(
398                                                    "Unable to update asset for file entry " +
399                                                            dlFileEntry.getFileEntryId() + ": " +
400                                                                    e.getMessage());
401                                    }
402                            }
403                    }
404    
405                    if (_log.isDebugEnabled()) {
406                            _log.debug("Assets verified for file entries");
407                    }
408            }
409    
410            protected void updateFolderAssets() throws Exception {
411                    List<DLFolder> dlFolders = DLFolderLocalServiceUtil.getNoAssetFolders();
412    
413                    if (_log.isDebugEnabled()) {
414                            _log.debug(
415                                    "Processing " + dlFolders.size() + " folders with no asset");
416                    }
417    
418                    for (DLFolder dlFolder : dlFolders) {
419                            Folder folder = new LiferayFolder(dlFolder);
420    
421                            try {
422                                    DLAppHelperLocalServiceUtil.updateAsset(
423                                            dlFolder.getUserId(), folder, null, null, null);
424                            }
425                            catch (Exception e) {
426                                    if (_log.isWarnEnabled()) {
427                                            _log.warn(
428                                                    "Unable to update asset for folder " +
429                                                            dlFolder.getFolderId() + ": " + e.getMessage());
430                                    }
431                            }
432                    }
433    
434                    if (_log.isDebugEnabled()) {
435                            _log.debug("Assets verified for folders");
436                    }
437            }
438    
439            private static Log _log = LogFactoryUtil.getLog(
440                    VerifyDocumentLibrary.class);
441    
442    }