001    /**
002     * Copyright (c) 2000-present 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.portlet.documentlibrary.util;
016    
017    import com.liferay.portal.kernel.configuration.Filter;
018    import com.liferay.portal.kernel.exception.PortalException;
019    import com.liferay.portal.kernel.language.LanguageUtil;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.portlet.PortletProvider;
023    import com.liferay.portal.kernel.portlet.PortletProviderUtil;
024    import com.liferay.portal.kernel.repository.model.FileEntry;
025    import com.liferay.portal.kernel.repository.model.FileVersion;
026    import com.liferay.portal.kernel.repository.model.Folder;
027    import com.liferay.portal.kernel.search.Document;
028    import com.liferay.portal.kernel.search.Field;
029    import com.liferay.portal.kernel.search.Hits;
030    import com.liferay.portal.kernel.util.ArrayUtil;
031    import com.liferay.portal.kernel.util.Constants;
032    import com.liferay.portal.kernel.util.FileUtil;
033    import com.liferay.portal.kernel.util.GetterUtil;
034    import com.liferay.portal.kernel.util.HtmlUtil;
035    import com.liferay.portal.kernel.util.HttpUtil;
036    import com.liferay.portal.kernel.util.OrderByComparator;
037    import com.liferay.portal.kernel.util.PrefsPropsUtil;
038    import com.liferay.portal.kernel.util.PropsKeys;
039    import com.liferay.portal.kernel.util.PropsUtil;
040    import com.liferay.portal.kernel.util.SetUtil;
041    import com.liferay.portal.kernel.util.StringBundler;
042    import com.liferay.portal.kernel.util.StringPool;
043    import com.liferay.portal.kernel.util.StringUtil;
044    import com.liferay.portal.kernel.util.Validator;
045    import com.liferay.portal.kernel.util.WebKeys;
046    import com.liferay.portal.kernel.workflow.WorkflowConstants;
047    import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
048    import com.liferay.portal.model.Company;
049    import com.liferay.portal.model.Group;
050    import com.liferay.portal.model.LayoutConstants;
051    import com.liferay.portal.model.Subscription;
052    import com.liferay.portal.service.GroupLocalServiceUtil;
053    import com.liferay.portal.service.ServiceContext;
054    import com.liferay.portal.service.SubscriptionLocalServiceUtil;
055    import com.liferay.portal.service.WorkflowDefinitionLinkLocalServiceUtil;
056    import com.liferay.portal.theme.PortletDisplay;
057    import com.liferay.portal.theme.ThemeDisplay;
058    import com.liferay.portal.util.PortalUtil;
059    import com.liferay.portal.util.PropsValues;
060    import com.liferay.portlet.PortletURLFactoryUtil;
061    import com.liferay.portlet.documentlibrary.model.DLFileEntryConstants;
062    import com.liferay.portlet.documentlibrary.model.DLFileEntryType;
063    import com.liferay.portlet.documentlibrary.model.DLFileEntryTypeConstants;
064    import com.liferay.portlet.documentlibrary.model.DLFileShortcut;
065    import com.liferay.portlet.documentlibrary.model.DLFileVersion;
066    import com.liferay.portlet.documentlibrary.model.DLFolder;
067    import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
068    import com.liferay.portlet.documentlibrary.service.DLAppLocalServiceUtil;
069    import com.liferay.portlet.documentlibrary.service.DLFolderLocalServiceUtil;
070    import com.liferay.portlet.documentlibrary.util.comparator.RepositoryModelCreateDateComparator;
071    import com.liferay.portlet.documentlibrary.util.comparator.RepositoryModelModifiedDateComparator;
072    import com.liferay.portlet.documentlibrary.util.comparator.RepositoryModelReadCountComparator;
073    import com.liferay.portlet.documentlibrary.util.comparator.RepositoryModelSizeComparator;
074    import com.liferay.portlet.documentlibrary.util.comparator.RepositoryModelTitleComparator;
075    import com.liferay.portlet.documentlibrary.webdav.DLWebDAVUtil;
076    import com.liferay.portlet.trash.util.TrashUtil;
077    
078    import java.io.Serializable;
079    
080    import java.util.ArrayList;
081    import java.util.Collections;
082    import java.util.Date;
083    import java.util.HashMap;
084    import java.util.HashSet;
085    import java.util.LinkedHashMap;
086    import java.util.List;
087    import java.util.Map;
088    import java.util.Set;
089    import java.util.TreeSet;
090    
091    import javax.portlet.PortletRequest;
092    import javax.portlet.PortletURL;
093    
094    import javax.servlet.http.HttpServletRequest;
095    
096    /**
097     * @author Brian Wing Shun Chan
098     * @author Julio Camarero
099     */
100    public class DLImpl implements DL {
101    
102            @Override
103            public int compareVersions(String version1, String version2) {
104                    int[] splitVersion1 = StringUtil.split(version1, StringPool.PERIOD, 0);
105                    int[] splitVersion2 = StringUtil.split(version2, StringPool.PERIOD, 0);
106    
107                    if ((splitVersion1.length != 2) && (splitVersion2.length != 2)) {
108                            return 0;
109                    }
110                    else if (splitVersion1.length != 2) {
111                            return -1;
112                    }
113                    else if (splitVersion2.length != 2) {
114                            return 1;
115                    }
116    
117                    if (splitVersion1[0] > splitVersion2[0]) {
118                            return 1;
119                    }
120                    else if (splitVersion1[0] < splitVersion2[0]) {
121                            return -1;
122                    }
123                    else if (splitVersion1[1] > splitVersion2[1]) {
124                            return 1;
125                    }
126                    else if (splitVersion1[1] < splitVersion2[1]) {
127                            return -1;
128                    }
129    
130                    return 0;
131            }
132    
133            @Override
134            public String getAbsolutePath(PortletRequest portletRequest, long folderId)
135                    throws PortalException {
136    
137                    ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
138                            WebKeys.THEME_DISPLAY);
139    
140                    if (folderId == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
141                            return themeDisplay.translate("home");
142                    }
143    
144                    Folder folder = DLAppLocalServiceUtil.getFolder(folderId);
145    
146                    List<Folder> folders = folder.getAncestors();
147    
148                    Collections.reverse(folders);
149    
150                    StringBundler sb = new StringBundler((folders.size() * 3) + 5);
151    
152                    sb.append(themeDisplay.translate("home"));
153                    sb.append(StringPool.SPACE);
154    
155                    for (Folder curFolder : folders) {
156                            sb.append(StringPool.RAQUO_CHAR);
157                            sb.append(StringPool.SPACE);
158                            sb.append(curFolder.getName());
159                    }
160    
161                    sb.append(StringPool.RAQUO_CHAR);
162                    sb.append(StringPool.SPACE);
163                    sb.append(folder.getName());
164    
165                    return sb.toString();
166            }
167    
168            @Override
169            public Set<String> getAllMediaGalleryMimeTypes() {
170                    return _allMediaGalleryMimeTypes;
171            }
172    
173            @Override
174            public String getDDMStructureKey(DLFileEntryType dlFileEntryType) {
175                    return getDDMStructureKey(dlFileEntryType.getUuid());
176            }
177    
178            @Override
179            public String getDDMStructureKey(String fileEntryTypeUuid) {
180                    return _STRUCTURE_KEY_PREFIX +
181                            StringUtil.toUpperCase(fileEntryTypeUuid);
182            }
183    
184            @Override
185            public String getDeprecatedDDMStructureKey(
186                    DLFileEntryType dlFileEntryType) {
187    
188                    return getDeprecatedDDMStructureKey(
189                            dlFileEntryType.getFileEntryTypeId());
190            }
191    
192            @Override
193            public String getDeprecatedDDMStructureKey(long fileEntryTypeId) {
194                    return _STRUCTURE_KEY_PREFIX + fileEntryTypeId;
195            }
196    
197            @Override
198            public String getDividedPath(long id) {
199                    StringBundler sb = new StringBundler(16);
200    
201                    long dividend = id;
202    
203                    while ((dividend / _DIVISOR) != 0) {
204                            sb.append(StringPool.SLASH);
205                            sb.append(dividend % _DIVISOR);
206    
207                            dividend = dividend / _DIVISOR;
208                    }
209    
210                    sb.append(StringPool.SLASH);
211                    sb.append(id);
212    
213                    return sb.toString();
214            }
215    
216            @Override
217            public String getDLFileEntryControlPanelLink(
218                    PortletRequest portletRequest, long fileEntryId) {
219    
220                    String portletId = PortletProviderUtil.getPortletId(
221                            FileEntry.class.getName(), PortletProvider.Action.MANAGE);
222    
223                    PortletURL portletURL = PortalUtil.getControlPanelPortletURL(
224                            portletRequest, portletId, PortletRequest.RENDER_PHASE);
225    
226                    portletURL.setParameter(
227                            "mvcRenderCommandName", "/document_library/view_file_entry");
228                    portletURL.setParameter("fileEntryId", String.valueOf(fileEntryId));
229    
230                    return portletURL.toString();
231            }
232    
233            @Override
234            public String getDLFolderControlPanelLink(
235                    PortletRequest portletRequest, long folderId) {
236    
237                    String portletId = PortletProviderUtil.getPortletId(
238                            Folder.class.getName(), PortletProvider.Action.MANAGE);
239    
240                    PortletURL portletURL = PortalUtil.getControlPanelPortletURL(
241                            portletRequest, portletId, PortletRequest.RENDER_PHASE);
242    
243                    portletURL.setParameter(
244                            "mvcRenderCommandName", "/document_library/view");
245                    portletURL.setParameter("folderId", String.valueOf(folderId));
246    
247                    return portletURL.toString();
248            }
249    
250            @Override
251            public String getDownloadURL(
252                    FileEntry fileEntry, FileVersion fileVersion, ThemeDisplay themeDisplay,
253                    String queryString) {
254    
255                    return getDownloadURL(
256                            fileEntry, fileVersion, themeDisplay, queryString, true, true);
257            }
258    
259            @Override
260            public String getDownloadURL(
261                    FileEntry fileEntry, FileVersion fileVersion, ThemeDisplay themeDisplay,
262                    String queryString, boolean appendVersion, boolean absoluteURL) {
263    
264                    String previewURL = getPreviewURL(
265                            fileEntry, fileVersion, themeDisplay, queryString, appendVersion,
266                            absoluteURL);
267    
268                    return HttpUtil.addParameter(previewURL, "download", true);
269            }
270    
271            @Override
272            public Map<String, String> getEmailDefinitionTerms(
273                    PortletRequest portletRequest, String emailFromAddress,
274                    String emailFromName) {
275    
276                    ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
277                            WebKeys.THEME_DISPLAY);
278    
279                    Map<String, String> definitionTerms = new LinkedHashMap<>();
280    
281                    definitionTerms.put(
282                            "[$COMPANY_ID$]",
283                            LanguageUtil.get(
284                                    themeDisplay.getLocale(),
285                                    "the-company-id-associated-with-the-document"));
286                    definitionTerms.put(
287                            "[$COMPANY_MX$]",
288                            LanguageUtil.get(
289                                    themeDisplay.getLocale(),
290                                    "the-company-mx-associated-with-the-document"));
291                    definitionTerms.put(
292                            "[$COMPANY_NAME$]",
293                            LanguageUtil.get(
294                                    themeDisplay.getLocale(),
295                                    "the-company-name-associated-with-the-document"));
296                    definitionTerms.put(
297                            "[$DOCUMENT_TITLE$]",
298                            LanguageUtil.get(themeDisplay.getLocale(), "the-document-title"));
299                    definitionTerms.put(
300                            "[$DOCUMENT_TYPE$]",
301                            LanguageUtil.get(themeDisplay.getLocale(), "the-document-type"));
302                    definitionTerms.put(
303                            "[$DOCUMENT_URL$]",
304                            LanguageUtil.get(themeDisplay.getLocale(), "the-document-url"));
305                    definitionTerms.put(
306                            "[$DOCUMENT_USER_ADDRESS$]",
307                            LanguageUtil.get(
308                                    themeDisplay.getLocale(),
309                                    "the-email-address-of-the-user-who-added-the-document"));
310                    definitionTerms.put(
311                            "[$DOCUMENT_USER_NAME$]",
312                            LanguageUtil.get(
313                                    themeDisplay.getLocale(), "the-user-who-added-the-document"));
314                    definitionTerms.put(
315                            "[$FOLDER_NAME$]",
316                            LanguageUtil.get(
317                                    themeDisplay.getLocale(),
318                                    "the-folder-in-which-the-document-has-been-added"));
319                    definitionTerms.put(
320                            "[$FROM_ADDRESS$]", HtmlUtil.escape(emailFromAddress));
321                    definitionTerms.put("[$FROM_NAME$]", HtmlUtil.escape(emailFromName));
322    
323                    Company company = themeDisplay.getCompany();
324    
325                    definitionTerms.put("[$PORTAL_URL$]", company.getVirtualHostname());
326    
327                    PortletDisplay portletDisplay = themeDisplay.getPortletDisplay();
328    
329                    definitionTerms.put(
330                            "[$PORTLET_NAME$]", HtmlUtil.escape(portletDisplay.getTitle()));
331    
332                    definitionTerms.put(
333                            "[$SITE_NAME$]",
334                            LanguageUtil.get(
335                                    themeDisplay.getLocale(),
336                                    "the-site-name-associated-with-the-document"));
337                    definitionTerms.put(
338                            "[$TO_ADDRESS$]",
339                            LanguageUtil.get(
340                                    themeDisplay.getLocale(),
341                                    "the-address-of-the-email-recipient"));
342                    definitionTerms.put(
343                            "[$TO_NAME$]",
344                            LanguageUtil.get(
345                                    themeDisplay.getLocale(), "the-name-of-the-email-recipient"));
346    
347                    return definitionTerms;
348            }
349    
350            @Override
351            public Map<String, String> getEmailFromDefinitionTerms(
352                    PortletRequest portletRequest, String emailFromAddress,
353                    String emailFromName) {
354    
355                    ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
356                            WebKeys.THEME_DISPLAY);
357    
358                    Map<String, String> definitionTerms = new LinkedHashMap<>();
359    
360                    definitionTerms.put(
361                            "[$COMPANY_ID$]",
362                            LanguageUtil.get(
363                                    themeDisplay.getLocale(),
364                                    "the-company-id-associated-with-the-document"));
365                    definitionTerms.put(
366                            "[$COMPANY_MX$]",
367                            LanguageUtil.get(
368                                    themeDisplay.getLocale(),
369                                    "the-company-mx-associated-with-the-document"));
370                    definitionTerms.put(
371                            "[$COMPANY_NAME$]",
372                            LanguageUtil.get(
373                                    themeDisplay.getLocale(),
374                                    "the-company-name-associated-with-the-document"));
375                    definitionTerms.put(
376                            "[$DOCUMENT_STATUS_BY_USER_NAME$]",
377                            LanguageUtil.get(
378                                    themeDisplay.getLocale(), "the-user-who-updated-the-document"));
379                    definitionTerms.put(
380                            "[$DOCUMENT_USER_ADDRESS$]",
381                            LanguageUtil.get(
382                                    themeDisplay.getLocale(),
383                                    "the-email-address-of-the-user-who-added-the-document"));
384                    definitionTerms.put(
385                            "[$DOCUMENT_USER_NAME$]",
386                            LanguageUtil.get(
387                                    themeDisplay.getLocale(), "the-user-who-added-the-document"));
388    
389                    PortletDisplay portletDisplay = themeDisplay.getPortletDisplay();
390    
391                    definitionTerms.put(
392                            "[$PORTLET_NAME$]", HtmlUtil.escape(portletDisplay.getTitle()));
393    
394                    definitionTerms.put(
395                            "[$SITE_NAME$]",
396                            LanguageUtil.get(
397                                    themeDisplay.getLocale(),
398                                    "the-site-name-associated-with-the-document"));
399    
400                    return definitionTerms;
401            }
402    
403            @Override
404            public List<FileEntry> getFileEntries(Hits hits) {
405                    List<FileEntry> entries = new ArrayList<>();
406    
407                    for (Document document : hits.getDocs()) {
408                            long fileEntryId = GetterUtil.getLong(
409                                    document.get(Field.ENTRY_CLASS_PK));
410    
411                            try {
412                                    FileEntry fileEntry = DLAppLocalServiceUtil.getFileEntry(
413                                            fileEntryId);
414    
415                                    entries.add(fileEntry);
416                            }
417                            catch (Exception e) {
418                                    if (_log.isWarnEnabled()) {
419                                            _log.warn(
420                                                    "Documents and Media search index is stale and " +
421                                                            "contains file entry " + fileEntryId);
422                                    }
423                            }
424                    }
425    
426                    return entries;
427            }
428    
429            @Override
430            public String getFileEntryImage(
431                    FileEntry fileEntry, ThemeDisplay themeDisplay) {
432    
433                    StringBundler sb = new StringBundler(5);
434    
435                    sb.append("<img src=\"");
436                    sb.append(themeDisplay.getPathThemeImages());
437                    sb.append("/file_system/small/");
438                    sb.append(fileEntry.getIcon());
439                    sb.append(".png\" style=\"border-width: 0; text-align: left;\">");
440    
441                    return sb.toString();
442            }
443    
444            @Override
445            public Set<Long> getFileEntryTypeSubscriptionClassPKs(long userId) {
446                    List<Subscription> subscriptions =
447                            SubscriptionLocalServiceUtil.getUserSubscriptions(
448                                    userId, DLFileEntryType.class.getName());
449    
450                    Set<Long> classPKs = new HashSet<>(subscriptions.size());
451    
452                    for (Subscription subscription : subscriptions) {
453                            classPKs.add(subscription.getClassPK());
454                    }
455    
456                    return classPKs;
457            }
458    
459            @Override
460            public String getFileIcon(String extension) {
461                    if (!_fileIcons.contains(extension)) {
462                            extension = _DEFAULT_FILE_ICON;
463                    }
464    
465                    return extension;
466            }
467    
468            @Override
469            public String getFileIconCssClass(String extension) {
470                    return "documents-and-media";
471            }
472    
473            @Override
474            public String getGenericName(String extension) {
475                    String genericName = _genericNames.get(extension);
476    
477                    if (genericName == null) {
478                            genericName = _DEFAULT_GENERIC_NAME;
479                    }
480    
481                    return genericName;
482            }
483    
484            @Override
485            public String getImagePreviewURL(
486                            FileEntry fileEntry, FileVersion fileVersion,
487                            ThemeDisplay themeDisplay)
488                    throws Exception {
489    
490                    String previewQueryString = null;
491    
492                    if (PropsValues.DL_FILE_ENTRY_THUMBNAIL_ENABLED) {
493                            if (ImageProcessorUtil.hasImages(fileVersion)) {
494                                    previewQueryString = "&imagePreview=1";
495                            }
496                            else if (PDFProcessorUtil.hasImages(fileVersion)) {
497                                    previewQueryString = "&previewFileIndex=1";
498                            }
499                            else if (VideoProcessorUtil.hasVideo(fileVersion)) {
500                                    previewQueryString = "&videoThumbnail=1";
501                            }
502                    }
503    
504                    return getImageSrc(
505                            fileEntry, fileVersion, themeDisplay, previewQueryString);
506            }
507    
508            @Override
509            public String getImagePreviewURL(
510                            FileEntry fileEntry, ThemeDisplay themeDisplay)
511                    throws Exception {
512    
513                    return getImagePreviewURL(
514                            fileEntry, fileEntry.getFileVersion(), themeDisplay);
515            }
516    
517            @Override
518            public String getPreviewURL(
519                    FileEntry fileEntry, FileVersion fileVersion, ThemeDisplay themeDisplay,
520                    String queryString) {
521    
522                    return getPreviewURL(
523                            fileEntry, fileVersion, themeDisplay, queryString, true, true);
524            }
525    
526            /**
527             * @deprecated As of 6.2.0, replaced by {@link #getPreviewURL(FileEntry,
528             *             FileVersion, ThemeDisplay, String, boolean, boolean)}
529             */
530            @Deprecated
531            @Override
532            public String getPreviewURL(
533                    FileEntry fileEntry, FileVersion fileVersion, ThemeDisplay themeDisplay,
534                    String queryString, boolean appendToken) {
535    
536                    return getPreviewURL(
537                            fileEntry, fileVersion, themeDisplay, queryString, true, true);
538            }
539    
540            @Override
541            public String getPreviewURL(
542                    FileEntry fileEntry, FileVersion fileVersion, ThemeDisplay themeDisplay,
543                    String queryString, boolean appendVersion, boolean absoluteURL) {
544    
545                    StringBundler sb = new StringBundler(15);
546    
547                    if ((themeDisplay != null) && absoluteURL) {
548                            sb.append(themeDisplay.getPortalURL());
549                    }
550    
551                    sb.append(PortalUtil.getPathContext());
552                    sb.append("/documents/");
553                    sb.append(fileEntry.getRepositoryId());
554                    sb.append(StringPool.SLASH);
555                    sb.append(fileEntry.getFolderId());
556                    sb.append(StringPool.SLASH);
557    
558                    String fileName = fileEntry.getFileName();
559    
560                    if (fileEntry.isInTrash()) {
561                            fileName = TrashUtil.getOriginalTitle(fileEntry.getFileName());
562                    }
563    
564                    sb.append(HttpUtil.encodeURL(HtmlUtil.unescape(fileName)));
565    
566                    sb.append(StringPool.SLASH);
567                    sb.append(HttpUtil.encodeURL(fileEntry.getUuid()));
568    
569                    if (appendVersion) {
570                            sb.append("?version=");
571                            sb.append(fileVersion.getVersion());
572                    }
573    
574                    if (ImageProcessorUtil.isImageSupported(fileVersion)) {
575                            if (appendVersion) {
576                                    sb.append("&t=");
577                            }
578                            else {
579                                    sb.append("?t=");
580                            }
581    
582                            Date modifiedDate = fileVersion.getModifiedDate();
583    
584                            sb.append(modifiedDate.getTime());
585                    }
586    
587                    sb.append(queryString);
588    
589                    String previewURL = sb.toString();
590    
591                    if ((themeDisplay != null) && themeDisplay.isAddSessionIdToURL()) {
592                            return PortalUtil.getURLWithSessionId(
593                                    previewURL, themeDisplay.getSessionId());
594                    }
595    
596                    return previewURL;
597            }
598    
599            @Override
600            public <T> OrderByComparator<T> getRepositoryModelOrderByComparator(
601                    String orderByCol, String orderByType) {
602    
603                    return getRepositoryModelOrderByComparator(
604                            orderByCol, orderByType, false);
605            }
606    
607            @Override
608            public <T> OrderByComparator<T> getRepositoryModelOrderByComparator(
609                    String orderByCol, String orderByType, boolean orderByModel) {
610    
611                    boolean orderByAsc = true;
612    
613                    if (orderByType.equals("desc")) {
614                            orderByAsc = false;
615                    }
616    
617                    OrderByComparator<T> orderByComparator = null;
618    
619                    if (orderByCol.equals("creationDate")) {
620                            orderByComparator = new RepositoryModelCreateDateComparator<>(
621                                    orderByAsc, orderByModel);
622                    }
623                    else if (orderByCol.equals("downloads")) {
624                            orderByComparator = new RepositoryModelReadCountComparator<>(
625                                    orderByAsc, orderByModel);
626                    }
627                    else if (orderByCol.equals("modifiedDate")) {
628                            orderByComparator = new RepositoryModelModifiedDateComparator<>(
629                                    orderByAsc, orderByModel);
630                    }
631                    else if (orderByCol.equals("size")) {
632                            orderByComparator = new RepositoryModelSizeComparator<>(
633                                    orderByAsc, orderByModel);
634                    }
635                    else {
636                            orderByComparator = new RepositoryModelTitleComparator<>(
637                                    orderByAsc, orderByModel);
638                    }
639    
640                    return orderByComparator;
641            }
642    
643            @Override
644            public String getSanitizedFileName(String title, String extension) {
645                    String fileName = StringUtil.replace(
646                            title, StringPool.SLASH, StringPool.UNDERLINE);
647    
648                    if (Validator.isNotNull(extension) &&
649                            !StringUtil.endsWith(fileName, StringPool.PERIOD + extension)) {
650    
651                            fileName += StringPool.PERIOD + extension;
652                    }
653    
654                    if (fileName.length() > 255) {
655                            int x = fileName.length() - 1;
656    
657                            if (Validator.isNotNull(extension)) {
658                                    x = fileName.lastIndexOf(StringPool.PERIOD);
659                            }
660    
661                            int y = x - (fileName.length() - 255);
662    
663                            fileName = fileName.substring(0, y) + fileName.substring(x);
664                    }
665    
666                    return fileName;
667            }
668    
669            @Override
670            public String getTempFileId(long id, String version) {
671                    return getTempFileId(id, version, null);
672            }
673    
674            @Override
675            public String getTempFileId(long id, String version, String languageId) {
676                    if (Validator.isNull(languageId)) {
677                            return String.valueOf(id).concat(StringPool.PERIOD).concat(version);
678                    }
679    
680                    StringBundler sb = new StringBundler(5);
681    
682                    sb.append(id);
683                    sb.append(StringPool.PERIOD);
684                    sb.append(version);
685                    sb.append(StringPool.PERIOD);
686                    sb.append(languageId);
687    
688                    return sb.toString();
689            }
690    
691            /**
692             * @deprecated As of 7.0.0, replaced by {@link #getThumbnailSrc(FileEntry,
693             *             ThemeDisplay)}
694             */
695            @Deprecated
696            @Override
697            public String getThumbnailSrc(
698                            FileEntry fileEntry, DLFileShortcut dlFileShortcut,
699                            ThemeDisplay themeDisplay)
700                    throws Exception {
701    
702                    return getThumbnailSrc(
703                            fileEntry, fileEntry.getFileVersion(), themeDisplay);
704            }
705    
706            /**
707             * @deprecated As of 7.0.0, replaced by {@link #getThumbnailSrc(FileEntry,
708             *             FileVersion, ThemeDisplay)}
709             */
710            @Deprecated
711            @Override
712            public String getThumbnailSrc(
713                            FileEntry fileEntry, FileVersion fileVersion,
714                            DLFileShortcut dlFileShortcut, ThemeDisplay themeDisplay)
715                    throws Exception {
716    
717                    return getThumbnailSrc(fileEntry, fileVersion, themeDisplay);
718            }
719    
720            @Override
721            public String getThumbnailSrc(
722                            FileEntry fileEntry, FileVersion fileVersion,
723                            ThemeDisplay themeDisplay)
724                    throws Exception {
725    
726                    String thumbnailQueryString = null;
727    
728                    if (PropsValues.DL_FILE_ENTRY_THUMBNAIL_ENABLED) {
729                            if (ImageProcessorUtil.hasImages(fileVersion)) {
730                                    thumbnailQueryString = "&imageThumbnail=1";
731                            }
732                            else if (PDFProcessorUtil.hasImages(fileVersion)) {
733                                    thumbnailQueryString = "&documentThumbnail=1";
734                            }
735                            else if (VideoProcessorUtil.hasVideo(fileVersion)) {
736                                    thumbnailQueryString = "&videoThumbnail=1";
737                            }
738                    }
739    
740                    return getImageSrc(
741                            fileEntry, fileVersion, themeDisplay, thumbnailQueryString);
742            }
743    
744            @Override
745            public String getThumbnailSrc(
746                            FileEntry fileEntry, ThemeDisplay themeDisplay)
747                    throws Exception {
748    
749                    return getThumbnailSrc(
750                            fileEntry, fileEntry.getFileVersion(), themeDisplay);
751            }
752    
753            @Override
754            public String getThumbnailStyle() {
755                    return getThumbnailStyle(true, 0);
756            }
757    
758            @Override
759            public String getThumbnailStyle(boolean max, int margin) {
760                    return getThumbnailStyle(
761                            max, margin,
762                            PrefsPropsUtil.getInteger(
763                                    PropsKeys.DL_FILE_ENTRY_THUMBNAIL_MAX_HEIGHT),
764                            PrefsPropsUtil.getInteger(
765                                    PropsKeys.DL_FILE_ENTRY_THUMBNAIL_MAX_WIDTH));
766            }
767    
768            @Override
769            public String getThumbnailStyle(
770                    boolean max, int margin, int height, int width) {
771    
772                    StringBundler sb = new StringBundler(5);
773    
774                    if (max) {
775                            sb.append("max-height: ");
776                    }
777                    else {
778                            sb.append("height: ");
779                    }
780    
781                    height = height + (2 * margin);
782    
783                    sb.append(height);
784    
785                    if (max) {
786                            sb.append("px; max-width: ");
787                    }
788                    else {
789                            sb.append("px; width: ");
790                    }
791    
792                    width = width + (2 * margin);
793    
794                    sb.append(width);
795    
796                    sb.append("px;");
797    
798                    return sb.toString();
799            }
800    
801            @Override
802            public String getTitleWithExtension(FileEntry fileEntry) {
803                    String title = fileEntry.getTitle();
804                    String extension = fileEntry.getExtension();
805    
806                    return getTitleWithExtension(title, extension);
807            }
808    
809            @Override
810            public String getTitleWithExtension(String title, String extension) {
811                    if (Validator.isNotNull(extension)) {
812                            String periodAndExtension = StringPool.PERIOD.concat(extension);
813    
814                            if (!title.endsWith(periodAndExtension)) {
815                                    title += periodAndExtension;
816                            }
817                    }
818    
819                    return title;
820            }
821    
822            @Override
823            public String getUniqueFileName(
824                    long groupId, long folderId, String fileName) {
825    
826                    String uniqueFileName = fileName;
827    
828                    for (int i = 1;; i++) {
829                            try {
830                                    DLAppLocalServiceUtil.getFileEntry(
831                                            groupId, folderId, uniqueFileName);
832    
833                                    uniqueFileName = FileUtil.appendParentheticalSuffix(
834                                            fileName, String.valueOf(i));
835                            }
836                            catch (Exception e) {
837                                    break;
838                            }
839                    }
840    
841                    return uniqueFileName;
842            }
843    
844            @Override
845            public String getWebDavURL(
846                            ThemeDisplay themeDisplay, Folder folder, FileEntry fileEntry)
847                    throws PortalException {
848    
849                    return getWebDavURL(themeDisplay, folder, fileEntry, false);
850            }
851    
852            @Override
853            public String getWebDavURL(
854                            ThemeDisplay themeDisplay, Folder folder, FileEntry fileEntry,
855                            boolean manualCheckInRequired)
856                    throws PortalException {
857    
858                    return getWebDavURL(
859                            themeDisplay, folder, fileEntry, manualCheckInRequired, false);
860            }
861    
862            @Override
863            public String getWebDavURL(
864                            ThemeDisplay themeDisplay, Folder folder, FileEntry fileEntry,
865                            boolean manualCheckInRequired, boolean openDocumentUrl)
866                    throws PortalException {
867    
868                    StringBundler webDavURL = new StringBundler(7);
869    
870                    boolean secure = false;
871    
872                    if (themeDisplay.isSecure() ||
873                            PropsValues.WEBDAV_SERVLET_HTTPS_REQUIRED) {
874    
875                            secure = true;
876                    }
877    
878                    String portalURL = PortalUtil.getPortalURL(
879                            themeDisplay.getServerName(), themeDisplay.getServerPort(), secure);
880    
881                    webDavURL.append(portalURL);
882    
883                    webDavURL.append(themeDisplay.getPathContext());
884                    webDavURL.append("/webdav");
885    
886                    if (manualCheckInRequired) {
887                            webDavURL.append(MANUAL_CHECK_IN_REQUIRED_PATH);
888                    }
889    
890                    Group group = null;
891    
892                    if (fileEntry != null) {
893                            group = GroupLocalServiceUtil.getGroup(fileEntry.getGroupId());
894                    }
895                    else {
896                            group = themeDisplay.getScopeGroup();
897                    }
898    
899                    webDavURL.append(group.getFriendlyURL());
900                    webDavURL.append("/document_library");
901    
902                    StringBuilder sb = new StringBuilder();
903    
904                    if ((folder != null) &&
905                            (folder.getFolderId() !=
906                                    DLFolderConstants.DEFAULT_PARENT_FOLDER_ID)) {
907    
908                            Folder curFolder = folder;
909    
910                            while (true) {
911                                    sb.insert(0, HttpUtil.encodeURL(curFolder.getName(), true));
912                                    sb.insert(0, StringPool.SLASH);
913    
914                                    if (curFolder.getParentFolderId() ==
915                                                    DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
916    
917                                            break;
918                                    }
919    
920                                    curFolder = DLAppLocalServiceUtil.getFolder(
921                                            curFolder.getParentFolderId());
922                            }
923                    }
924    
925                    if (fileEntry != null) {
926                            sb.append(StringPool.SLASH);
927                            sb.append(DLWebDAVUtil.escapeURLTitle(fileEntry.getTitle()));
928                    }
929    
930                    webDavURL.append(sb.toString());
931    
932                    return webDavURL.toString();
933            }
934    
935            @Override
936            public boolean hasWorkflowDefinitionLink(
937                            long companyId, long groupId, long folderId, long fileEntryTypeId)
938                    throws Exception {
939    
940                    while (folderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
941                            DLFolder dlFolder = DLFolderLocalServiceUtil.fetchDLFolder(
942                                    folderId);
943    
944                            if (dlFolder == null) {
945                                    return false;
946                            }
947    
948                            if (dlFolder.getRestrictionType() !=
949                                            DLFolderConstants.RESTRICTION_TYPE_INHERIT) {
950    
951                                    break;
952                            }
953    
954                            folderId = dlFolder.getParentFolderId();
955                    }
956    
957                    if (WorkflowDefinitionLinkLocalServiceUtil.hasWorkflowDefinitionLink(
958                                    companyId, groupId, DLFolderConstants.getClassName(), folderId,
959                                    fileEntryTypeId) ||
960                            WorkflowDefinitionLinkLocalServiceUtil.hasWorkflowDefinitionLink(
961                                    companyId, groupId, DLFolderConstants.getClassName(), folderId,
962                                    DLFileEntryTypeConstants.FILE_ENTRY_TYPE_ID_ALL)) {
963    
964                            return true;
965                    }
966    
967                    return false;
968            }
969    
970            @Override
971            public boolean isAutoGeneratedDLFileEntryTypeDDMStructureKey(
972                    String ddmStructureKey) {
973    
974                    if (ddmStructureKey.startsWith(_STRUCTURE_KEY_PREFIX)) {
975                            return true;
976                    }
977    
978                    return false;
979            }
980    
981            @Override
982            public boolean isOfficeExtension(String extension) {
983                    return ArrayUtil.contains(_MICROSOFT_OFFICE_EXTENSIONS, extension);
984            }
985    
986            @Override
987            public boolean isSubscribedToFileEntryType(
988                    long companyId, long groupId, long userId, long fileEntryTypeId) {
989    
990                    if (fileEntryTypeId ==
991                                    DLFileEntryTypeConstants.FILE_ENTRY_TYPE_ID_BASIC_DOCUMENT) {
992    
993                            fileEntryTypeId = groupId;
994                    }
995    
996                    return SubscriptionLocalServiceUtil.isSubscribed(
997                            companyId, userId, DLFileEntryType.class.getName(),
998                            fileEntryTypeId);
999            }
1000    
1001            @Override
1002            public boolean isSubscribedToFolder(
1003                            long companyId, long groupId, long userId, long folderId)
1004                    throws PortalException {
1005    
1006                    return isSubscribedToFolder(companyId, groupId, userId, folderId, true);
1007            }
1008    
1009            @Override
1010            public boolean isSubscribedToFolder(
1011                            long companyId, long groupId, long userId, long folderId,
1012                            boolean recursive)
1013                    throws PortalException {
1014    
1015                    List<Long> ancestorFolderIds = new ArrayList<>();
1016    
1017                    if (folderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
1018                            Folder folder = DLAppLocalServiceUtil.getFolder(folderId);
1019    
1020                            ancestorFolderIds.add(folderId);
1021    
1022                            if (recursive) {
1023                                    ancestorFolderIds.addAll(folder.getAncestorFolderIds());
1024    
1025                                    ancestorFolderIds.add(groupId);
1026                            }
1027                    }
1028                    else {
1029                            ancestorFolderIds.add(groupId);
1030                    }
1031    
1032                    long[] folderIdsArray = ArrayUtil.toLongArray(ancestorFolderIds);
1033    
1034                    return SubscriptionLocalServiceUtil.isSubscribed(
1035                            companyId, userId, DLFolder.class.getName(), folderIdsArray);
1036            }
1037    
1038            @Override
1039            public boolean isValidVersion(String version) {
1040                    if (version.equals(DLFileEntryConstants.PRIVATE_WORKING_COPY_VERSION)) {
1041                            return true;
1042                    }
1043    
1044                    String[] versionParts = StringUtil.split(version, StringPool.PERIOD);
1045    
1046                    if (versionParts.length != 2) {
1047                            return false;
1048                    }
1049    
1050                    if (Validator.isNumber(versionParts[0]) &&
1051                            Validator.isNumber(versionParts[1])) {
1052    
1053                            return true;
1054                    }
1055    
1056                    return false;
1057            }
1058    
1059            @Override
1060            public void startWorkflowInstance(
1061                            long userId, DLFileVersion dlFileVersion, String syncEventType,
1062                            ServiceContext serviceContext)
1063                    throws PortalException {
1064    
1065                    Map<String, Serializable> workflowContext = new HashMap<>();
1066    
1067                    workflowContext.put(
1068                            WorkflowConstants.CONTEXT_URL,
1069                            getEntryURL(dlFileVersion, serviceContext));
1070                    workflowContext.put("event", syncEventType);
1071    
1072                    WorkflowHandlerRegistryUtil.startWorkflowInstance(
1073                            dlFileVersion.getCompanyId(), dlFileVersion.getGroupId(), userId,
1074                            DLFileEntryConstants.getClassName(),
1075                            dlFileVersion.getFileVersionId(), dlFileVersion, serviceContext,
1076                            workflowContext);
1077            }
1078    
1079            protected String getEntryURL(
1080                            DLFileVersion dlFileVersion, ServiceContext serviceContext)
1081                    throws PortalException {
1082    
1083                    if (Validator.equals(
1084                                    serviceContext.getCommand(), Constants.ADD_WEBDAV) ||
1085                            Validator.equals(
1086                                    serviceContext.getCommand(), Constants.UPDATE_WEBDAV)) {
1087    
1088                            return serviceContext.getPortalURL() +
1089                                    serviceContext.getCurrentURL();
1090                    }
1091    
1092                    String entryURL = GetterUtil.getString(
1093                            serviceContext.getAttribute("entryURL"));
1094    
1095                    if (Validator.isNotNull(entryURL)) {
1096                            return entryURL;
1097                    }
1098    
1099                    HttpServletRequest request = serviceContext.getRequest();
1100    
1101                    if ((request == null) || (serviceContext.getThemeDisplay() == null)) {
1102                            return StringPool.BLANK;
1103                    }
1104    
1105                    PortletURL portletURL = null;
1106    
1107                    long plid = serviceContext.getPlid();
1108                    long controlPanelPlid = PortalUtil.getControlPanelPlid(
1109                            serviceContext.getCompanyId());
1110                    String portletId = PortletProviderUtil.getPortletId(
1111                            FileEntry.class.getName(), PortletProvider.Action.VIEW);
1112    
1113                    if ((plid == controlPanelPlid) ||
1114                            (plid == LayoutConstants.DEFAULT_PLID)) {
1115    
1116                            portletURL = PortalUtil.getControlPanelPortletURL(
1117                                    request, portletId, PortletRequest.RENDER_PHASE);
1118                    }
1119                    else {
1120                            portletURL = PortletURLFactoryUtil.create(
1121                                    request, portletId, plid, PortletRequest.RENDER_PHASE);
1122                    }
1123    
1124                    portletURL.setParameter(
1125                            "mvcRenderCommandName", "/document_library/view_file_entry");
1126                    portletURL.setParameter(
1127                            "fileEntryId", String.valueOf(dlFileVersion.getFileEntryId()));
1128    
1129                    return portletURL.toString();
1130            }
1131    
1132            protected String getImageSrc(
1133                            FileEntry fileEntry, FileVersion fileVersion,
1134                            ThemeDisplay themeDisplay, String queryString)
1135                    throws Exception {
1136    
1137                    StringBundler sb = new StringBundler(4);
1138    
1139                    sb.append(themeDisplay.getPathThemeImages());
1140                    sb.append("/file_system/large/");
1141                    sb.append(getGenericName(fileEntry.getExtension()));
1142                    sb.append(".png");
1143    
1144                    String thumbnailSrc = sb.toString();
1145    
1146                    if (Validator.isNotNull(queryString)) {
1147                            thumbnailSrc = getPreviewURL(
1148                                    fileEntry, fileVersion, themeDisplay, queryString, true, true);
1149                    }
1150    
1151                    return thumbnailSrc;
1152            }
1153    
1154            private static void _populateGenericNamesMap(String genericName) {
1155                    String[] extensions = PropsUtil.getArray(
1156                            PropsKeys.DL_FILE_GENERIC_EXTENSIONS, new Filter(genericName));
1157    
1158                    for (String extension : extensions) {
1159                            _genericNames.put(extension, genericName);
1160                    }
1161            }
1162    
1163            private static final String _DEFAULT_FILE_ICON = "page";
1164    
1165            private static final String _DEFAULT_GENERIC_NAME = "default";
1166    
1167            private static final long _DIVISOR = 256;
1168    
1169            private static final String[] _MICROSOFT_OFFICE_EXTENSIONS = {
1170                    "accda", "accdb", "accdc", "accde", "accdp", "accdr", "accdt", "accdu",
1171                    "acl", "ade", "adp", "asd", "cnv", "crtx", "doc", "docm", "docx", "dot",
1172                    "dotm", "dotx", "grv", "iaf", "laccdb", "maf", "mam", "maq", "mar",
1173                    "mat", "mda", "mdb", "mde", "mdt", "mdw", "mpd", "mpp", "mpt", "oab",
1174                    "obi", "oft", "olm", "one", "onepkg", "ops", "ost", "pa", "pip", "pot",
1175                    "potm", "potx", "ppa", "ppam", "pps", "ppsm", "ppsx", "ppt", "pptm",
1176                    "pptx", "prf", "pst", "pub", "puz", "rpmsg", "sldm", "sldx", "slk",
1177                    "snp", "svd", "thmx", "vdx", "vrge08message", "vsd", "vss", "vst",
1178                    "vsx", "vtx", "wbk", "wll", "xar", "xl", "xla", "xlam", "xlb", "xlc",
1179                    "xll", "xlm", "xls", "xlsb", "xlsm", "xlsx", "xlt", "xltm", "xltx",
1180                    "xlw", "xsf", "xsn"
1181            };
1182    
1183            private static final String _STRUCTURE_KEY_PREFIX = "AUTO_";
1184    
1185            private static final Log _log = LogFactoryUtil.getLog(DLImpl.class);
1186    
1187            private static final Set<String> _allMediaGalleryMimeTypes =
1188                    new TreeSet<>();
1189            private static final Set<String> _fileIcons = new HashSet<>();
1190            private static final Map<String, String> _genericNames = new HashMap<>();
1191    
1192            static {
1193                    _allMediaGalleryMimeTypes.addAll(
1194                            SetUtil.fromArray(
1195                                    PropsUtil.getArray(
1196                                            PropsKeys.DL_FILE_ENTRY_PREVIEW_AUDIO_MIME_TYPES)));
1197                    _allMediaGalleryMimeTypes.addAll(
1198                            SetUtil.fromArray(
1199                                    PropsUtil.getArray(
1200                                            PropsKeys.DL_FILE_ENTRY_PREVIEW_VIDEO_MIME_TYPES)));
1201                    _allMediaGalleryMimeTypes.addAll(
1202                            SetUtil.fromArray(
1203                                    PropsUtil.getArray(
1204                                            PropsKeys.DL_FILE_ENTRY_PREVIEW_IMAGE_MIME_TYPES)));
1205    
1206                    String[] fileIcons = null;
1207    
1208                    try {
1209                            fileIcons = PropsUtil.getArray(PropsKeys.DL_FILE_ICONS);
1210                    }
1211                    catch (Exception e) {
1212                            if (_log.isDebugEnabled()) {
1213                                    _log.debug(e, e);
1214                            }
1215    
1216                            fileIcons = new String[] {StringPool.BLANK};
1217                    }
1218    
1219                    for (int i = 0; i < fileIcons.length; i++) {
1220    
1221                            // Only process non wildcard extensions
1222    
1223                            if (!StringPool.STAR.equals(fileIcons[i])) {
1224    
1225                                    // Strip starting period
1226    
1227                                    String extension = fileIcons[i];
1228    
1229                                    if (extension.length() > 0) {
1230                                            extension = extension.substring(1);
1231                                    }
1232    
1233                                    _fileIcons.add(extension);
1234                            }
1235                    }
1236    
1237                    String[] genericNames = PropsUtil.getArray(
1238                            PropsKeys.DL_FILE_GENERIC_NAMES);
1239    
1240                    for (String genericName : genericNames) {
1241                            _populateGenericNamesMap(genericName);
1242                    }
1243            }
1244    
1245    }