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