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 "icon-file-alt";
471            }
472    
473            @Override
474            public String getFileName(
475                    long groupId, long folderId, String tempFileName) {
476    
477                    String extension = FileUtil.getExtension(tempFileName);
478    
479                    int pos = tempFileName.lastIndexOf(TEMP_RANDOM_SUFFIX);
480    
481                    if (pos != -1) {
482                            tempFileName = tempFileName.substring(0, pos);
483    
484                            if (Validator.isNotNull(extension)) {
485                                    tempFileName = tempFileName + StringPool.PERIOD + extension;
486                            }
487                    }
488    
489                    while (true) {
490                            try {
491                                    DLAppLocalServiceUtil.getFileEntry(
492                                            groupId, folderId, tempFileName);
493    
494                                    StringBundler sb = new StringBundler(5);
495    
496                                    sb.append(FileUtil.stripExtension(tempFileName));
497                                    sb.append(StringPool.DASH);
498                                    sb.append(StringUtil.randomString());
499    
500                                    if (Validator.isNotNull(extension)) {
501                                            sb.append(StringPool.PERIOD);
502                                            sb.append(extension);
503                                    }
504    
505                                    tempFileName = sb.toString();
506                            }
507                            catch (Exception e) {
508                                    break;
509                            }
510                    }
511    
512                    return tempFileName;
513            }
514    
515            @Override
516            public String getGenericName(String extension) {
517                    String genericName = _genericNames.get(extension);
518    
519                    if (genericName == null) {
520                            genericName = _DEFAULT_GENERIC_NAME;
521                    }
522    
523                    return genericName;
524            }
525    
526            @Override
527            public String getImagePreviewURL(
528                            FileEntry fileEntry, FileVersion fileVersion,
529                            ThemeDisplay themeDisplay)
530                    throws Exception {
531    
532                    String previewQueryString = null;
533    
534                    if (PropsValues.DL_FILE_ENTRY_THUMBNAIL_ENABLED) {
535                            if (ImageProcessorUtil.hasImages(fileVersion)) {
536                                    previewQueryString = "&imagePreview=1";
537                            }
538                            else if (PDFProcessorUtil.hasImages(fileVersion)) {
539                                    previewQueryString = "&previewFileIndex=1";
540                            }
541                            else if (VideoProcessorUtil.hasVideo(fileVersion)) {
542                                    previewQueryString = "&videoThumbnail=1";
543                            }
544                    }
545    
546                    return getImageSrc(
547                            fileEntry, fileVersion, themeDisplay, previewQueryString);
548            }
549    
550            @Override
551            public String getImagePreviewURL(
552                            FileEntry fileEntry, ThemeDisplay themeDisplay)
553                    throws Exception {
554    
555                    return getImagePreviewURL(
556                            fileEntry, fileEntry.getFileVersion(), themeDisplay);
557            }
558    
559            @Override
560            public String getPreviewURL(
561                    FileEntry fileEntry, FileVersion fileVersion, ThemeDisplay themeDisplay,
562                    String queryString) {
563    
564                    return getPreviewURL(
565                            fileEntry, fileVersion, themeDisplay, queryString, true, true);
566            }
567    
568            /**
569             * @deprecated As of 6.2.0, replaced by {@link #getPreviewURL(FileEntry,
570             *             FileVersion, ThemeDisplay, String, boolean, boolean)}
571             */
572            @Deprecated
573            @Override
574            public String getPreviewURL(
575                    FileEntry fileEntry, FileVersion fileVersion, ThemeDisplay themeDisplay,
576                    String queryString, boolean appendToken) {
577    
578                    return getPreviewURL(
579                            fileEntry, fileVersion, themeDisplay, queryString, true, true);
580            }
581    
582            @Override
583            public String getPreviewURL(
584                    FileEntry fileEntry, FileVersion fileVersion, ThemeDisplay themeDisplay,
585                    String queryString, boolean appendVersion, boolean absoluteURL) {
586    
587                    StringBundler sb = new StringBundler(17);
588    
589                    if (themeDisplay != null) {
590                            if (absoluteURL) {
591                                    sb.append(themeDisplay.getPortalURL());
592                            }
593                    }
594    
595                    sb.append(PortalUtil.getPathContext());
596                    sb.append("/documents/");
597                    sb.append(fileEntry.getRepositoryId());
598                    sb.append(StringPool.SLASH);
599                    sb.append(fileEntry.getFolderId());
600                    sb.append(StringPool.SLASH);
601    
602                    String fileName = fileEntry.getFileName();
603    
604                    if (fileEntry.isInTrash()) {
605                            fileName = TrashUtil.getOriginalTitle(fileEntry.getFileName());
606                    }
607    
608                    sb.append(HttpUtil.encodeURL(HtmlUtil.unescape(fileName)));
609    
610                    sb.append(StringPool.SLASH);
611                    sb.append(HttpUtil.encodeURL(fileEntry.getUuid()));
612    
613                    if (appendVersion) {
614                            sb.append("?version=");
615                            sb.append(fileVersion.getVersion());
616                    }
617    
618                    if (ImageProcessorUtil.isImageSupported(fileVersion)) {
619                            if (appendVersion) {
620                                    sb.append("&t=");
621                            }
622                            else {
623                                    sb.append("?t=");
624                            }
625    
626                            Date modifiedDate = fileVersion.getModifiedDate();
627    
628                            sb.append(modifiedDate.getTime());
629                    }
630    
631                    sb.append(queryString);
632    
633                    String previewURL = sb.toString();
634    
635                    if ((themeDisplay != null) && themeDisplay.isAddSessionIdToURL()) {
636                            return PortalUtil.getURLWithSessionId(
637                                    previewURL, themeDisplay.getSessionId());
638                    }
639    
640                    return previewURL;
641            }
642    
643            @Override
644            public <T> OrderByComparator<T> getRepositoryModelOrderByComparator(
645                    String orderByCol, String orderByType) {
646    
647                    return getRepositoryModelOrderByComparator(
648                            orderByCol, orderByType, false);
649            }
650    
651            @Override
652            public <T> OrderByComparator<T> getRepositoryModelOrderByComparator(
653                    String orderByCol, String orderByType, boolean orderByModel) {
654    
655                    boolean orderByAsc = true;
656    
657                    if (orderByType.equals("desc")) {
658                            orderByAsc = false;
659                    }
660    
661                    OrderByComparator<T> orderByComparator = null;
662    
663                    if (orderByCol.equals("creationDate")) {
664                            orderByComparator = new RepositoryModelCreateDateComparator<>(
665                                    orderByAsc, orderByModel);
666                    }
667                    else if (orderByCol.equals("downloads")) {
668                            orderByComparator = new RepositoryModelReadCountComparator<>(
669                                    orderByAsc, orderByModel);
670                    }
671                    else if (orderByCol.equals("modifiedDate")) {
672                            orderByComparator = new RepositoryModelModifiedDateComparator<>(
673                                    orderByAsc, orderByModel);
674                    }
675                    else if (orderByCol.equals("size")) {
676                            orderByComparator = new RepositoryModelSizeComparator<>(
677                                    orderByAsc, orderByModel);
678                    }
679                    else {
680                            orderByComparator = new RepositoryModelTitleComparator<>(
681                                    orderByAsc, orderByModel);
682                    }
683    
684                    return orderByComparator;
685            }
686    
687            @Override
688            public String getSanitizedFileName(String title, String extension) {
689                    String fileName = StringUtil.replace(
690                            title, StringPool.SLASH, StringPool.UNDERLINE);
691    
692                    if (Validator.isNotNull(extension) &&
693                            !StringUtil.endsWith(fileName, StringPool.PERIOD + extension)) {
694    
695                            fileName += StringPool.PERIOD + extension;
696                    }
697    
698                    if (fileName.length() > 255) {
699                            int x = fileName.length() - 1;
700    
701                            if (Validator.isNotNull(extension)) {
702                                    x = fileName.lastIndexOf(StringPool.PERIOD);
703                            }
704    
705                            int y = x - (fileName.length() - 255);
706    
707                            fileName = fileName.substring(0, y) + fileName.substring(x);
708                    }
709    
710                    return fileName;
711            }
712    
713            @Override
714            public String getTempFileId(long id, String version) {
715                    return getTempFileId(id, version, null);
716            }
717    
718            @Override
719            public String getTempFileId(long id, String version, String languageId) {
720                    if (Validator.isNull(languageId)) {
721                            return String.valueOf(id).concat(StringPool.PERIOD).concat(version);
722                    }
723    
724                    StringBundler sb = new StringBundler(5);
725    
726                    sb.append(id);
727                    sb.append(StringPool.PERIOD);
728                    sb.append(version);
729                    sb.append(StringPool.PERIOD);
730                    sb.append(languageId);
731    
732                    return sb.toString();
733            }
734    
735            /**
736             * @deprecated As of 7.0.0, replaced by {@link #getThumbnailSrc(FileEntry,
737             *             ThemeDisplay)}
738             */
739            @Deprecated
740            @Override
741            public String getThumbnailSrc(
742                            FileEntry fileEntry, DLFileShortcut dlFileShortcut,
743                            ThemeDisplay themeDisplay)
744                    throws Exception {
745    
746                    return getThumbnailSrc(
747                            fileEntry, fileEntry.getFileVersion(), themeDisplay);
748            }
749    
750            /**
751             * @deprecated As of 7.0.0, replaced by {@link #getThumbnailSrc(FileEntry,
752             *             FileVersion, ThemeDisplay)}
753             */
754            @Deprecated
755            @Override
756            public String getThumbnailSrc(
757                            FileEntry fileEntry, FileVersion fileVersion,
758                            DLFileShortcut dlFileShortcut, ThemeDisplay themeDisplay)
759                    throws Exception {
760    
761                    return getThumbnailSrc(fileEntry, fileVersion, themeDisplay);
762            }
763    
764            @Override
765            public String getThumbnailSrc(
766                            FileEntry fileEntry, FileVersion fileVersion,
767                            ThemeDisplay themeDisplay)
768                    throws Exception {
769    
770                    String thumbnailQueryString = null;
771    
772                    if (PropsValues.DL_FILE_ENTRY_THUMBNAIL_ENABLED) {
773                            if (ImageProcessorUtil.hasImages(fileVersion)) {
774                                    thumbnailQueryString = "&imageThumbnail=1";
775                            }
776                            else if (PDFProcessorUtil.hasImages(fileVersion)) {
777                                    thumbnailQueryString = "&documentThumbnail=1";
778                            }
779                            else if (VideoProcessorUtil.hasVideo(fileVersion)) {
780                                    thumbnailQueryString = "&videoThumbnail=1";
781                            }
782                    }
783    
784                    return getImageSrc(
785                            fileEntry, fileVersion, themeDisplay, thumbnailQueryString);
786            }
787    
788            @Override
789            public String getThumbnailSrc(
790                            FileEntry fileEntry, ThemeDisplay themeDisplay)
791                    throws Exception {
792    
793                    return getThumbnailSrc(
794                            fileEntry, fileEntry.getFileVersion(), themeDisplay);
795            }
796    
797            @Override
798            public String getThumbnailStyle() {
799                    return getThumbnailStyle(true, 0);
800            }
801    
802            @Override
803            public String getThumbnailStyle(boolean max, int margin) {
804                    return getThumbnailStyle(
805                            max, margin,
806                            PrefsPropsUtil.getInteger(
807                                    PropsKeys.DL_FILE_ENTRY_THUMBNAIL_MAX_HEIGHT),
808                            PrefsPropsUtil.getInteger(
809                                    PropsKeys.DL_FILE_ENTRY_THUMBNAIL_MAX_WIDTH));
810            }
811    
812            @Override
813            public String getThumbnailStyle(
814                    boolean max, int margin, int height, int width) {
815    
816                    StringBundler sb = new StringBundler(7);
817    
818                    if (max) {
819                            sb.append("max-height: ");
820                    }
821                    else {
822                            sb.append("height: ");
823                    }
824    
825                    height = height + (2 * margin);
826    
827                    sb.append(height);
828    
829                    if (max) {
830                            sb.append("px; max-width: ");
831                    }
832                    else {
833                            sb.append("px; width: ");
834                    }
835    
836                    width = width + (2 * margin);
837    
838                    sb.append(width);
839    
840                    sb.append("px;");
841    
842                    return sb.toString();
843            }
844    
845            @Override
846            public String getTitleWithExtension(FileEntry fileEntry) {
847                    String title = fileEntry.getTitle();
848                    String extension = fileEntry.getExtension();
849    
850                    return getTitleWithExtension(title, extension);
851            }
852    
853            @Override
854            public String getTitleWithExtension(String title, String extension) {
855                    if (Validator.isNotNull(extension)) {
856                            String periodAndExtension = StringPool.PERIOD.concat(extension);
857    
858                            if (!title.endsWith(periodAndExtension)) {
859                                    title += periodAndExtension;
860                            }
861                    }
862    
863                    return title;
864            }
865    
866            @Override
867            public String getWebDavURL(
868                            ThemeDisplay themeDisplay, Folder folder, FileEntry fileEntry)
869                    throws PortalException {
870    
871                    return getWebDavURL(themeDisplay, folder, fileEntry, false);
872            }
873    
874            @Override
875            public String getWebDavURL(
876                            ThemeDisplay themeDisplay, Folder folder, FileEntry fileEntry,
877                            boolean manualCheckInRequired)
878                    throws PortalException {
879    
880                    return getWebDavURL(
881                            themeDisplay, folder, fileEntry, manualCheckInRequired, false);
882            }
883    
884            @Override
885            public String getWebDavURL(
886                            ThemeDisplay themeDisplay, Folder folder, FileEntry fileEntry,
887                            boolean manualCheckInRequired, boolean openDocumentUrl)
888                    throws PortalException {
889    
890                    StringBundler webDavURL = new StringBundler(8);
891    
892                    boolean secure = false;
893    
894                    if (themeDisplay.isSecure() ||
895                            PropsValues.WEBDAV_SERVLET_HTTPS_REQUIRED) {
896    
897                            secure = true;
898                    }
899    
900                    String portalURL = PortalUtil.getPortalURL(
901                            themeDisplay.getServerName(), themeDisplay.getServerPort(), secure);
902    
903                    webDavURL.append(portalURL);
904    
905                    webDavURL.append(themeDisplay.getPathContext());
906                    webDavURL.append("/webdav");
907    
908                    if (manualCheckInRequired) {
909                            webDavURL.append(MANUAL_CHECK_IN_REQUIRED_PATH);
910                    }
911    
912                    Group group = null;
913    
914                    if (fileEntry != null) {
915                            group = GroupLocalServiceUtil.getGroup(fileEntry.getGroupId());
916                    }
917                    else {
918                            group = themeDisplay.getScopeGroup();
919                    }
920    
921                    webDavURL.append(group.getFriendlyURL());
922                    webDavURL.append("/document_library");
923    
924                    StringBuilder sb = new StringBuilder();
925    
926                    if ((folder != null) &&
927                            (folder.getFolderId() !=
928                                    DLFolderConstants.DEFAULT_PARENT_FOLDER_ID)) {
929    
930                            Folder curFolder = folder;
931    
932                            while (true) {
933                                    sb.insert(0, HttpUtil.encodeURL(curFolder.getName(), true));
934                                    sb.insert(0, StringPool.SLASH);
935    
936                                    if (curFolder.getParentFolderId() ==
937                                                    DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
938    
939                                            break;
940                                    }
941    
942                                    curFolder = DLAppLocalServiceUtil.getFolder(
943                                            curFolder.getParentFolderId());
944                            }
945                    }
946    
947                    if (fileEntry != null) {
948                            sb.append(StringPool.SLASH);
949                            sb.append(DLWebDAVUtil.escapeURLTitle(fileEntry.getTitle()));
950                    }
951    
952                    webDavURL.append(sb.toString());
953    
954                    return webDavURL.toString();
955            }
956    
957            @Override
958            public boolean hasWorkflowDefinitionLink(
959                            long companyId, long groupId, long folderId, long fileEntryTypeId)
960                    throws Exception {
961    
962                    while (folderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
963                            DLFolder dlFolder = DLFolderLocalServiceUtil.fetchDLFolder(
964                                    folderId);
965    
966                            if (dlFolder == null) {
967                                    return false;
968                            }
969    
970                            if (dlFolder.getRestrictionType() !=
971                                            DLFolderConstants.RESTRICTION_TYPE_INHERIT) {
972    
973                                    break;
974                            }
975    
976                            folderId = dlFolder.getParentFolderId();
977                    }
978    
979                    if (WorkflowDefinitionLinkLocalServiceUtil.hasWorkflowDefinitionLink(
980                                    companyId, groupId, DLFolderConstants.getClassName(), folderId,
981                                    fileEntryTypeId) ||
982                            WorkflowDefinitionLinkLocalServiceUtil.hasWorkflowDefinitionLink(
983                                    companyId, groupId, DLFolderConstants.getClassName(), folderId,
984                                    DLFileEntryTypeConstants.FILE_ENTRY_TYPE_ID_ALL)) {
985    
986                            return true;
987                    }
988    
989                    return false;
990            }
991    
992            @Override
993            public boolean isAutoGeneratedDLFileEntryTypeDDMStructureKey(
994                    String ddmStructureKey) {
995    
996                    if (ddmStructureKey.startsWith(_STRUCTURE_KEY_PREFIX)) {
997                            return true;
998                    }
999    
1000                    return false;
1001            }
1002    
1003            @Override
1004            public boolean isOfficeExtension(String extension) {
1005                    return ArrayUtil.contains(_MICROSOFT_OFFICE_EXTENSIONS, extension);
1006            }
1007    
1008            @Override
1009            public boolean isSubscribedToFileEntryType(
1010                    long companyId, long groupId, long userId, long fileEntryTypeId) {
1011    
1012                    if (fileEntryTypeId ==
1013                                    DLFileEntryTypeConstants.FILE_ENTRY_TYPE_ID_BASIC_DOCUMENT) {
1014    
1015                            fileEntryTypeId = groupId;
1016                    }
1017    
1018                    return SubscriptionLocalServiceUtil.isSubscribed(
1019                            companyId, userId, DLFileEntryType.class.getName(),
1020                            fileEntryTypeId);
1021            }
1022    
1023            @Override
1024            public boolean isSubscribedToFolder(
1025                            long companyId, long groupId, long userId, long folderId)
1026                    throws PortalException {
1027    
1028                    return isSubscribedToFolder(companyId, groupId, userId, folderId, true);
1029            }
1030    
1031            @Override
1032            public boolean isSubscribedToFolder(
1033                            long companyId, long groupId, long userId, long folderId,
1034                            boolean recursive)
1035                    throws PortalException {
1036    
1037                    List<Long> ancestorFolderIds = new ArrayList<>();
1038    
1039                    if (folderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
1040                            Folder folder = DLAppLocalServiceUtil.getFolder(folderId);
1041    
1042                            ancestorFolderIds.add(folderId);
1043    
1044                            if (recursive) {
1045                                    ancestorFolderIds.addAll(folder.getAncestorFolderIds());
1046    
1047                                    ancestorFolderIds.add(groupId);
1048                            }
1049                    }
1050                    else {
1051                            ancestorFolderIds.add(groupId);
1052                    }
1053    
1054                    long[] folderIdsArray = ArrayUtil.toLongArray(ancestorFolderIds);
1055    
1056                    return SubscriptionLocalServiceUtil.isSubscribed(
1057                            companyId, userId, DLFolder.class.getName(), folderIdsArray);
1058            }
1059    
1060            @Override
1061            public boolean isValidVersion(String version) {
1062                    if (version.equals(DLFileEntryConstants.PRIVATE_WORKING_COPY_VERSION)) {
1063                            return true;
1064                    }
1065    
1066                    String[] versionParts = StringUtil.split(version, StringPool.PERIOD);
1067    
1068                    if (versionParts.length != 2) {
1069                            return false;
1070                    }
1071    
1072                    if (Validator.isNumber(versionParts[0]) &&
1073                            Validator.isNumber(versionParts[1])) {
1074    
1075                            return true;
1076                    }
1077    
1078                    return false;
1079            }
1080    
1081            @Override
1082            public void startWorkflowInstance(
1083                            long userId, DLFileVersion dlFileVersion, String syncEventType,
1084                            ServiceContext serviceContext)
1085                    throws PortalException {
1086    
1087                    Map<String, Serializable> workflowContext = new HashMap<>();
1088    
1089                    workflowContext.put(
1090                            WorkflowConstants.CONTEXT_URL,
1091                            getEntryURL(dlFileVersion, serviceContext));
1092                    workflowContext.put("event", syncEventType);
1093    
1094                    WorkflowHandlerRegistryUtil.startWorkflowInstance(
1095                            dlFileVersion.getCompanyId(), dlFileVersion.getGroupId(), userId,
1096                            DLFileEntryConstants.getClassName(),
1097                            dlFileVersion.getFileVersionId(), dlFileVersion, serviceContext,
1098                            workflowContext);
1099            }
1100    
1101            protected String getEntryURL(
1102                            DLFileVersion dlFileVersion, ServiceContext serviceContext)
1103                    throws PortalException {
1104    
1105                    if (Validator.equals(
1106                                    serviceContext.getCommand(), Constants.ADD_WEBDAV) ||
1107                            Validator.equals(
1108                                    serviceContext.getCommand(), Constants.UPDATE_WEBDAV)) {
1109    
1110                            return serviceContext.getPortalURL() +
1111                                    serviceContext.getCurrentURL();
1112                    }
1113    
1114                    String entryURL = GetterUtil.getString(
1115                            serviceContext.getAttribute("entryURL"));
1116    
1117                    if (Validator.isNotNull(entryURL)) {
1118                            return entryURL;
1119                    }
1120    
1121                    HttpServletRequest request = serviceContext.getRequest();
1122    
1123                    if ((request == null) || (serviceContext.getThemeDisplay() == null)) {
1124                            return StringPool.BLANK;
1125                    }
1126    
1127                    PortletURL portletURL = null;
1128    
1129                    long plid = serviceContext.getPlid();
1130                    long controlPanelPlid = PortalUtil.getControlPanelPlid(
1131                            serviceContext.getCompanyId());
1132                    String portletId = PortletProviderUtil.getPortletId(
1133                            FileEntry.class.getName(), PortletProvider.Action.VIEW);
1134    
1135                    if ((plid == controlPanelPlid) ||
1136                            (plid == LayoutConstants.DEFAULT_PLID)) {
1137    
1138                            portletURL = PortalUtil.getControlPanelPortletURL(
1139                                    request, portletId, PortletRequest.RENDER_PHASE);
1140                    }
1141                    else {
1142                            portletURL = PortletURLFactoryUtil.create(
1143                                    request, portletId, plid, PortletRequest.RENDER_PHASE);
1144                    }
1145    
1146                    portletURL.setParameter(
1147                            "mvcRenderCommandName", "/document_library/view_file_entry");
1148                    portletURL.setParameter(
1149                            "fileEntryId", String.valueOf(dlFileVersion.getFileEntryId()));
1150    
1151                    return portletURL.toString();
1152            }
1153    
1154            protected String getImageSrc(
1155                            FileEntry fileEntry, FileVersion fileVersion,
1156                            ThemeDisplay themeDisplay, String queryString)
1157                    throws Exception {
1158    
1159                    StringBundler sb = new StringBundler(4);
1160    
1161                    sb.append(themeDisplay.getPathThemeImages());
1162                    sb.append("/file_system/large/");
1163                    sb.append(getGenericName(fileEntry.getExtension()));
1164                    sb.append(".png");
1165    
1166                    String thumbnailSrc = sb.toString();
1167    
1168                    if (Validator.isNotNull(queryString)) {
1169                            thumbnailSrc = getPreviewURL(
1170                                    fileEntry, fileVersion, themeDisplay, queryString, true, true);
1171                    }
1172    
1173                    return thumbnailSrc;
1174            }
1175    
1176            private static void _populateGenericNamesMap(String genericName) {
1177                    String[] extensions = PropsUtil.getArray(
1178                            PropsKeys.DL_FILE_GENERIC_EXTENSIONS, new Filter(genericName));
1179    
1180                    for (String extension : extensions) {
1181                            _genericNames.put(extension, genericName);
1182                    }
1183            }
1184    
1185            private static final String _DEFAULT_FILE_ICON = "page";
1186    
1187            private static final String _DEFAULT_GENERIC_NAME = "default";
1188    
1189            private static final long _DIVISOR = 256;
1190    
1191            private static final String[] _MICROSOFT_OFFICE_EXTENSIONS = {
1192                    "accda", "accdb", "accdc", "accde", "accdp", "accdr", "accdt", "accdu",
1193                    "acl", "ade", "adp", "asd", "cnv", "crtx", "doc", "docm", "docx", "dot",
1194                    "dotm", "dotx", "grv", "iaf", "laccdb", "maf", "mam", "maq", "mar",
1195                    "mat", "mda", "mdb", "mde", "mdt", "mdw", "mpd", "mpp", "mpt", "oab",
1196                    "obi", "oft", "olm", "one", "onepkg", "ops", "ost", "pa", "pip", "pot",
1197                    "potm", "potx", "ppa", "ppam", "pps", "ppsm", "ppsx", "ppt", "pptm",
1198                    "pptx", "prf", "pst", "pub", "puz", "rpmsg", "sldm", "sldx", "slk",
1199                    "snp", "svd", "thmx", "vdx", "vrge08message", "vsd", "vss", "vst",
1200                    "vsx", "vtx", "wbk", "wll", "xar", "xl", "xla", "xlam", "xlb", "xlc",
1201                    "xll", "xlm", "xls", "xlsb", "xlsm", "xlsx", "xlt", "xltm", "xltx",
1202                    "xlw", "xsf", "xsn"
1203            };
1204    
1205            private static final String _STRUCTURE_KEY_PREFIX = "AUTO_";
1206    
1207            private static final Log _log = LogFactoryUtil.getLog(DLImpl.class);
1208    
1209            private static final Set<String> _allMediaGalleryMimeTypes =
1210                    new TreeSet<>();
1211            private static final Set<String> _fileIcons = new HashSet<>();
1212            private static final Map<String, String> _genericNames = new HashMap<>();
1213    
1214            static {
1215                    _allMediaGalleryMimeTypes.addAll(
1216                            SetUtil.fromArray(
1217                                    PropsUtil.getArray(
1218                                            PropsKeys.DL_FILE_ENTRY_PREVIEW_AUDIO_MIME_TYPES)));
1219                    _allMediaGalleryMimeTypes.addAll(
1220                            SetUtil.fromArray(
1221                                    PropsUtil.getArray(
1222                                            PropsKeys.DL_FILE_ENTRY_PREVIEW_VIDEO_MIME_TYPES)));
1223                    _allMediaGalleryMimeTypes.addAll(
1224                            SetUtil.fromArray(
1225                                    PropsUtil.getArray(
1226                                            PropsKeys.DL_FILE_ENTRY_PREVIEW_IMAGE_MIME_TYPES)));
1227    
1228                    String[] fileIcons = null;
1229    
1230                    try {
1231                            fileIcons = PropsUtil.getArray(PropsKeys.DL_FILE_ICONS);
1232                    }
1233                    catch (Exception e) {
1234                            if (_log.isDebugEnabled()) {
1235                                    _log.debug(e, e);
1236                            }
1237    
1238                            fileIcons = new String[] {StringPool.BLANK};
1239                    }
1240    
1241                    for (int i = 0; i < fileIcons.length; i++) {
1242    
1243                            // Only process non wildcard extensions
1244    
1245                            if (!StringPool.STAR.equals(fileIcons[i])) {
1246    
1247                                    // Strip starting period
1248    
1249                                    String extension = fileIcons[i];
1250    
1251                                    if (extension.length() > 0) {
1252                                            extension = extension.substring(1);
1253                                    }
1254    
1255                                    _fileIcons.add(extension);
1256                            }
1257                    }
1258    
1259                    String[] genericNames = PropsUtil.getArray(
1260                            PropsKeys.DL_FILE_GENERIC_NAMES);
1261    
1262                    for (String genericName : genericNames) {
1263                            _populateGenericNamesMap(genericName);
1264                    }
1265            }
1266    
1267    }